<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="../assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Peek Read Info (Posts about security)</title><link>https://peekread.info/</link><description></description><atom:link href="https://peekread.info/tags/security.xml" rel="self" type="application/rss+xml"></atom:link><language>en</language><copyright>Contents © 2024 &lt;a href="mailto:dugite-code@peekread.info"&gt;Dugite-Code&lt;/a&gt; 
&lt;a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/"&gt;
&lt;img alt="Creative Commons License BY-SA"
width="88px" height="31px" style="border-width:0; margin-bottom:12px;"
src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png"&gt;&lt;/a&gt;</copyright><lastBuildDate>Wed, 14 Feb 2024 06:33:09 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>Authentik Gotifiy Login Notifications</title><link>https://peekread.info/tech/20220506-authentik-gotifiy-login-notifications/</link><dc:creator>Dugite-Code</dc:creator><description>&lt;p&gt;&lt;/p&gt;&lt;div class="d-flex position-relative pt-3 pb-3"&gt;
    &lt;div class="flex-shrink-0 me-3"&gt;
        &lt;img data-pagefind-meta="image[src], image_alt[alt]" style="height:89px;" src="https://peekread.info/images/2022/0428-sso-with-authentik/image01.png" alt="SSO all the things"&gt;
    &lt;/div&gt;
    &lt;div&gt;
        &lt;p class="mt-3"&gt;&lt;/p&gt;&lt;p&gt;Continuing with my journy of utilising Authentik for my SSO. After reading a rather good comment by &lt;a href="https://www.reddit.com/r/selfhosted/comments/ub7dvb/authentik_or_keycloak/i62o6hf/"&gt;/u/internallogictv&lt;/a&gt; over on the reddit &lt;a href="https://www.reddit.com/r/selfhosted/"&gt;/r/selfhosted&lt;/a&gt;, I wanted to add a few more protections. The simplest of which is to send myself a notification whenever a login or a failed login occurs.&lt;/p&gt;
    &lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;Step 1&lt;/h2&gt;
&lt;p&gt;First things first we create a new application in gotify in order to generate a token for authentik use. Select the &lt;code&gt;Apps&lt;/code&gt; tab and press the &lt;code&gt;Create Application&lt;/code&gt; button.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Gotify create an application" class="img-fluid dark-image mx-auto d-block text-center text-light" loading="lazy" max-height="185" max-width="800" src="https://peekread.info/images/2022/0506-authentik-gotifiy-login-notifications/image01.png"&gt;&lt;/p&gt;
&lt;h2&gt;Step 2&lt;/h2&gt;
&lt;p&gt;Create a new gotify property mapping in the &lt;code&gt;Admin Interface -&amp;gt; Customisation -&amp;gt; Property Mappings&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" class="img-fluid dark-image mx-auto d-block text-center text-light" loading="lazy" max-height="426" max-width="800" src="https://peekread.info/images/2022/0506-authentik-gotifiy-login-notifications/image02.png"&gt;&lt;/p&gt;
&lt;p&gt;I've built this so a login failed is set to the maximum gotify priority level regardless of the user group. For successful logins I divide the levels based on the group gotify-users. I algo create a geo uri for mapping applications on android. You will be able to click the notification and it will open the city co-ordinates, although you may have to skip this if you don't have the &lt;code&gt;geoipupdate&lt;/code&gt; container configured.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Get the login failed username&lt;/span&gt;
    &lt;span class="n"&gt;event_user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Get the login succeeded username&lt;/span&gt;
    &lt;span class="n"&gt;event_user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"login_failed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;priority&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;
    &lt;span class="n"&gt;severity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"warning"&lt;/span&gt;
&lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;ak_is_group_member&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;ak_user_by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;event_user&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"gotify-users"&lt;/span&gt; &lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="c1"&gt;# Check if the user belongs to group&lt;/span&gt;
    &lt;span class="n"&gt;priority&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;severity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;severity&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# default notification settings&lt;/span&gt;
    &lt;span class="n"&gt;priority&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="n"&gt;severity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;severity&lt;/span&gt;

&lt;span class="c1"&gt;# Build a geo uri for opening a mapping applications from the gotify notification.&lt;/span&gt;
&lt;span class="n"&gt;geo_uri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;"geo:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'geo'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;'lat'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'geo'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;'long'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;?q=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'geo'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;'lat'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'geo'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;'long'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;severity&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; from authentik &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'_'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;' '&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;capitalize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;"New &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'_'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;' '&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; for &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;event_user&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; was detected coming from &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'geo'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;'city'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'geo'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;'country'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; from the IP address: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;client_ip&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;capitalize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Build the gotify payload&lt;/span&gt;
&lt;span class="n"&gt;gotify_payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"priority"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;priority&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"extras"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s2"&gt;"client::notification"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s2"&gt;"click"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s2"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;geo_uri&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;gotify_payload&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Step 3&lt;/h2&gt;
&lt;p&gt;Create a new notification transport &lt;code&gt;Admin Interface -&amp;gt; Events -&amp;gt;  Notification Transports&lt;/code&gt; using &lt;code&gt;Webhook (generic)&lt;/code&gt; your gotify message url with the token created in step one &lt;code&gt;https://example.tld/gotify/message?token=yourtokenhere&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="" class="img-fluid dark-image mx-auto d-block text-center text-light" loading="lazy" max-height="360" max-width="799" src="https://peekread.info/images/2022/0506-authentik-gotifiy-login-notifications/image03.png"&gt;&lt;/p&gt;
&lt;h2&gt;Step 4&lt;/h2&gt;
&lt;p&gt;Finally we create the notification rule that actually calls the Notification transport. &lt;code&gt;Admin Interface -&amp;gt; Events -&amp;gt;  Notification Rules&lt;/code&gt; Create a new rule &lt;code&gt;login-notification&lt;/code&gt; sending to the group of your choice (This dosn't really matter but it will display an ugly json string as notification on the web UI). Select the &lt;code&gt;Gotify&lt;/code&gt; notification transport you created and set the Severity to &lt;code&gt;Notice&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" class="img-fluid dark-image mx-auto d-block text-center text-light" loading="lazy" max-height="489" max-width="798" src="https://peekread.info/images/2022/0506-authentik-gotifiy-login-notifications/image04.png"&gt;&lt;/p&gt;
&lt;p&gt;Now we have to create the policies &lt;code&gt;authentik-core-login&lt;/code&gt; and &lt;code&gt;authentik-core-login-failed&lt;/code&gt; to the event. Expand the &lt;code&gt;login-notification&lt;/code&gt; event and press &lt;code&gt;Create Policy&lt;/code&gt;. Select &lt;code&gt;Event Matcher Policy&lt;/code&gt;, name it &lt;code&gt;authentik-core-login&lt;/code&gt; enable the &lt;code&gt;Execution Logging&lt;/code&gt; option, select the &lt;code&gt;Login&lt;/code&gt; action and &lt;code&gt;authentik Core&lt;/code&gt; App. Finish and repeat for the &lt;code&gt;Login Failed&lt;/code&gt; action.&lt;/p&gt;
&lt;p&gt;Now you should be receiving Login and Login Failed notifications from your Authentik instance over Gotify. I Hope I'll be able to update this to pull different tokens from the user/group attributes in the future to better separate notifications to individual users/admins.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" class="img-fluid dark-image mx-auto d-block text-center text-light" loading="lazy" max-height="294" max-width="797" src="https://peekread.info/images/2022/0506-authentik-gotifiy-login-notifications/image05.png"&gt;&lt;/p&gt;</description><category>authentik</category><category>gotify</category><category>notifications</category><category>security</category><category>SSO</category><guid>https://peekread.info/tech/20220506-authentik-gotifiy-login-notifications/</guid><pubDate>Thu, 05 May 2022 16:00:00 GMT</pubDate></item><item><title>Node-Red SSO with Authentik</title><link>https://peekread.info/tech/20220429-node-red-sso-with-authentik/</link><dc:creator>Dugite-Code</dc:creator><description>&lt;p&gt;&lt;/p&gt;&lt;div class="d-flex position-relative pt-3 pb-3"&gt;
    &lt;div class="flex-shrink-0 me-3"&gt;
        &lt;img data-pagefind-meta="image[src], image_alt[alt]" style="height:89px;" src="https://peekread.info/images/2019/1122-node-red-website-alerts/image01.png" alt="Node-RED is a flow-based programming tool, originally developed by IBM’s Emerging Technology Services team and now a part of the JS Foundation."&gt;
    &lt;/div&gt;
    &lt;div&gt;
        &lt;p class="mt-3"&gt;&lt;/p&gt;&lt;p&gt;Following my &lt;a href="https://peekread.info/tech/20220325-sso-with-authentik/"&gt;last post regarding SSO with Authentik&lt;/a&gt; I thought I should post my passportjs configuration for Node-Red and OpenidConnect. Currently User accounts work, however I haven't gotten group based permissions setup yet.&lt;/p&gt;
    &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Note This guide is based off the &lt;a href="https://goauthentik.io/integrations/services/gitea/"&gt;Gitea integration guide from the Authentik docs.&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Preparation&lt;/h3&gt;
&lt;p&gt;The following placeholders will be used:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;authentik.company&lt;/code&gt; is the FQDN of authentik.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;nodered.company&lt;/code&gt; is the FQDN of nodered.&lt;/p&gt;
&lt;h3&gt;Step 1&lt;/h3&gt;
&lt;p&gt;In authentik, create an OAuth2/OpenID Provider (under Resources/Providers) with these settings:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;note&lt;/p&gt;
&lt;p&gt;Only settings that have been modified from default have been listed.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;Protocol Settings&lt;/h4&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nodered&lt;/span&gt;
&lt;span class="n"&gt;Signing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Select&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;any&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;available&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;note&lt;/p&gt;
&lt;p&gt;Take note of the Client ID and Client Secret, you'll need to give them to nodered in Step 3.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Step 2&lt;/h3&gt;
&lt;p&gt;In authentik, create an application (under Resources/Applications) which uses this provider. Optionally apply access restrictions to the application using policy bindings.
note&lt;/p&gt;
&lt;p&gt;Only settings that have been modified from default have been listed.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nodered&lt;/span&gt;
&lt;span class="n"&gt;Slug&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nodered&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;slug&lt;/span&gt;
&lt;span class="n"&gt;Provider&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nodered&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Step 3&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;note&lt;/p&gt;
&lt;p&gt;We are assuming node-red is installed under docker&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Navigate to the node-red data volume &lt;code&gt;data/node_modules/&lt;/code&gt;. Alternatively enter the docker container &lt;code&gt;sudo docker exec -it nodered bash&lt;/code&gt; and cd &lt;code&gt;/data/node_modules&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Use npm to install passport-openidconnect npm install passport-openidconnect&lt;/p&gt;
&lt;p&gt;Edit the node-red settings.js file &lt;code&gt;/data/settings.js&lt;/code&gt;&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nx"&gt;adminAuth&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"strategy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="nx"&gt;strategy&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"openidconnect"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'Sign in with authentik'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;icon&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"fa-cloud"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;strategy&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"passport-openidconnect"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;Strategy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nx"&gt;issuer&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'https://authentik.company/application/o/&amp;lt;application-slug&amp;gt;/'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nx"&gt;authorizationURL&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'https://authentik.company/application/o/authorize/'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nx"&gt;tokenURL&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'https://authentik.company/application/o/token/'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nx"&gt;userInfoURL&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'https://authentik.company/application/o/userinfo/'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nx"&gt;clientID&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'&amp;lt;Client ID (Key): Step 2&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nx"&gt;clientSecret&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'&amp;lt;Client Secret: Step 2&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nx"&gt;callbackURL&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'https://nodered.company/auth/strategy/callback/'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'email'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'profile'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'openid'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nx"&gt;proxy&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;verify&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;issuer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;done&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nx"&gt;done&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;permissions&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;</description><category>authentik</category><category>node-red</category><category>security</category><category>SSO</category><guid>https://peekread.info/tech/20220429-node-red-sso-with-authentik/</guid><pubDate>Thu, 28 Apr 2022 16:00:00 GMT</pubDate></item><item><title>SSO with Authentik</title><link>https://peekread.info/tech/20220325-sso-with-authentik/</link><dc:creator>Dugite-Code</dc:creator><description>&lt;p&gt;&lt;/p&gt;&lt;div class="d-flex position-relative pt-3 pb-3"&gt;
    &lt;div class="flex-shrink-0 me-3"&gt;
        &lt;img data-pagefind-meta="image[src], image_alt[alt]" style="height:89px;" src="https://peekread.info/images/2022/0428-sso-with-authentik/image01.png" alt="SSO all the things"&gt;
    &lt;/div&gt;
    &lt;div&gt;
        &lt;p class="mt-3"&gt;&lt;/p&gt;&lt;p&gt;A while back I wrote about minimising my attack surface by utilising default deny and whitelists in Nginx. Now I've gotten into the weeds with authentication and deployed an SSO (Signle sign-on) service on my selfhosted infrastructure.&lt;/p&gt;
    &lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;What is Authentik?&lt;/h3&gt;
&lt;p&gt;Authentik is a SSO (Single Sign on) provider, much like with Google's services you sign in once and then you can access all your services. This has been a big bugbear with selfhosted applications, with &lt;a href="https://gitlab.com/dugite-code/rcmail_ttrss"&gt;Roundcubemail TTRSS plugin&lt;/a&gt;, &lt;a href="https://github.com/dugite-code/auth_rcmail"&gt;auto authentication for Tiny Tiny RSS against an IMAP Server&lt;/a&gt; and &lt;a href="https://github.com/dugite-code/codiad-imap_auth"&gt;Codiad External Authentication via IMAP &lt;/a&gt; to name a few work arounds to the issue I have hacked together over the years.&lt;/p&gt;
&lt;p&gt;Most importantly for my use case is the single pane of glass to access my services:&lt;/p&gt;
&lt;p&gt;&lt;img alt="A nice dashboard really brings it all together" class="img-fluid dark-image mx-auto d-block text-center text-light" loading="lazy" max-width="1110" src="https://peekread.info/images/2022/0428-sso-with-authentik/a-nice-dashboard-realy-brings-it-all-together.png"&gt;&lt;/p&gt;
&lt;h3&gt;The Issues&lt;/h3&gt;
&lt;p&gt;Introducing a SSO system introduces complexity and potential problems so it's not all smooth sailing, passwords are a thing still as they are simple and reliable and understandable.&lt;/p&gt;
&lt;h4&gt;New Project new problems, limited reviews&lt;/h4&gt;
&lt;p&gt;Authentik's first beta release was in Jan 2020 so it's very new and has had a few teething issues and quite a few bugs. I highly recommend utilising additional security methods in front of authentik (IDS/IPS, Geo Blocking and ideally using a VPN to access) until it reaches maturity.&lt;/p&gt;
&lt;h4&gt;Poor Documentation&lt;/h4&gt;
&lt;p&gt;Quite frankly the documentation isn't great if you are attempting to figure out &lt;strong&gt;HOW&lt;/strong&gt; it’s supposed to work. Thankfully they have integration guides included in the docs that covers the gaps, so some reading between the lines is needed for a while yet.&lt;/p&gt;
&lt;h4&gt;Limited compatibility&lt;/h4&gt;
&lt;p&gt;Not everything has SSO support (SAML, Oauth/OpenidConnect or reverse Proxy Authentication), thankfully this isn't as hard to deal with as it once was:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://discourse.nodered.org/t/nextcloud-oauth-2-login/4403/8?u=dugite-code"&gt;My post on adding openidconnect to node-red&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ArchiveBox/ArchiveBox/pull/866#discussion_r839151488"&gt;My minor contribution to the Reverse Proxy authentication pull request for ArchiveBox&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main issue I have faced is with HomeAssistant. The developers have been reluctant/resistant to adding additional authentication methods to the project. There is the &lt;a href="https://github.com/BeryJu/hass-auth-header"&gt;hass-auth-header&lt;/a&gt; project created by the developer of Authentik, however the HomeAssistant Android app is frustratingly a &lt;a href="https://github.com/home-assistant/android/issues/1438"&gt;major sticking point&lt;/a&gt;.&lt;/p&gt;</description><category>authentication</category><category>authentik</category><category>rss</category><category>security</category><category>SSO</category><guid>https://peekread.info/tech/20220325-sso-with-authentik/</guid><pubDate>Thu, 24 Mar 2022 16:00:00 GMT</pubDate></item><item><title>I shouldn't use sudo nano</title><link>https://peekread.info/tech/20210727-i-shouldn-t-use-sudo-nano/</link><dc:creator>Dugite-Code</dc:creator><description>&lt;p&gt;Over on &lt;a href="https://www.reddit.com/r/linux"&gt;/r/linux&lt;/a&gt; a user going by &lt;a href="https://www.reddit.com/user/AlternOSx"&gt;/u/AlternOSx&lt;/a&gt; posted a short You should Know:  &lt;a href="https://www.reddit.com/r/linux/comments/osah05/ysk_do_not_use_sudo_vimnanoemacs_to_edit_a_file/"&gt;YSK : Do not use 'sudo vim/nano/emacs..' to edit a file. Instead, set your $EDITOR and use sudoedit or sudo -e.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Long story short &lt;code&gt;sudoedit&lt;/code&gt; copies the file you want to edit to &lt;code&gt;/tmp/file.xxx&lt;/code&gt; and then opens it with an &lt;strong&gt;unprivileged&lt;/strong&gt; instance of your editor of choice. It then overwrites the source file when you are finished editing, protecting from accidental privilege escalation of commands through your text editor.&lt;/p&gt;
&lt;p&gt;Knowing this I came up with a quick way to enforce this best practice by added this function into my &lt;code&gt;.bashrc&lt;/code&gt; file. Hopefully I can retrain myself not to use &lt;code&gt;sudo nano&lt;/code&gt; all the time.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="cp"&gt;# Define the default editor in this case nano.&lt;/span&gt;
&lt;span class="n"&gt;EDITOR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;nano&lt;/span&gt;

&lt;span class="cp"&gt;# Catch calls to sudo.&lt;/span&gt;
&lt;span class="n"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sudo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;$1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"$EDITOR"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;]];&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="cp"&gt;# The editor has been called&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"$2"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="cp"&gt;# If the file is writable by the current user just use the editor as normal.&lt;/span&gt;

&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;$EDITOR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"$2"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="cp"&gt;# The file is not writable use sudoedit.&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sudoedit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"$2"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;fi&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="cp"&gt;# Use sudo as normal.&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;bin&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;sudo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"$@"&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;fi&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;</description><category>linux</category><category>security</category><category>sudo</category><guid>https://peekread.info/tech/20210727-i-shouldn-t-use-sudo-nano/</guid><pubDate>Mon, 26 Jul 2021 16:00:00 GMT</pubDate></item><item><title>Minimizing my selfhosted attack surface</title><link>https://peekread.info/tech/20210318-minimizing-my-selfhosted-attack-surface/</link><dc:creator>Dugite-Code</dc:creator><description>&lt;p&gt;&lt;/p&gt;&lt;div class="d-flex position-relative pt-3 pb-3"&gt;
    &lt;div class="flex-shrink-0 me-3"&gt;
        &lt;img data-pagefind-meta="image[src], image_alt[alt]" style="height:89px;" src="https://peekread.info/images/2019/0625-server-set-up-checklist/image01.png" alt="Tweeking my linux server"&gt;
    &lt;/div&gt;
    &lt;div&gt;
        &lt;p class="mt-3"&gt;&lt;/p&gt;&lt;p&gt;I'm always fairly wary of opening my selfhosted services up to the internet, just how sure am I that the developer has done the right due-diligence? Thankfully it's relatively simple to at least limit parts of a service accessible to the open internet with Nginx and &lt;code&gt;allow&lt;/code&gt; and &lt;code&gt;deny&lt;/code&gt; options.&lt;/p&gt;
    &lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h3&gt;Update&lt;/h3&gt;
&lt;p&gt;Note: If you want a docker container to access a protected service you will have to set the subnet in your docker-compose file as below:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;networks:
&lt;span class="w"&gt;  &lt;/span&gt;node-red-network:
&lt;span class="w"&gt;    &lt;/span&gt;ipam:
&lt;span class="w"&gt;      &lt;/span&gt;config:
&lt;span class="w"&gt;        &lt;/span&gt;-&lt;span class="w"&gt; &lt;/span&gt;subnet:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"172.16.0.0/24"&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Update 2&lt;/h3&gt;
&lt;p&gt;A more generic change you can do is set the default address pools in docker's &lt;code&gt;/etc/docker/daemon.json&lt;/code&gt; file. You then just have to whitelist &lt;code&gt;172.16.0.0/16&lt;/code&gt; subnets&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s2"&gt;"default-address-pools"&lt;/span&gt;:
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"base"&lt;/span&gt;:&lt;span class="s2"&gt;"172.16.0.0/16"&lt;/span&gt;,&lt;span class="s2"&gt;"size"&lt;/span&gt;:24&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;p&gt;First you should store this in a file, that way you can then include it multiple times, this will make it trivial to update in the future. Create the file &lt;code&gt;include_whitelist&lt;/code&gt; in your nginx folder, adding your own allow options between &lt;code&gt;satisfy any;&lt;/code&gt; and &lt;code&gt;deny all;&lt;/code&gt;.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;satisfy&lt;span class="w"&gt; &lt;/span&gt;any&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;# allow localhost&lt;/span&gt;
allow&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;127&lt;/span&gt;.0.0.1&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;# allow a single address&lt;/span&gt;
&lt;span class="c1"&gt;# allow 000.000.000.000;&lt;/span&gt;

&lt;span class="c1"&gt;# allow LAN network&lt;/span&gt;
allow&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;192&lt;/span&gt;.168.0.0/24&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;# allow WLAN network&lt;/span&gt;
allow&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;192&lt;/span&gt;.168.2.0/24&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;# allow VPN network&lt;/span&gt;
allow&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.1.4.0/24&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;# drop rest of the world&lt;/span&gt;
deny&lt;span class="w"&gt; &lt;/span&gt;all&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You then have to include the file in your nginx config. Here I am using TT-RSS as an example, Note that I'm excluding the API and the public.php by having it in a separate location block without including the &lt;code&gt;include_whitelist&lt;/code&gt;. This allows me to keep accessing TT-RSS on my mobile phone through the mobile application.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="w"&gt;  &lt;/span&gt;location&lt;span class="w"&gt; &lt;/span&gt;^~&lt;span class="w"&gt; &lt;/span&gt;/tt-rss/&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;include&lt;span class="w"&gt; &lt;/span&gt;/etc/nginx/include_whitelist&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;      &lt;/span&gt;access_log&lt;span class="w"&gt; &lt;/span&gt;off&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;proxy_set_header&lt;span class="w"&gt; &lt;/span&gt;Host&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;proxy_set_header&lt;span class="w"&gt; &lt;/span&gt;X-Real-IP&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$remote_addr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;proxy_set_header&lt;span class="w"&gt; &lt;/span&gt;X-Forwarded-For&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$remote_addr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;proxy_set_header&lt;span class="w"&gt; &lt;/span&gt;X-Forwarded-Proto&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$scheme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;proxy_pass&lt;span class="w"&gt; &lt;/span&gt;http://127.0.0.1:8280/tt-rss/&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;location&lt;span class="w"&gt; &lt;/span&gt;^~&lt;span class="w"&gt; &lt;/span&gt;/tt-rss/api&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;

&lt;span class="w"&gt;      &lt;/span&gt;access_log&lt;span class="w"&gt; &lt;/span&gt;off&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;proxy_set_header&lt;span class="w"&gt; &lt;/span&gt;Host&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;proxy_set_header&lt;span class="w"&gt; &lt;/span&gt;X-Real-IP&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$remote_addr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;proxy_set_header&lt;span class="w"&gt; &lt;/span&gt;X-Forwarded-For&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$remote_addr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;proxy_set_header&lt;span class="w"&gt; &lt;/span&gt;X-Forwarded-Proto&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$scheme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;proxy_pass&lt;span class="w"&gt; &lt;/span&gt;http://127.0.0.1:8280/tt-rss/api&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;location&lt;span class="w"&gt; &lt;/span&gt;^~&lt;span class="w"&gt; &lt;/span&gt;/tt-rss/public.php&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;

&lt;span class="w"&gt;      &lt;/span&gt;proxy_set_header&lt;span class="w"&gt; &lt;/span&gt;Host&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;proxy_set_header&lt;span class="w"&gt; &lt;/span&gt;X-Real-IP&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$remote_addr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;proxy_set_header&lt;span class="w"&gt; &lt;/span&gt;X-Forwarded-For&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$remote_addr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;proxy_set_header&lt;span class="w"&gt; &lt;/span&gt;X-Forwarded-Proto&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$scheme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;proxy_pass&lt;span class="w"&gt; &lt;/span&gt;http://127.0.0.1:8280/tt-rss/public.php&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;For Node-Red I wanted an API endpoint for Tasker on my phone. Thankfully this is just as easy to define in Node-red as it is in nginx. In Node-Red open your GET node and just add another folder.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Add and extra folder to your Node-Red endpoints" class="img-fluid dark-image mx-auto d-block text-center text-light" loading="lazy" max-height="194" max-width="473" src="https://peekread.info/images/2021/0318-minimizing-my-selfhosted-attack-surface/image01.png"&gt;&lt;/p&gt;
&lt;p&gt;An example of the Node-Red nginx configuration. Again just like the TT-RSS example above, I have excluded an api subdirectory by having a separate location block.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="w"&gt;  &lt;/span&gt;location&lt;span class="w"&gt; &lt;/span&gt;^~&lt;span class="w"&gt; &lt;/span&gt;/node-red/&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;include&lt;span class="w"&gt; &lt;/span&gt;/etc/nginx/include_whitelist&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;proxy_set_header&lt;span class="w"&gt; &lt;/span&gt;Host&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$http_host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;proxy_set_header&lt;span class="w"&gt; &lt;/span&gt;X-Real-IP&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$remote_addr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;proxy_set_header&lt;span class="w"&gt; &lt;/span&gt;X-Forwarded-For&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$proxy_add_x_forwarded_for&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;proxy_set_header&lt;span class="w"&gt; &lt;/span&gt;X-Forwarded-Proto&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$scheme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;proxy_http_version&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;.1&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;proxy_set_header&lt;span class="w"&gt; &lt;/span&gt;Upgrade&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$http_upgrade&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;proxy_set_header&lt;span class="w"&gt; &lt;/span&gt;Connection&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"upgrade"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;proxy_pass&lt;span class="w"&gt; &lt;/span&gt;http://127.0.0.1:1880/node-red/&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;location&lt;span class="w"&gt; &lt;/span&gt;^~&lt;span class="w"&gt; &lt;/span&gt;/node-red/api/&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;proxy_set_header&lt;span class="w"&gt; &lt;/span&gt;Host&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$http_host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;proxy_set_header&lt;span class="w"&gt; &lt;/span&gt;X-Real-IP&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$remote_addr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;proxy_set_header&lt;span class="w"&gt; &lt;/span&gt;X-Forwarded-For&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$proxy_add_x_forwarded_for&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;proxy_set_header&lt;span class="w"&gt; &lt;/span&gt;X-Forwarded-Proto&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$scheme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;proxy_http_version&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;.1&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;proxy_set_header&lt;span class="w"&gt; &lt;/span&gt;Upgrade&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$http_upgrade&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;proxy_set_header&lt;span class="w"&gt; &lt;/span&gt;Connection&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"upgrade"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;proxy_pass&lt;span class="w"&gt; &lt;/span&gt;http://127.0.0.1:1880/node-red/api/&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now only your API endpoints are globally available. If like me you use a firewall, throwing a convenient geo-block up in front you can lower the exposure a bit more.&lt;/p&gt;</description><category>node-red</category><category>security</category><category>tt-rss</category><guid>https://peekread.info/tech/20210318-minimizing-my-selfhosted-attack-surface/</guid><pubDate>Wed, 17 Mar 2021 16:00:00 GMT</pubDate></item><item><title>TOTP with sudo (Google Auth)</title><link>https://peekread.info/tech/20200610-totp-with-sudo-google-auth/</link><dc:creator>Dugite-Code</dc:creator><description>&lt;p&gt;I was reading the posts over on lobste.rs and saw this post: &lt;a href="https://lobste.rs/s/hs7yjv/is_sudo_almost_useless"&gt;Is &lt;code&gt;sudo&lt;/code&gt; almost useless?&lt;/a&gt;. Typically I see sudo as a safety belt to protect you from doing something stupid with administrator privileges rather than a security shield. But that doesn't mean it can't be both&lt;/p&gt;
&lt;p&gt;As with ssh, outlined in my previous post &lt;a href="https://peekread.info/tech/20190614-totp-with-ssh-google-auth/"&gt;TOTP with SSH (Google Auth)&lt;/a&gt;, you can certainly boost your sudo usefulness security wise by throwing 2FA via &lt;a href="https://github.com/google/google-authenticator-libpam"&gt;google-authenticator-libpam&lt;/a&gt; on top of it.&lt;/p&gt;
&lt;h3&gt;Install google-authenticator-libpam&lt;/h3&gt;
&lt;p&gt;On debian/ubuntu:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="w"&gt;    &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;update&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;apt&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;google-authenticator-libpam
&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Set-up your secret keys&lt;/h3&gt;
&lt;p&gt;We now need to create the secret key, this should not be kept in the user folder, after all what is the point of 2FA if the user we are authenticating can just read the secret files. In my case I keep them in the root dir&lt;/p&gt;
&lt;p&gt;Replace the variable &lt;code&gt;${USER}&lt;/code&gt; if/when you create a key for a user other than the active one.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;google-authenticator&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;/root/.sudo_totp/&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;USER&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;/.google_authenticator
sudo&lt;span class="w"&gt; &lt;/span&gt;chmod&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;600&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-R&lt;span class="w"&gt; &lt;/span&gt;/root/.sudo_totp/
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You will see a QR code/secret key that you can scan with a TOTP app like &lt;a href="https://f-droid.org/en/packages/org.shadowice.flocke.andotp/"&gt;andotp&lt;/a&gt;, &lt;a href="https://play.google.com/store/apps/details?id=com.authy.authy"&gt;authy&lt;/a&gt;, &lt;a href="https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2"&gt;google authenticator&lt;/a&gt; or in my case I added it to my yubikey. There are also your emergency scratch codes that you should record somewhere safe.&lt;/p&gt;
&lt;h3&gt;Enable in PAM&lt;/h3&gt;
&lt;p&gt;You now need to let PAM know it should be checking the codes. There are two ways to do this, Mandatory and Only if secret key exists. I have it as Mandatory any user using sudo &lt;strong&gt;MUST&lt;/strong&gt; have a secret key&lt;/p&gt;
&lt;p&gt;In &lt;code&gt;/etc/pam.d/sudo&lt;/code&gt; add the following configuration lines to the end of the file.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="c1"&gt;# Use Google Auth -- Mandatory&lt;/span&gt;
auth&lt;span class="w"&gt; &lt;/span&gt;required&lt;span class="w"&gt; &lt;/span&gt;pam_google_authenticator.so&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;secret&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/root/.sudo_totp/&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;USER&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;/.google_authenticator&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;root

&lt;span class="c1"&gt;# Use Google Auth -- Only if secret key exists&lt;/span&gt;
&lt;span class="c1"&gt;# auth required pam_google_authenticator.so secret=/root/.sudo_totp/${USER}/.google_authenticator user=root nullok&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Bonus do this for su as well&lt;/h3&gt;
&lt;p&gt;You can do the same thing for su as well however obviously the user variable will be root rather than the user attempting to elevate their privilege's.&lt;/p&gt;
&lt;p&gt;Setup the key as before, just for the root user&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;google-authenticator&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;/root/.google_authenticator
sudo&lt;span class="w"&gt; &lt;/span&gt;chmod&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;600&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-R&lt;span class="w"&gt; &lt;/span&gt;/root/.google_authenticator
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In &lt;code&gt;/etc/pam.d/su&lt;/code&gt; add the following configuration lines to the end of the file.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="c1"&gt;# Use Google Auth -- Mandatory&lt;/span&gt;
auth&lt;span class="w"&gt; &lt;/span&gt;required&lt;span class="w"&gt; &lt;/span&gt;pam_google_authenticator.so&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;secret&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/root/.google_authenticator&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;root
&lt;/pre&gt;&lt;/div&gt;</description><category>linux</category><category>quick post</category><category>security</category><category>sudo</category><guid>https://peekread.info/tech/20200610-totp-with-sudo-google-auth/</guid><pubDate>Tue, 09 Jun 2020 16:00:00 GMT</pubDate></item><item><title>Nextcry and Nextcloud security</title><link>https://peekread.info/tech/20191119-nextcry-and-nextcloud-security/</link><dc:creator>Dugite-Code</dc:creator><description>&lt;p&gt;About a month ago there was an urgent security notice from the Nexcloud devs regarding a flaw in &lt;a href="https://nextcloud.com/blog/urgent-security-issue-in-nginx-php-fpm/"&gt;Nginx php-fpm and the associated Nextcloud config&lt;/a&gt;. Unfortunately we are now seeing it being exploited in the wild.&lt;/p&gt;
&lt;div class="alert alert-info" role="alert"&gt;
&lt;p&gt;&lt;a href="https://www.bleepingcomputer.com/news/security/new-nextcry-ransomware-encrypts-data-on-nextcloud-linux-servers/"&gt;Via: Bleeping computer&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A new ransomware has been found in the wild that is currently undetected by antivirus engines on public scanning platforms. Its name is NextCry due to the extension appended to encrypted files and that it targets clients of the NextCloud file sync and share service.&lt;/p&gt;
&lt;p&gt;The malware targets Nextcloud instances and for the time being there is no free decryption tool available for victims.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;The Nextcloud devs have &lt;a href="https://help.nextcloud.com/t/nextcry-encrypted-all-files-through-my-instance/64154/44"&gt;confirmed that it doesn't appear to be an issue with Nextcloud itself&lt;/a&gt; and that patching and updating is &lt;strong&gt;highly&lt;/strong&gt; advised.&lt;/p&gt;
&lt;p&gt;This brings to mind some extra security measures I do for Nextcloud on top of my standard &lt;a href="https://peekread.info/tech/20190625-server-set-up-checklist/"&gt;server checklist&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;[ &lt;a href="https://www.pfsense.org/" title="pfSense is an open source firewall/router computer software distribution based on FreeBSD."&gt;pfsense&lt;/a&gt; ] basic Geo Blocking with pfBlockerNGGeneral.&lt;/li&gt;
&lt;li&gt;[ &lt;a href="https://www.pfsense.org/" title="pfSense is an open source firewall/router computer software distribution based on FreeBSD."&gt;pfsense&lt;/a&gt; ] IDS with Suricata.&lt;/li&gt;
&lt;li&gt;[ &lt;a href="https://www.graylog.org/"&gt;Graylog&lt;/a&gt; ] I have  set up with an alert if a &lt;a href="https://www.reddit.com/r/sysadmin/comments/46361k/list_of_ransomware_extensions_and_known_ransom/"&gt;known ransomware file extension&lt;/a&gt; is detected on any of my systems (loggin through rsyslog and sidecars).&lt;/li&gt;
&lt;li&gt;[ fail2ban ] - set up to monitor both nginx logs and &lt;a href="https://gist.github.com/GAS85/957e0b1a4f30120225a7be09b173eb24"&gt;nextcloud logs&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;[ Nextcloud APP ] - &lt;a href="https://apps.nextcloud.com/apps/bruteforcesettings"&gt;Brute-force settings&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[ Nextcloud APP ] - &lt;a href="https://apps.nextcloud.com/apps/files_antivirus"&gt;Antivirus for files&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[ Nextcloud APP ] - &lt;a href="https://apps.nextcloud.com/apps/ransomware_protection"&gt;Ransomware protection&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[ Nextcloud APP ] - &lt;a href="https://apps.nextcloud.com/apps/ransomware_detection"&gt;Ransomware recovery&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[ Nextcloud APP ] - &lt;a href="https://apps.nextcloud.com/apps/suspicious_login"&gt;Suspicious Login&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[ Nextcloud APP ] - &lt;a href="https://apps.nextcloud.com/apps/twofactor_totp"&gt;Two-Factor TOTP Provider&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Have extra security advice? Let me know in the comments down below!&lt;/p&gt;</description><category>nextcloud</category><category>security</category><guid>https://peekread.info/tech/20191119-nextcry-and-nextcloud-security/</guid><pubDate>Mon, 18 Nov 2019 16:00:00 GMT</pubDate></item><item><title>SSH Login Notifications with Gotify</title><link>https://peekread.info/tech/20190716-ssh-login-notifications-with-gotify/</link><dc:creator>Dugite-Code</dc:creator><description>&lt;p&gt;&lt;/p&gt;&lt;div class="d-flex position-relative pt-3 pb-3"&gt;
    &lt;div class="flex-shrink-0 me-3"&gt;
        &lt;img data-pagefind-meta="image[src], image_alt[alt]" style="height:89px;" src="https://peekread.info/images/2019/gotify.png" alt="Gotify is a simple server for sending and receiving messages"&gt;
    &lt;/div&gt;
    &lt;div&gt;
        &lt;p class="mt-3"&gt;&lt;/p&gt;&lt;p&gt;Inspired by &lt;a href="https://8192.one/post/ssh_login_notification_signal/"&gt;this post&lt;/a&gt; I decided to add a notification on my phone every time an ssh session began on my servers. Seeing as I make use of &lt;a href="https://gotify.net"&gt;Gotify&lt;/a&gt; for selfhosted push notifications I used that rather than signal.&lt;/p&gt;
    &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;First I created created the file &lt;code&gt;/usr/local/bin/sshnotif&lt;/code&gt;. At the top you can add your own token and Gotify url&lt;/p&gt;
&lt;p&gt;Update: I had to push the current time back a full minute in order to improve consistency. I'll defiantly want to revisit this at a later date&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="ch"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/dev/null&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#Hide output&lt;/span&gt;

&lt;span class="nv"&gt;Gotify_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'https://example.tld/gotify'&lt;/span&gt;
&lt;span class="nv"&gt;Gotify_Token&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'gotify-app-token'&lt;/span&gt;

notify&lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;now&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;date&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"-60 seconds"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;+%s&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#Get current time minus 60 seconds&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nv"&gt;end&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt;&lt;span class="nv"&gt;SECONDS&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="k"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#Set 30s Timeout for loop&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$SECONDS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-lt&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$end&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;

&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nv"&gt;SSHdate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;date&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;who&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;pts&lt;span class="p"&gt;|&lt;/span&gt;tail&lt;span class="w"&gt; &lt;/span&gt;-1&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;awk&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'{print $3, $4}'&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;+%s&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#Check for the latest SSH session&lt;/span&gt;

&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$SSHdate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-ge&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$now&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;then&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#Once who is updated continue with sending Notification&lt;/span&gt;

&lt;span class="w"&gt;                        &lt;/span&gt;&lt;span class="nv"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"SSH Login for &lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;/bin/hostname&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="w"&gt;                        &lt;/span&gt;&lt;span class="nv"&gt;message&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;/usr/bin/who&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;pts&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="w"&gt;                        &lt;/span&gt;/usr/bin/curl&lt;span class="w"&gt; &lt;/span&gt;-X&lt;span class="w"&gt; &lt;/span&gt;POST&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;                                &lt;/span&gt;-F&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"title=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;                                &lt;/span&gt;-F&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"message=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;message&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;                                &lt;/span&gt;-F&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"priority=5"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;                                &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;Gotify_URL&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/message?token=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;Gotify_Token&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="w"&gt;                        &lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;done&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;

notify&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;#Run in background to prevent holding up the login process&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Run the command &lt;code&gt;chmod +x /usr/local/bin/sshnotif&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;In the file &lt;code&gt;/etc/pam.d/sshd&lt;/code&gt; add the following line&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="c1"&gt;# note optional is set to prevent ssh login failure&lt;/span&gt;
session&lt;span class="w"&gt; &lt;/span&gt;optional&lt;span class="w"&gt; &lt;/span&gt;pam_exec.so&lt;span class="w"&gt; &lt;/span&gt;/usr/local/bin/sshnotif
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I now get a nice notification with all the open SSH sessions listed. Unlike the post on &lt;a href="https://peekread.info/tech/20190716-ssh-login-notifications-with-gotify/8192.one"&gt;8192.one&lt;/a&gt; I didn't want any IP address resolution using an online service. I plan on integrating the MaxMind &lt;a href="https://dev.maxmind.com/geoip/geoip2/geolite2/"&gt;GeoLite2 database&lt;/a&gt; at some point. However as I already have &lt;a href="https://peekread.info/tech/20190716-ssh-login-notifications-with-gotify/graylog.org"&gt;Graylog&lt;/a&gt; set up to do this it's not a high priority for me.&lt;/p&gt;
&lt;p&gt;Thanks for the shoutout: https://zerosec.xyz/posts/gotify-notifications/&lt;/p&gt;</description><category>gotify</category><category>security</category><category>ssh</category><guid>https://peekread.info/tech/20190716-ssh-login-notifications-with-gotify/</guid><pubDate>Mon, 15 Jul 2019 16:00:00 GMT</pubDate></item><item><title>Server set-up Checklist</title><link>https://peekread.info/tech/20190625-server-set-up-checklist/</link><dc:creator>Dugite-Code</dc:creator><description>&lt;p&gt;&lt;/p&gt;&lt;div class="d-flex position-relative pt-3 pb-3"&gt;
    &lt;div class="flex-shrink-0 me-3"&gt;
        &lt;img data-pagefind-meta="image[src], image_alt[alt]" style="height:89px;" src="https://peekread.info/images/2019/0625-server-set-up-checklist/image01.png" alt="Configure your linux server"&gt;
    &lt;/div&gt;
    &lt;div&gt;
        &lt;p class="mt-3"&gt;&lt;/p&gt;&lt;p&gt;I often see questions on &lt;a href="https://www.reddit.com/r/selfhosted/"&gt;/r/selfhosted&lt;/a&gt; on how to secure a server. Here is a quick checklist of things you might want to look into.&lt;/p&gt;
    &lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;Follow best practices for the basics&lt;/h3&gt;
&lt;ul class="checklist"&gt;
&lt;li&gt;&lt;input type="checkbox" disabled&gt; &lt;a href="https://tutorials.ubuntu.com/tutorial/tutorial-how-to-verify-ubuntu"&gt;Verify your install images using gpg and sha256&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" disabled&gt; Use strong passwords, defiantly think about using a password manager like &lt;a href="https://keepass.info/" title="KeePass Password Safe is a free and open-source password manager primarily for Windows."&gt;KeePass&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" disabled&gt; Don't use the same password for root and the regular user.&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" disabled&gt; Don't run scripts/applications using sudo/su where possible.&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" disabled&gt; Learn &lt;a href="https://www.cyberciti.biz/faq/unix-linux-bsd-chmod-numeric-permissions-notation-command/"&gt;linux permissions&lt;/a&gt; to avoid using sudo/su where possible.&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" disabled&gt; Use &lt;a href="https://www.ssh.com/ssh/public-key-authentication" title="Public key authentication provides cryptographic strength that even extremely long passwords can not offer."&gt;SSH Public Keys&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" disabled&gt; Regularly Update&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Lock down the Server&lt;/h3&gt;
&lt;ul class="checklist"&gt;
&lt;li&gt;&lt;input type="checkbox" disabled&gt; &lt;a href="https://askubuntu.com/questions/27559/how-do-i-disable-remote-ssh-login-as-root-from-a-server"&gt;Disable root login via SSH&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" disabled&gt; Close &lt;strong&gt;all&lt;/strong&gt; unused incoming ports via &lt;a href="https://www.digitalocean.com/community/tutorials/how-to-setup-a-firewall-with-ufw-on-an-ubuntu-and-debian-cloud-server" title="UFW - Uncomplicated Firewall"&gt;UFW&lt;/a&gt;/iptables&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" disabled&gt; Limit outgoing ports as well as incoming using &lt;a href="https://help.ubuntu.com/community/UFW" title="UFW - Uncomplicated Firewall"&gt;UFW&lt;/a&gt;/iptables&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" disabled&gt; Watch for credential stuffing/brute force attacks with &lt;a href="https://www.digitalocean.com/community/tutorials/how-to-protect-ssh-with-fail2ban-on-ubuntu-14-04" title="Fail2Ban is an intrusion prevention software framework that protects computer servers from brute-force attacks."&gt;Fail2ban&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Backup your configs/files&lt;/h3&gt;
&lt;ul class="checklist"&gt;
&lt;li&gt;&lt;input type="checkbox" disabled&gt; Securely encrypted backup via &lt;a href="http://duplicity.nongnu.org/" title="Encrypted bandwidth-efficient backup using the rsync algorithm"&gt;Duplicity&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" disabled&gt; External Backup to external drive.&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" disabled&gt; Remote backup, either via a regularly swapped out external drive or via the cload&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Set up monitoring services to let you know when something goes wrong&lt;/h3&gt;
&lt;ul class="checklist"&gt;
&lt;li&gt;&lt;input type="checkbox" disabled&gt; Send email on &lt;a href="https://www.perturb.org/display/1191_RSYSLOG_Send_email_notifications.html"&gt;syslog message&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" disabled&gt; Set up notifications for when &lt;a href="https://www.reddit.com/r/selfhosted/comments/bqt6eu/get_notified_when_upgrades_are_available_better/"&gt;updates are available&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" disabled&gt; Monitor system critical files with &lt;a href="https://www.digitalocean.com/community/tutorials/how-to-use-tripwire-to-detect-server-intrusions-on-an-ubuntu-vps"&gt;Tripwire&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" disabled&gt; Set up &lt;a href="https://peekread.info/tech/20190716-ssh-login-notifications-with-gotify/"&gt;ssh login notifications with gotify&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" disabled&gt; Set up &lt;a href="https://www.graylog.org/"&gt;Graylog &lt;/a&gt; or a similar system log aggregator in order to do log analysis&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Here are a few extra things you can do to bolster your ssh security&lt;/h4&gt;
&lt;ul class="checklist"&gt;
&lt;li&gt;&lt;input type="checkbox" disabled&gt; Use a non standard port, this stops like 80% of the dumb bots&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" disabled&gt; Enable geo-blocking on your ssh port, easy to do in &lt;a href="https://www.pfsense.org/" title="pfSense is an open source firewall/router computer software distribution based on FreeBSD."&gt;pfsense&lt;/a&gt; using the package  PFBlockerNG  or with &lt;a href="https://daenney.github.io/2017/01/07/geoip-filtering-iptables.html"&gt;iptables&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" disabled&gt; Close you ssh port based on the time, will you ever really need to ssh in at 3am? Possibly&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" disabled&gt; Add 2FA using &lt;a href="https://peekread.info/tech/20190614-totp-with-ssh-google-auth/"&gt;google-authenticator-libpam&lt;/a&gt; this &lt;a href="https://2.bp.blogspot.com/-2FvyOSlV3f8/XN4qy-LbWjI/AAAAAAAAAiY/m6skYaPJodMJgKv_gxtpvWZCwWulyLfxACLcBGAs/s1600/infographic%25402x.png"&gt;should stop 99% of brute force attacks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;input type="checkbox" disabled&gt; Use something like &lt;a href="https://peekread.info/tech/20190513-fwknop/"&gt;fwknop for encrypted port knocking&lt;/a&gt; - best to avoid unencrypted port knocking using knockd&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Useful resources&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://linux.die.net/man/"&gt;Linux man pages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.digitalocean.com/community/tutorials/"&gt;Digital Ocean tutorials&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.cyberciti.biz/faq/"&gt;nixCraft tutorials&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://crontab.guru/"&gt;crontab wizard&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wiki.ubuntu.com/"&gt;Ubuntu wiki&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description><category>checklist</category><category>security</category><guid>https://peekread.info/tech/20190625-server-set-up-checklist/</guid><pubDate>Mon, 24 Jun 2019 16:00:00 GMT</pubDate></item><item><title>Dugite is this video of you?</title><link>https://peekread.info/blog/20190624-dugite-is-this-video-of-you/</link><dc:creator>Dugite-Code</dc:creator><description>&lt;p&gt;&lt;img alt="Ohhh a virus!" class="dark-image mx-auto" height="416" loading="lazy" src="https://peekread.info/images/2019/0624-dugite-is-this-video-of-you/image01.png" width="800"&gt;&lt;/p&gt;
&lt;p&gt;This morning I received a link in Facebook messenger from an old friend, someone I haven't spoken to in years. It was obviously a phishing link, the title was wrong "Dugite is this &lt;del&gt;a&lt;/del&gt; video of you?" and the preview image was blurry, like it was stuck not loading.&lt;/p&gt;
&lt;p&gt;Needless to say I didn't click and messaged them back saying "Probably should change your password?"&lt;/p&gt;
&lt;p&gt;What Interests me is the reaction when this friend posted on their wall, within minuets, not to open any messages from them and they "HAVE A VIRUS ON MY PHONE". Out of 7 people 3 opened the obviously shady link.&lt;/p&gt;
&lt;p&gt;Not one of these people who opened this link mentioned they will now need to change their password, in fact one person even said it all should be ok once it's gone through their entire address book. The non-technical people, to me at least, seem to be treating phishing and malware like you would the common cold. It'll pass, fact of life and not a real concern.&lt;/p&gt;
&lt;p&gt;They of course should be very concerned with the &lt;a href="https://www.stonetemple.com/mobile-vs-desktop-usage-study/"&gt;majority of web browsing&lt;/a&gt; occurring on the mobile the amount of data that is potentially stored on a phone is astronomically large. From your banking app to your photos and everything you can gain access through your email accounts is at risk. Mobile operating systems are, thankfully, very locked down with each app operating somewhat isolated from the others, but that's not a guarantee.&lt;/p&gt;
&lt;p&gt;I fear the next decade of tech breaches are going to get ugly and there just isn't a technical solution to user apathy.&lt;/p&gt;</description><category>facebook</category><category>phishing</category><category>security</category><guid>https://peekread.info/blog/20190624-dugite-is-this-video-of-you/</guid><pubDate>Sun, 23 Jun 2019 16:00:00 GMT</pubDate></item></channel></rss>