pages tagged securityFeeding the Cloudhttps://feeding.cloud.geek.nz/tags/security/Feeding the Cloudikiwiki2023-12-22T05:40:11ZEncoding your WiFi access point password into a QR codehttps://feeding.cloud.geek.nz/posts/encoding-wifi-access-point-passwords-qr-code/
<a href="https://creativecommons.org/licenses/by-sa/4.0/">Creative Commons Attribution-ShareAlike 4.0 International License</a>
2023-04-22T00:01:20Z2019-12-29T03:25:00Z
<p>Up until recently, it was a pain to defend againt <a href="https://en.wikipedia.org/wiki/Wi-Fi_Protected_Access#Weak_password">WPA2 brute-force
attacks</a>
by using a random 63-character password (the maximum in
<a href="https://en.wikipedia.org/wiki/Wi-Fi_Protected_Access#Target_users_(authentication_key_distribution">WPA-Personal</a>)
mode). Thanks to Android 10 and iOS 11 supporting reading WiFi passwords
from a QR code, this is finally a practical defense.</p>
<h2 id="Generating_the_QR_code">Generating the QR code</h2>
<p>After installing the <a href="https://packages.debian.org/stable/qrencode"><code>qrencode</code></a>
package, run the following:</p>
<pre><code>qrencode -o wifi.png "WIFI:T:WPA;S:<SSID>;P:<PASSWORD>;;"
</code></pre>
<p>substituting <code><SSID></code> for the name of your WiFi network and <code><PASSWORD></code> for
the 63-character password you hopefully generated with <code>pwgen -s 63</code>.</p>
<p>If your password includes a semicolon, then escape it like this:</p>
<pre><code>"WIFI:T:WPA;S:<SSID>;P:pass\:word;;"
</code></pre>
<p>since iOS won't support the following (which works fine on Android):</p>
<pre><code>'WIFI:T:WPA;S:<SSID>;P:"pass:word";;'
</code></pre>
<p>The only other pitfall I ran into is that if you include a trailing newline
character (for example piping <code>echo "..."</code> into <code>qrencode</code> as opposed to
<code>echo -n "..."</code>) then it will fail on both iOS and Android.</p>
<p>The full syntax for these WiFi QR codes can be found on the <a href="https://github.com/zxing/zxing/wiki/Barcode-Contents#wi-fi-network-config-android-ios-11">zxing wiki</a>.</p>
<h2 id="Scanning_the_QR_code">Scanning the QR code</h2>
<p>On iOS, simply open the camera app and scan the QR code to bring up a
notification which allows you to connect to the WiFi network:</p>
<p><img alt="" src="https://feeding.cloud.geek.nz/posts/encoding-wifi-access-point-passwords-qr-code/ios_qr_scanner.png" /></p>
<p>On Android, go into the WiFi settings and tap on the WiFi network you want
to join:</p>
<p><img alt="" src="https://feeding.cloud.geek.nz/posts/encoding-wifi-access-point-passwords-qr-code/android_wifi_settings.png" /></p>
<p>then click the QR icon in the password field and scan the code:</p>
<p><img alt="" src="https://feeding.cloud.geek.nz/posts/encoding-wifi-access-point-passwords-qr-code/android_qr_scanner.png" /></p>
<h2 id="In-browser_alternative">In-browser alternative</h2>
<p>If you can't do this locally for some reason, there is also an <a href="https://qifi.org/">in-browser
QR code generator</a> with <a href="https://github.com/evgeni/qifi">source code
available</a>.</p>
Restricting third-party iframe widgets using the sandbox attribute, referrer policy and feature policyhttps://feeding.cloud.geek.nz/posts/restricting-third-party-iframes-sandbox-referrer-feature-policy/
<a href="https://creativecommons.org/licenses/by-sa/4.0/">Creative Commons Attribution-ShareAlike 4.0 International License</a>
2021-06-11T20:43:57Z2019-09-21T03:15:00Z
<p>Adding third-party embedded widgets on a website is a common but potentially
dangerous practice. Thankfully, the web platform offers a few controls that can help
mitigate the risks. While this post uses the example of an embedded
SurveyMonkey survey, the principles can be used for all kinds of other widgets.</p>
<p>Note that this is by no means an endorsement of SurveyMonkey's proprietary
service. If you are looking for a survey product, you should consider a free
and open source alternative like <a href="https://www.limesurvey.org/">LimeSurvey</a>.</p>
<h1 id="SurveyMonkey.26.2339.3Bs_snippet">SurveyMonkey's snippet</h1>
<p>In order to embed a <a href="https://www.surveymonkey.com/curiosity/how-to-embed-your-survey-on-a-website/">survey on your
website</a>,
the SurveyMonkey interface will tell you to install the following <a href="https://help.surveymonkey.com/articles/en_US/kb/Website-Collector">website
collector</a> script:</p>
<pre><code><script>(function(t,e,s,n){var
o,a,c;t.SMCX=t.SMCX||[],e.getElementById(n)||(o=e.getElementsByTagName(s),a=o[o.length-1],c=e.createElement(s),c.type="text/javascript",c.async=!0,c.id=n,c.src=["https:"===location.protocol?"https://":"http://","widget.surveymonkey.com/collect/website/js/tRaiETqnLgj758hTBazgd9NxKf_2BhnTfDFrN34n_2BjT1Kk0sqrObugJL8ZXdb_2BaREa.js"].join(""),a.parentNode.insertBefore(c,a))})(window,document,"script","smcx-sdk");</script><a
style="font: 12px Helvetica, sans-serif; color: #999; text-decoration:
none;" href=https://www.surveymonkey.com> Create your own user feedback
survey </a>
</code></pre>
<p>which can be rewritten in a more understandable form as:</p>
<pre><code>(
function (s) {
var scripts, last_script, new_script;
window.SMCX = window.SMCX || [],
document.getElementById("smcx-sdk") ||
(
scripts = document.getElementsByTagName("script"),
last_script = scripts[scripts.length - 1],
new_script = document.createElement("script"),
new_script.type = "text/javascript",
new_script.async = true,
new_script.id = "smcx-sdk",
new_script.src =
[
"https:" === location.protocol ? "https://" : "http://",
"widget.surveymonkey.com/collect/website/js/tRaiETqnLgj758hTBazgd9NxKf_2BhnTfDFrN34n_2BjT1Kk0sqrObugJL8ZXdb_2BaREa.js"
].join(""),
last_script.parentNode.insertBefore(new_script, last_script)
)
}
)();
</code></pre>
<p>The fact that this adds a third-party script dependency to your website is
problematic because it means that a security vulnerability in their
infrastructure could lead to a complete compromise of your site, thanks to
third-party scripts having full control over your website. Security issues
aside though, this could also enable this third-party to violate your users'
privacy expectations and extract any information displayed on your site for
marketing purposes.</p>
<p>However, if you embed the snippet on a test page and inspect it with the
developer tools, you will find that it actually creates an
<a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe">iframe</a>:</p>
<pre><code><iframe
width="500"
height="500"
frameborder="0"
allowtransparency="true"
src="https://www.surveymonkey.com/r/D3KDY6R?embedded=1"
></iframe>
</code></pre>
<p>and you can use that directly on your site without having to load their
script.</p>
<h2 id="Mixed_content_anti-pattern">Mixed content anti-pattern</h2>
<p>As an aside, the script snippet they propose makes use of a common front-end
anti-pattern:</p>
<pre><code>"https:"===location.protocol?"https://":"http://"
</code></pre>
<p>This is presumably meant to avoid inserting an HTTP script element into an
HTTPS page, since that would be considered <a href="https://developer.mozilla.org/en-US/docs/Web/Security/Mixed_content">mixed
content</a>
and get blocked by browsers, however this is entirely unnecessary. One
should only ever use the HTTPS version of such scripts anyways since an HTTP
page <a href="https://www.w3.org/TR/mixed-content/#categorize-settings-object">never prohibits embedding HTTPS
content</a>.</p>
<p>In other words, the above code snippet can be simplified to:</p>
<pre><code>"https://"
</code></pre>
<h1 id="Restricting_iframes">Restricting iframes</h1>
<p>Thanks to defenses which have been added to the web platform recently, there
are a few things that can be done to constrain iframes.</p>
<p>Firstly, you can choose to hide your full page URL from SurveyMonkey using
the <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy">referrer
policy</a>:</p>
<pre><code>referrerpolicy="strict-origin"
</code></pre>
<p>This mean seem harmless, but page URLs sometimes include sensitive
information in the URL path or query string, for example, search terms that
a user might have typed. The <code>strict-origin</code> policy will limit the referrer
to your site's hostname, port and protocol.</p>
<p>Secondly, you can prevent the iframe from being able to access anything
about its embedding page or to trigger popups and unwanted downloads using
the <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#attr-sandbox">sandbox
attribute</a>:</p>
<pre><code>sandbox="allow-scripts allow-forms"
</code></pre>
<p>Ideally, the contents of this attribute would be empty so that all
restrictions would be active, but SurveyMonkey is a JavaScript application
and it of course needs to submit a form since that's the purpose of the widget.</p>
<p>Finally, a new experimental capability is making its way into browsers:
<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Feature_Policy">feature policy</a>.
In the context of untrusted iframes, it enables developers to explicitly
disable <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Feature-Policy#Directives">certain powerful
features</a>:</p>
<pre><code>allow="accelerometer 'none';
ambient-light-sensor 'none';
camera 'none';
display-capture 'none';
document-domain 'none';
fullscreen 'none';
geolocation 'none';
gyroscope 'none';
magnetometer 'none';
microphone 'none';
midi 'none';
payment 'none';
usb 'none';
vibrate 'none';
vr 'none';
webauthn 'none'"
</code></pre>
<p>Putting it all together, we end up with the following HTML snippet:</p>
<pre><code><iframe
width="500"
height="500"
frameborder="0"
allowtransparency="true"
allow="accelerometer 'none'; ambient-light-sensor 'none';
camera 'none'; display-capture 'none';
document-domain 'none'; fullscreen 'none';
geolocation 'none'; gyroscope 'none'; magnetometer 'none';
microphone 'none'; midi 'none'; payment 'none'; usb 'none';
vibrate 'none'; vr 'none'; webauthn 'none'"
sandbox="allow-scripts allow-forms"
referrerpolicy="strict-origin"
src="https://www.surveymonkey.com/r/D3KDY6R?embedded=1"
></iframe>
</code></pre>
<h1 id="Content_Security_Policy">Content Security Policy</h1>
<p>Another advantage of using the iframe directly is that instead of loosening
your site's <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP">Content Security
Policy</a> by adding all
of the following:</p>
<ul>
<li><code>script-src https://www.surveymonkey.com</code></li>
<li><code>img-src https://www.surveymonkey.com</code></li>
<li><code>frame-src https://www.surveymonkey.com</code></li>
</ul>
<p>you can limit the extra directives to just the frame controls:</p>
<ul>
<li><code>frame-src https://www.surveymonkey.com</code></li>
</ul>
<p><a href="https://w3c.github.io/webappsec-cspee/">CSP Embedded Enforcement</a> would be
another nice mechanism to make use of, but looking at SurveyMonkey's CSP
policy:</p>
<pre><code>Content-Security-Policy:
default-src https: data: blob: 'unsafe-eval' 'unsafe-inline'
wss://*.hotjar.com 'self';
img-src https: http: data: blob: 'self';
script-src https: 'unsafe-eval' 'unsafe-inline' http://www.google-analytics.com http://ajax.googleapis.com
http://bat.bing.com http://static.hotjar.com http://www.googleadservices.com
'self';
style-src https: 'unsafe-inline' http://secure.surveymonkey.com 'self';
report-uri https://csp.surveymonkey.com/report?e=true&c=prod&a=responseweb
</code></pre>
<p>it allows the injection of arbitrary Flash files, <a href="https://developers.google.com/web/fundamentals/security/csp/#inline_code_is_considered_harmful">inline
scripts</a>,
evals and any other scripts hosted on an HTTPS URL, which means that it
<a href="https://csp-evaluator.withgoogle.com/">doesn't really provide any meaningful security
benefits</a>.</p>
<p>Embedded enforcement is thefore not a usable security control in this
particular example until SurveyMonkey gets a stricter CSP policy.</p>
Secure ssh-agent usagehttps://feeding.cloud.geek.nz/posts/secure-ssh-agent-usage/
<a href="https://creativecommons.org/licenses/by-sa/4.0/">Creative Commons Attribution-ShareAlike 4.0 International License</a>
2021-06-11T20:43:57Z2019-04-13T13:45:00Z
<p><code>ssh-agent</code> was in the news recently due to the <a href="https://github.com/matrix-org/matrix.org/issues/371">matrix.org
compromise</a>. The main
takeaway from that incident was that one should <a href="https://heipei.io/2015/02/26/SSH-Agent-Forwarding-considered-harmful/">avoid the <code>ForwardAgent</code>
(or <code>-A</code>) functionality when <code>ProxyCommand</code> can
do</a>
and consider multi-factor authentication on the server-side, for example
using
<a href="https://wiki.archlinux.org/index.php/Google_Authenticator">libpam-google-authenticator</a>
or <a href="https://developers.yubico.com/yubico-pam/YubiKey_and_SSH_via_PAM.html">libpam-yubico</a>.</p>
<p>That said, there are also two options to <code>ssh-add</code> that can help reduce the
risk of someone else with elevated privileges hijacking your agent to make
use of your ssh credentials.</p>
<h2 id="Prompt_before_each_use_of_a_key">Prompt before each use of a key</h2>
<p>The first option is <code>-c</code> which will require you to confirm each use of your
ssh key by pressing Enter when a graphical prompt shows up.</p>
<p>Simply install an <code>ssh-askpass</code> frontend like
<a href="https://packages.debian.org/stable/ssh-askpass-gnome">ssh-askpass-gnome</a>:</p>
<pre><code>apt install ssh-askpass-gnome
</code></pre>
<p>and then use this to when adding your key to the agent:</p>
<pre><code>ssh-add -c ~/.ssh/key
</code></pre>
<h2 id="Automatically_removing_keys_after_a_timeout">Automatically removing keys after a timeout</h2>
<p><code>ssh-add -D</code> will remove all identities (i.e. keys) from your ssh agent, but
requires that you remember to run it manually once you're done.</p>
<p>That's where the second option comes in. Specifying <code>-t</code> when adding a key
will automatically remove that key from the agent after a while.</p>
<p>For example, I have found that this setting works well at work:</p>
<pre><code>ssh-add -t 10h ~/.ssh/key
</code></pre>
<p>where I don't want to have to type my ssh password everytime I push a git
branch.</p>
<p>At home on the other hand, my use of ssh is more sporadic and so I don't
mind a shorter timeout:</p>
<pre><code>ssh-add -t 4h ~/.ssh/key
</code></pre>
<h2 id="Making_these_options_the_default">Making these options the default</h2>
<p>I couldn't find a configuration file to make these settings the default and
so I ended up putting the following line in my <code>~/.bash_aliases</code>:</p>
<pre><code>alias ssh-add='ssh-add -c -t 4h'
</code></pre>
<p>so that I can continue to use <code>ssh-add</code> as normal and have not remember
to include these extra options.</p>
Checking Your Passwords Against the Have I Been Pwned Listhttps://feeding.cloud.geek.nz/posts/checking-your-passwords-against-hibp/
<a href="https://creativecommons.org/licenses/by-sa/4.0/">Creative Commons Attribution-ShareAlike 4.0 International License</a>
2021-06-11T20:43:57Z2017-10-17T05:10:00Z
<p>Two months ago, Troy Hunt, the security professional behind
<a href="https://haveibeenpwned.com/">Have I been pwned?</a>,
<a href="https://www.troyhunt.com/introducing-306-million-freely-downloadable-pwned-passwords/">released</a>
an incredibly comprehensive
<a href="https://haveibeenpwned.com/Passwords">password list</a> in the hope that it
would allow web developers to steer their users away from passwords that
have been compromised in past breaches.</p>
<p>While the list released by HIBP is hashed, the plaintext passwords are out
there and one should assume that password crackers have access to them.
So if you use a password on that list, you can be fairly confident
that it's very easy to guess or crack your password.</p>
<p>I wanted to check my <strong>active</strong> passwords against that list to check whether
or not any of them are compromised and should be changed immediately. This
meant that I needed to download the list and do these lookups locally since
it's not a good idea to send your current passwords to this third-party
service.</p>
<p>I put my tool up on <a href="https://launchpad.net/hibp-pwlookup">Launchpad</a> /
<a href="https://pypi.python.org/pypi/hibp-pwlookup">PyPI</a> and you are more than
welcome to give it a go. Install <a href="https://www.postgresql.org/">Postgres</a> and
<a href="http://initd.org/psycopg/">Psycopg2</a> and then follow the
<a href="https://git.launchpad.net/hibp-pwlookup/tree/README.txt">README instructions</a>
to setup your database.</p>
Using DNSSEC and DNSCrypt in Debianhttps://feeding.cloud.geek.nz/posts/using-dnssec-and-dnscrypt-in-debian/
<a href="https://creativecommons.org/licenses/by-sa/4.0/">Creative Commons Attribution-ShareAlike 4.0 International License</a>
2023-10-01T21:42:31Z2016-04-26T03:00:00Z
<p>While there is real progress being made towards
<a href="https://blog.mozilla.org/security/2015/04/30/deprecating-non-secure-http/">eliminating insecure HTTP traffic</a>,
<a href="https://en.wikipedia.org/wiki/Domain_Name_System">DNS</a> is a fundamental
Internet service that still usually relies on unauthenticated cleartext.
There are however a few efforts to try and fix this problem. Here is the
setup I use on my Debian laptop to make use of both
<a href="http://www.dnssec.net/">DNSSEC</a> and <a href="https://dnscrypt.info/">DNSCrypt</a>.</p>
<h1 id="DNSCrypt">DNSCrypt</h1>
<p>DNSCrypt was created to enable end-users to encrypt the traffic between
themselves and their chosen DNS resolver.</p>
<p>To switch away from your ISP's default DNS resolver to a DNSCrypt resolver,
simply install the <a href="https://packages.debian.org/stretch/dnscrypt-proxy"><code>dnscrypt-proxy</code> package</a> and then
set it as the default resolver either in <code>/etc/resolv.conf</code>:</p>
<pre><code>nameserver 127.0.2.1
</code></pre>
<p>if you are using a static network configuration or in
<code>/etc/dhcp/dhclient.conf</code>:</p>
<pre><code>supersede domain-name-servers 127.0.2.1;
</code></pre>
<p>if you rely on dynamic network configuration via <a href="https://en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol">DHCP</a>.</p>
<p>There are two things you might want to keep in mind when choosing your
<a href="https://github.com/DNSCrypt/dnscrypt-resolvers/tree/master/v1">DNSCrypt resolver</a>:</p>
<ul>
<li>whether or not they keep any logs of the DNS traffic</li>
<li>whether or not they support DNSSEC</li>
</ul>
<p>I have personally selected a resolver located in Iceland by setting the
following in <code>/etc/default/dnscrypt-proxy</code>:</p>
<pre><code>DNSCRYPT_PROXY_RESOLVER_NAME=ns0.dnscrypt.is
</code></pre>
<h1 id="DNSSEC">DNSSEC</h1>
<p>While DNSCrypt protects the confidentiality of our DNS queries, it doesn't
give us any assurance that the results of such queries are the right ones.
In order to authenticate results in that way and prevent DNS poisoning, a
hierarchical cryptographic system was created: DNSSEC.</p>
<p>In order to enable it, I have <a href="https://feeding.cloud.geek.nz/posts/setting-up-your-own-dnssec-aware/">setup a local unbound DNSSEC
resolver</a>
on my machine and pointed <code>/etc/resolv.conf</code> (or
<code>/etc/dhcp/dhclient.conf</code>) to my unbound installation at <code>127.0.0.1</code>.</p>
<p>Then I put the following in <code>/etc/unbound/unbound.conf.d/dnscrypt.conf</code>:</p>
<pre><code>server:
# Remove localhost from the donotquery list
do-not-query-localhost: no
forward-zone:
name: "."
forward-addr: 127.0.2.1@53
</code></pre>
<p>to stop unbound from resolving DNS directly and to instead go through the
encrypted DNSCrypt proxy.</p>
<h1 id="Reliability">Reliability</h1>
<p>In my experience, unbound and dnscrypt-proxy are fairly reliable but they
eventually get confused (presumably) by network changes and start returning
errors.</p>
<p>The ugly but dependable work-around I have found is to create a cronjob at
<code>/etc/cron.d/restart-dns.conf</code> that restarts both services once a day:</p>
<pre><code>0 3 * * * root /usr/sbin/service dnscrypt-proxy restart
1 3 * * * root /usr/sbin/service unbound restart
</code></pre>
<h1 id="Captive_portals">Captive portals</h1>
<p>The one remaining problem I need to solve has to do with
<a href="https://en.wikipedia.org/wiki/Captive_portal">captive portals</a>. This can be
quite annoying when travelling because it requires me to use the portal's
DNS resolver in order to connect to the splash screen that unlocks the wifi
connection.</p>
<p>The
<a href="https://packages.debian.org/stable/dnssec-trigger"><code>dnssec-trigger</code> package</a>
looked promising but when I tried it on my <code>jessie</code> laptop, it wasn't
particularly reliable.</p>
<p>My temporary work-around is to comment out this line in
<code>/etc/dhcp/dhclient.conf</code> whenever I need to connect to such annoying wifi
networks:</p>
<pre><code>#supersede domain-name-servers 127.0.0.1;
</code></pre>
<p>If you've found a better solution to this problem, please leave a comment!</p>
How Safe Browsing works in Firefoxhttps://feeding.cloud.geek.nz/posts/how-safe-browsing-works-in-firefox/
<a href="https://creativecommons.org/licenses/by-sa/4.0/">Creative Commons Attribution-ShareAlike 4.0 International License</a>
2022-08-11T01:04:34Z2016-04-01T06:00:00Z
<p><em>Also see Google's official description of <a href="https://security.googleblog.com/2022/08/how-hash-based-safe-browsing-works-in.html">how Safe Browsing works in Chrome</a>.</em></p>
<p>Firefox has had support for Google's
<a href="https://developers.google.com/safe-browsing/">Safe Browsing</a> since 2005
when it started as
<a href="https://web.archive.org/web/20051218171531/http://www.google.com/tools/firefox/safebrowsing/index.html">a stand-alone Firefox extension</a>.
At first it was only available in the USA, but it was opened up to the rest of the world in
2006 and moved to the
<a href="https://web.archive.org/web/20060412192055/http://tools.google.com/firefox/toolbar/">Google Toolbar</a>.
It then got
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=329292">integrated directly</a>
into
<a href="http://website-archive.mozilla.org/www.mozilla.org/firefox_releasenotes/en-US/firefox/2.0/releasenotes/">Firefox 2.0</a>
before the
<a href="https://security.googleblog.com/2007/05/introducing-googles-anti-malware.html">public launch</a>
of the service in 2007.</p>
<p>Many people seem confused by this phishing and malware protection
system and while there is a
<a href="https://support.mozilla.org/en-US/kb/how-does-phishing-and-malware-protection-work">pretty good explanation of how it works</a>
on our support site, it doesn't go into technical details. This will
hopefully be of interest to those who have more questions about it.</p>
<h1 id="Browsing_Protection">Browsing Protection</h1>
<p>The main part of the Safe Browsing system is the one that watches for bad
URLs as you're browsing. Browsing protection currently protects users from:</p>
<ul>
<li><a href="https://www.stopbadware.org/badware">malware</a> sites,</li>
<li><a href="https://security.googleblog.com/2015/11/safe-browsing-protection-from-even-more.html">deceptive sites</a>
(including <a href="https://support.google.com/websearch/answer/106318?hl=en&rd=1">phishing</a>
and <a href="https://security.googleblog.com/2016/02/no-more-deceptive-download-buttons.html">social engineering</a>
sites), and</li>
<li>sites hosting <a href="https://security.googleblog.com/2015/07/more-visible-protection-against.html">potentially unwanted software</a>.</li>
</ul>
<p>If a Firefox user attempts to visit one of these sites, a warning page will
show up instead, which you can see for yourself here:</p>
<ul>
<li><a href="https://itisatrap.org/firefox/its-an-attack.html">fake malware page</a></li>
<li><a href="https://itisatrap.org/firefox/unwanted.html">fake unwanted software page</a></li>
<li><a href="https://itisatrap.org/firefox/its-a-trap.html">fake phishing page</a></li>
</ul>
<p>The first two warnings can be toggled using the <code>browser.safebrowsing.malware.enabled</code>
preference (in <code>about:config</code>) whereas the last one is controlled by
<code>browser.safebrowsing.phishing.enabled</code>.</p>
<h2 id="List_updates">List updates</h2>
<p>It would be too slow (and privacy-invasive) to contact a trusted server
every time the browser wants to establish a connection with a web server.
Instead, Firefox downloads a list of bad URLs every 30 minutes from the
server (<code>browser.safebrowsing.provider.google.updateURL</code>) and does a
<a href="https://dxr.mozilla.org/mozilla-central/rev/494289c72ba3997183e7b5beaca3e0447ecaf96d/netwerk/base/nsBaseChannel.cpp#303-320">lookup against its local database</a>
before displaying a page to the user.</p>
<p>Downloading the entire list of sites flagged by Safe Browsing would be
impractical due to
<a href="https://www.google.com/transparencyreport/safebrowsing/notes/#size-of-blacklist">its size</a>
so the following transformations are applied:</p>
<ol>
<li>each URL on the list is <a href="https://developers.google.com/safe-browsing/developers_guide_v2#Canonicalization">canonicalized</a>,</li>
<li>then <a href="https://en.wikipedia.org/w/index.php?title=SHA256">hashed</a>,</li>
<li>of which only the first 32 bits of the hash are kept.</li>
</ol>
<p>The lists that are requested from the Safe Browsing server and used to flag
pages as malware/unwanted or phishing can be found in
<code>urlclassifier.malwareTable</code> and <code>urlclassifier.phishTable</code> respectively.</p>
<p>If you want to see some debugging information in your terminal while Firefox
is downloading updated lists, turn on <code>browser.safebrowsing.debug</code>.</p>
<p>Once downloaded, the lists can be found in the cache directory:</p>
<ul>
<li><code>~/.cache/mozilla/firefox/XXXX/safebrowsing/</code> on Linux</li>
<li><code>~/Library/Caches/Firefox/Profiles/XXXX/safebrowsing/</code> on Mac</li>
<li><code>C:\Users\XXXX\AppData\Local\mozilla\firefox\profiles\XXXX\safebrowsing\</code> on Windows</li>
</ul>
<h2 id="Resolving_partial_hash_conflicts">Resolving partial hash conflicts</h2>
<p>Because the Safe Browsing database only contains partial hashes, it is
possible for a safe page to share the same 32-bit hash prefix as a bad page.
Therefore when a URL matches the local list, the browser needs to know
whether or not the rest of the hash matches the entry on the Safe Browsing
list.</p>
<p>In order resolve such conflicts, Firefox requests from the Safe Browsing
server (<code>browser.safebrowsing.provider.google.gethashURL</code>) all of the
hashes that start with the affected 32-bit prefix and adds these full-length
hashes to its local database. Turn on <code>browser.safebrowsing.debug</code> to see
some debugging information on the terminal while these "completion" requests
are made.</p>
<p>If the current URL doesn't match any of these full hashes, the load
proceeds as normal. If it does match one of them, a warning interstitial
page is shown and the
<a href="https://dxr.mozilla.org/mozilla-central/rev/494289c72ba3997183e7b5beaca3e0447ecaf96d/netwerk/base/nsChannelClassifier.cpp#689">load is canceled</a>.</p>
<h1 id="Download_Protection">Download Protection</h1>
<p>The second part of the Safe Browsing system protects users against malicious
downloads. It was
<a href="https://security.googleblog.com/2011/04/protecting-users-from-malicious.html">launched</a>
in 2011, <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=662819">implemented</a> in
<a href="https://www.mozilla.org/en-US/firefox/31.0/releasenotes/">Firefox 31</a> on
Windows and <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1111741">enabled</a>
in <a href="https://www.mozilla.org/en-US/firefox/39.0/releasenotes/">Firefox 39</a> on
Mac and Linux.</p>
<p>It roughly works like this:</p>
<ol>
<li>Download the file.</li>
<li>Check the main URL, referrer and redirect chain against a local
blocklist (<code>urlclassifier.downloadBlockTable</code>) and block the download
in case of a match.</li>
<li>On Windows, if the binary is signed, check the signature against a local
whitelist (<code>urlclassifier.downloadAllowTable</code>) of known good publishers and
release the download if a match is found.</li>
<li>If the file is not a
<a href="https://dxr.mozilla.org/mozilla-central/rev/494289c72ba3997183e7b5beaca3e0447ecaf96d/toolkit/components/downloads/ApplicationReputation.cpp#388-425">binary file</a>
then release the download.</li>
<li>Otherwise, send the binary file's
<a href="https://dxr.mozilla.org/mozilla-central/rev/494289c72ba3997183e7b5beaca3e0447ecaf96d/toolkit/components/downloads/ApplicationReputation.cpp#921-950">metadata</a>
to the remote application reputation server
(<code>browser.safebrowsing.downloads.remote.url</code>) and block the download if the
server indicates that the file isn't safe.</li>
</ol>
<p>Blocked downloads can be unblocked by right-clicking on them in the download
manager and selecting "Unblock".</p>
<p>While the download protection feature is automatically disabled when malware
protection (<code>browser.safebrowsing.malware.enabled</code>) is turned off, it can
also be disabled independently via the
<code>browser.safebrowsing.downloads.enabled</code> preference.</p>
<p>Note that Step 5 is the only point at which any information about the
download is shared with Google. That remote lookup can be suppressed via the
<code>browser.safebrowsing.downloads.remote.enabled</code> preference for those users
concerned about sending that metadata to a third party.</p>
<h2 id="Types_of_malware">Types of malware</h2>
<p>The original application reputation service would protect users against
"dangerous" downloads, but it has recently been expanded to also warn users
about
<a href="https://chrome.googleblog.com/2014/08/thats-not-download-youre-looking-for.html">unwanted software</a>
as well as software that's not commonly downloaded.</p>
<p>These various warnings can be turned on and off in Firefox through the
following preferences:</p>
<ul>
<li><code>browser.safebrowsing.downloads.remote.block_dangerous</code></li>
<li><code>browser.safebrowsing.downloads.remote.block_dangerous_host</code></li>
<li><code>browser.safebrowsing.downloads.remote.block_potentially_unwanted</code></li>
<li><code>browser.safebrowsing.downloads.remote.block_uncommon</code></li>
</ul>
<p>and tested using <a href="https://testsafebrowsing.appspot.com">Google's test page</a>.</p>
<p>If you want to see how often each "verdict" is returned by the server, you
can have a look at the
<a href="https://telemetry.mozilla.org/new-pipeline/dist.html#!cumulative=0&end_date=2016-03-23&keys=__none__!__none__!__none__&max_channel_version=beta%252F46&measure=APPLICATION_REPUTATION_SERVER_VERDICT&min_channel_version=null&product=Firefox&sanitize=1&sort_keys=submissions&start_date=2016-03-07&table=1&trim=1&use_submission_date=0">telemetry results for Firefox Beta</a>.</p>
<h1 id="Privacy">Privacy</h1>
<p>One of the most persistent misunderstandings about Safe Browsing is the idea
that the browser needs to send all visited URLs to Google in order to verify
whether or not they are safe.</p>
<p>While this was
<a href="https://www.google.com/tools/firefox/safebrowsing/faq.html#q11">an option</a>
in <a href="https://wiki.mozilla.org/Safe_Browsing:_Server_Spec">version 1</a> of the Safe Browsing protocol (as disclosed in their
<a href="https://web.archive.org/web/20051230133135/http://www.google.com/tools/firefox/extensions_privacy.html">privacy policy</a>
at the time), support for this
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=388652">"enhanced mode" was removed in Firefox 3</a>
and the version 1 server was
<a href="https://security.googleblog.com/2011/05/safe-browsing-protocol-v2-transition.html">decommissioned in late 2011</a>
in favor of
<a href="https://developers.google.com/safe-browsing/developers_guide_v2">version 2 of the Safe Browsing API</a>
which doesn't offer this type of real-time lookup.</p>
<p>Google explicitly states that the information collected as part
of operating the Safe Browsing service
<a href="https://blog.chromium.org/2012/01/all-about-safe-browsing.html">"is only used to flag malicious activity and is never used anywhere else at Google"</a>
and that
<a href="https://www.google.com/intl/en/chrome/browser/privacy/whitepaper.html#malware">"Safe Browsing requests won't be associated with your Google Account"</a>.
In addition, Firefox adds a few privacy protections:</p>
<ul>
<li>Query string parameters are
<a href="https://dxr.mozilla.org/mozilla-central/rev/494289c72ba3997183e7b5beaca3e0447ecaf96d/toolkit/components/downloads/ApplicationReputation.cpp#684-710">stripped</a>
from URLs we check as part of the download protection feature.</li>
<li>Cookies set by the Safe Browsing servers to protect the service from
abuse are stored in a
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=897516">separate cookie jar</a>
so that they are not mixed with regular browsing/session cookies.</li>
<li>When requesting complete hashes for a 32-bit prefix, Firefox throws in a
number of extra
<a href="https://dxr.mozilla.org/mozilla-central/rev/494289c72ba3997183e7b5beaca3e0447ecaf96d/toolkit/components/url-classifier/nsUrlClassifierDBService.cpp#283-289">"noise" entries</a>
to obfuscate the original URL further.</li>
</ul>
<p>On balance, we believe that most users will want to keep Safe Browsing enabled,
but we also make it easy for
<a href="https://www.torproject.org/projects/torbrowser.html">users with particular needs</a>
to turn it off.</p>
<h1 id="Learn_More">Learn More</h1>
<p>If you want to learn more about how Safe Browsing works in Firefox, you can
find all of the technical details on the
<a href="https://wiki.mozilla.org/Security/Safe_Browsing">Safe Browsing</a> and
<a href="https://wiki.mozilla.org/Security/Application_Reputation">Application Reputation</a>
pages of the Mozilla wiki or you can ask questions on our
<a href="https://www.mozilla.org/en-US/about/forums/#dev-security">mailing list</a>.</p>
<p>Google provides some interesting statistics about what their systems detect in their
<a href="https://www.google.com/transparencyreport/safebrowsing/">transparency report</a>
and offers a tool to find out
<a href="https://www.google.com/transparencyreport/safebrowsing/diagnostic/">why a particular page has been blocked</a>.
Some information on
<a href="https://security.googleblog.com/2010/03/phishing-phree.html">how phishing sites are detected</a>
is also available on the Google Security blog, but for more detailed information
about all parts of the Safe Browsing system, see the following papers:</p>
<ul>
<li><a href="http://research.google.com/archive/provos-2008a.pdf">All Your IFrames Are Belong to Us</a></li>
<li><a href="https://www.cs.jhu.edu/~moheeb/aburajab-ndss-13.pdf">Content-Agnostic Malware Protection</a></li>
<li><a href="http://www.usenix.org/event/hotbots07/tech/full_papers/provos/provos.pdf">Ghost in the Browser</a></li>
</ul>
Using OpenVPN on Android Lollipophttps://feeding.cloud.geek.nz/posts/using-openvpn-on-android-lollipop/
<a href="https://creativecommons.org/licenses/by-sa/4.0/">Creative Commons Attribution-ShareAlike 4.0 International License</a>
2022-11-19T07:11:46Z2015-04-03T03:45:00Z
<p>I use my personal server as a VPN endpoint for my laptop when I'm using untrusted networks and I
wanted to do the same on my Android 5 (Lollipop) phone.</p>
<p>It turns out that it's quite easy to do (doesn't require rooting your phone)
and that it works very well.</p>
<h2 id="Install_OpenVPN">Install OpenVPN</h2>
<p>Once you have <a href="https://feeding.cloud.geek.nz/posts/creating-a-linode-based-vpn-setup-using_openvpn_on_debian_or_ubuntu/">installed and configured OpenVPN on the
server</a>,
you need to install the OpenVPN app for Android (available both on
<a href="https://f-droid.org/repository/browse/?fdid=de.blinkt.openvpn">F-Droid</a> and
<a href="https://play.google.com/store/apps/details?id=de.blinkt.openvpn">Google
Play</a>).</p>
<p>From the <code>easy-rsa</code> directory you created while generating the server keys,
create a new keypair for your phone:</p>
<pre><code>./build-key nexus6 # "nexus6" as Name, no password
</code></pre>
<p>and then copy the following files onto your phone:</p>
<ul>
<li><code>ca.crt</code></li>
<li><code>nexus6.crt</code></li>
<li><code>nexus6.key</code></li>
<li><code>ta.key</code></li>
</ul>
<h2 id="Create_a_new_VPN_config">Create a new VPN config</h2>
<p>If you configured your server as per my instructions, these are the settings
you'll need to use on your phone:</p>
<p>Basic:</p>
<ul>
<li>LZO Compression: <code>NO</code></li>
<li>Type: <code>Certificates</code></li>
<li>CA Certificate: <code>ca.crt</code></li>
<li>Client Certificate: <code>nexus6.crt</code></li>
<li>Client Certificate Key: <code>nexus6.key</code></li>
</ul>
<p>Server list:</p>
<ul>
<li>Server address: <code>hafnarfjordur.fmarier.org</code></li>
<li>Port: <code>1194</code></li>
<li>Protocol: <code>UDP</code></li>
<li>Custom Options: <code>NO</code></li>
</ul>
<p>Authentication/Encryption:</p>
<ul>
<li>TLS Security Profile: <code>preferred</code></li>
<li>Expect TLS server certificate: <code>YES</code></li>
<li>Certificate hostname check: <code>YES</code></li>
<li>Remote certificate subject: <code>server</code></li>
<li>Use TLS Authentication: <code>YES</code></li>
<li>TLS Auth File: <code>ta.key</code></li>
<li>TLS Direction: <code>1</code></li>
<li>Encryption cipher: <code>AES-256-GCM</code></li>
<li>Packet authentication: <code>SHA512</code></li>
</ul>
<p>Advanced:</p>
<ul>
<li>Persistent tun: <code>YES</code></li>
</ul>
<p>That's it. Everything else should work with the defaults.</p>
Encrypted mailing list on Debian and Ubuntuhttps://feeding.cloud.geek.nz/posts/encrypted-mailing-list-on-debian-and-ubuntu/
<a href="https://creativecommons.org/licenses/by-sa/4.0/">Creative Commons Attribution-ShareAlike 4.0 International License</a>
2021-06-11T20:43:57Z2014-09-30T05:30:00Z
<p>Running an encrypted mailing list is surprisingly tricky. One of the first
challenges is that you need to decide what the threat model is. Are you
worried about someone compromising the list server? One of the subscribers
stealing the list of subscriber email addresses? You can't just "turn on
encryption", you have to think about what you're trying to defend against.</p>
<p>I decided to use <a href="https://schleuder2.nadir.org/">schleuder</a>. Here's how I
set it up.</p>
<h1 id="Requirements">Requirements</h1>
<p>What I decided to create was a mailing list where people could subscribe
and receive emails encrypted to them from the list itself. In order to
post, they need to send an email encrypted to the list' public key and
signed using the private key of a subscriber.</p>
<p>What the list then does is decrypt the email and encrypts it individually
for each subscriber. This protects the emails while in transit, but is
vulnerable to the list server itself being compromised since every list email
transits through there at some point in plain text.</p>
<h1 id="Installing_the_schleuder_package">Installing the schleuder package</h1>
<p>The first thing to know about installing schleuder on Debian or Ubuntu is
that at the moment it unfortunately depends on ruby 1.8. This means that you
can only install it on Debian wheezy or Ubuntu precise: trusty and jessie
won't work (until schleuder is ported to a more recent version of ruby).</p>
<p>If you're running wheezy, you're fine, but if you're running precise, I
recommend adding
<a href="https://launchpad.net/~fmarier/+archive/ubuntu/ppa?field.series_filter=precise">my ppa</a>
to your <code>/etc/apt/sources.list</code> to get a version of schleuder that actually
lets you create a new list without throwing an error.</p>
<p>Then, simply install this package:</p>
<pre><code>apt-get install schleuder
</code></pre>
<h1 id="Postfix_configuration">Postfix configuration</h1>
<p>The next step is to configure your mail server (I use <a href="http://www.postfix.org/">postfix</a>) to
handle the schleuder lists.</p>
<p>This may be obvious but if you're like me and you're repurposing a server
which hasn't had to accept incoming emails, make sure that postfix is set
to the following in <code>/etc/postfix/main.cf</code>:</p>
<pre><code>inet_interfaces = all
</code></pre>
<p>Then follow the instructions from
<a href="http://sources.debian.net/src/schleuder/2.2.1-2%2Bdeb7u1/debian/README.Debian/#L86">/usr/share/doc/schleuder/README.Debian</a>
and finally add the following line (thanks to the <a href="https://schleuder2.nadir.org/contrib/postfix_transport.html">wiki
instructions</a>)
to <code>/etc/postfix/main.cf</code>:</p>
<pre><code>local_recipient_maps = proxy:unix:passwd.byname $alias_maps $transport_maps
</code></pre>
<h1 id="Creating_a_new_list">Creating a new list</h1>
<p>Once everything is set up, creating a new list is pretty easy. Simply run
<code>schleuder-newlist list@example.org</code> and follow the instructions.</p>
<p>After creating your list, remember to update <code>/etc/postfix/transports</code> and
run <code>postmap /etc/postfix/transports</code>.</p>
<p>Then you can test it by sending an email to
<code>LISTNAME-sendkey@example.com</code>. You should receive the list's public key.</p>
<h1 id="Adding_list_members">Adding list members</h1>
<p>Once your list is created, the list admin is the only subscriber. To add
more people, you can send an <a href="http://sources.debian.net/src/schleuder/2.2.1-2%2Bdeb7u1/debian/README.Debian/#L29">admin
email</a>
to the list or follow <a href="https://schleuder2.nadir.org/contrib/creating_lists_with_postfix.html">these
instructions</a>
to do it manually:</p>
<ol>
<li>Get the person's GPG key: <code>gpg --recv-key KEYID</code></li>
<li>Verify that the key is trusted: <code>gpg --fingerprint KEYID</code></li>
<li>Add the person to the list's <code>/var/lib/schleuder/HOSTNAME/LISTNAME/members.conf</code>:
<pre><code>- email: francois@fmarier.org
key_fingerprint: 8C470B2A0B31568E110D432516281F2E007C98D1
</code></pre></li>
<li>Export the public key: <code>gpg --export -a KEYID</code></li>
<li><p>Paste the exported key into the list's keyring:</p>
<pre><code>sudo -u schleuder gpg --homedir /var/lib/schleuder/HOSTNAME/LISTNAME/ --import
</code></pre></li>
</ol>
<h1 id="Signing_the_list_key">Signing the list key</h1>
<p>In order to give assurance to list members that the list key is legitimate,
it should be signed by the list admin.</p>
<ol>
<li><p>Export the key:</p>
<pre><code>sudo -u schleuder gpg --homedir /var/lib/schleuder/HOSTNAME/LISTNAME/ -a --export LISTNAE@HOSTNAME > ~/LISTNAME.asc
</code></pre></li>
<li>Copy the key onto your own machine using scp and import it: <code>gpg --import < LISTNAME.asc</code></li>
<li>Sign the key locally by editing the key <code>gpg --edit-key KEYID</code> and using the <code>sign</code> command.</li>
<li>Export your signature: <code>gpg -a --export KEYID > LISTNAME.asc</code></li>
<li>Copy the signed key back onto the server using scp.</li>
<li><p>Import your signature into the schleuder public keyring:</p>
<pre><code>sudo -u schleuder gpg --homedir /var/lib/schleuder/HOSTNAME/LISTNAME/ --import < ~/LISTNAME.asc
</code></pre></li>
</ol>
<p>After that, anybody requesting the list key will get your signature as well.</p>
Hardening ssh Servershttps://feeding.cloud.geek.nz/posts/hardening-ssh-servers/
<a href="https://creativecommons.org/licenses/by-sa/4.0/">Creative Commons Attribution-ShareAlike 4.0 International License</a>
2022-09-13T22:57:03Z2014-02-20T10:52:00Z
<p>These are the settings that I use to harden ssh on my servers and clients.</p>
<h1 id="Basic_server_configuration">Basic server configuration</h1>
<p>There are a few basic things that most admins will already know (and that
<a href="http://savannah.nongnu.org/projects/tiger/">tiger</a> will warn you about if
you forget):</p>
<ul>
<li>disable root logins</li>
<li>disable password authentication</li>
</ul>
<p>If you are using <a href="http://rkhunter.sourceforge.net/">rkhunter</a>, you will need
to disable the check for root logins since <a href="https://sourceforge.net/p/rkhunter/bugs/151/">rkhunter doesn't check
non-default config files</a>.
This is what I put in <code>/etc/rkhunter.conf.local</code>:</p>
<pre><code>ALLOW_SSH_ROOT_USER=unset
</code></pre>
<p>This is what my <code>/etc/ssh/sshd_config.d/local.conf</code> contains:</p>
<pre><code>AuthorizedKeysFile .ssh/authorized_keys
AcceptEnv LANG LC_* TZ
HostKey /etc/ssh/ssh_host_ed25519_key
KexAlgorithms curve25519-sha256@libssh.org,curve25519-sha256,diffie-hellman-group14-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group-exchange-sha256
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com
AuthenticationMethods publickey
LogLevel VERBOSE
PermitRootLogin no
</code></pre>
<p>in order to also prevent the use of problematic or weak cryptographic algorithms.</p>
<p>Once you've done that, make sure you have all of the required host keys by running:</p>
<pre><code>ssh-keygen -A
</code></pre>
<p>as root.</p>
<p>The above configuration is based on the <a href="https://infosec.mozilla.org/guidelines/openssh#modern-openssh-67">Mozilla
recommendations</a>
and then tightened up using the
<a href="https://github.com/jtesta/ssh-audit"><code>ssh-audit</code></a> package.</p>
<p>While Mozilla recommends disabling short Diffie-Hellman moduli:</p>
<pre><code>awk '$5 >= 3071' /etc/ssh/moduli > /etc/ssh/moduli.tmp
mv /etc/ssh/moduli.tmp /etc/ssh/moduli
</code></pre>
<p>that ends up being very annoying since it causes merge conflicts on distro
upgrades.</p>
<p>Finally, if you don't need <code>sftp</code> support, Mozilla recommends disabling it,
which can be done by commenting out this line in <code>/etc/ssh/sshd_config</code>:</p>
<pre><code>#Subsystem sftp /usr/lib/openssh/sftp-server
</code></pre>
<p>On the other hand, if you do need it, it's generally better to replace it
with the <a href="https://serverfault.com/questions/660160/openssh-difference-between-internal-sftp-and-sftp-server#660325">internal sftp
server</a>:</p>
<pre><code>Subsystem sftp internal-sftp
</code></pre>
<h1 id="Whitelist_approach_to_giving_users_ssh_access">Whitelist approach to giving users ssh access</h1>
<p>To ensure that only a few users have ssh access to the server and that newly
created users don't have it enabled by default, create a new group:</p>
<pre><code>addgroup sshuser
</code></pre>
<p>and then add the relevant users to it:</p>
<pre><code>adduser francois sshuser
</code></pre>
<p>Finally, add this to <code>/etc/ssh/sshd_config.d/local.conf</code>:</p>
<pre><code>AllowGroups sshuser
</code></pre>
<h1 id="Deterring_brute-force_.28or_dictionary.29_attacks">Deterring brute-force (or dictionary) attacks</h1>
<p>One way to ban attackers who try to brute-force your ssh server is to
install the <a href="http://www.fail2ban.org/wiki/index.php/Main_Page">fail2ban</a>
package. It keeps an eye on the ssh log file (<code>/var/log/auth.log</code>) and
temporarily blocks IP addresses after a number of failed login attempts.</p>
<p>To prevent your own IP addresses from being blocked, add them to
<code>/etc/fail2ban/jail.d/local.conf</code>:</p>
<pre><code>[DEFAULT]
ignoreip = 127.0.0.1/8 1.2.3.4
</code></pre>
<p>Another approach is to hide the ssh service using
<a href="http://en.wikipedia.org/wiki/Single_Packet_Authorization">Single-Packet Authentication</a>. I
have <a href="http://www.cipherdyne.org/fwknop/">fwknop</a> installed on some of my
servers and use small
<a href="https://github.com/fmarier/user-scripts/blob/master/spassh">wrapper</a>
<a href="https://github.com/fmarier/user-scripts/blob/master/spascp">scripts</a>
to connect to them.</p>
<h1 id="Restricting_shell_access">Restricting shell access</h1>
<p>For those users who only need an ssh account on the server in order to
transfer files (using <code>scp</code> or <code>rsync</code>), it's a good idea to restrict their
access further. I used to switch these users' shell (via <a href="http://linux.die.net/man/1/chsh">chsh</a>) to a restricted one like
<a href="http://www.pizzashack.org/rssh/">rssh</a>, but that project has been
<a href="https://tracker.debian.org/news/1033905/removed-234-12-from-unstable/">abandoned</a>.</p>
<p>I now use a <a href="https://www.allthingsdigital.nl/2013/05/12/setting-up-an-sftp-only-account-with-openssh/">different
approach</a>
which consists of using an essentially empty chroot for these users and
limiting them to <code>internal-sftp</code> by putting the following in
<code>/etc/ssh/sshd_config</code>:</p>
<pre><code>Match Group sftponly
ForceCommand internal-sftp
ChrootDirectory /mnt/data
</code></pre>
<p>creating a group:</p>
<pre><code>adduser sftponly
</code></pre>
<p>and a base chroot directory:</p>
<pre><code>mkdir -p /mnt/data/home
</code></pre>
<p>Note that the base directory, and each parent directory all the way to the
root directory, must be owned by <code>root:root</code> (user <strong>and</strong> group) otherwise
you'll see an unhelpful error message like this when you try to connect via
sftp:</p>
<pre><code>$ sftp user1@server.example
client_loop: send disconnect: Broken pipe
</code></pre>
<p>Then for each user, we need to do the following:</p>
<pre><code>adduser user1 sftp-only
chsh user1 -s /bin/false
mkdir -p /mnt/data/home/user1
chown user1:user1 /mnt/data/home/user1
chmod 700 /mnt/data/home/user1
</code></pre>
<p>before restarting the ssh daemon:</p>
<pre><code>systemctl restart sshd.service
</code></pre>
<p>Should one of these users attempt to connect via ssh instead of stp, they
will see the following:</p>
<pre><code>$ ssh user1@server.example
This service allows sftp connections only.
Connection to server.example closed.
</code></pre>
<h1 id="Restricting_authorized_keys_to_certain_IP_addresses">Restricting authorized keys to certain IP addresses</h1>
<p>In addition to listing all of the public keys that are allowed to log into a
user account, the <code>~/.ssh/authorized_keys</code> file also allows (as the
<a href="http://www.openbsd.org/cgi-bin/man.cgi?query=sshd&sektion=8#SSHRC">man page</a>
points out) a user to impose a number of restrictions.</p>
<p>Perhaps the most useful option is <em>from</em> which allows a user to restrict the
IP addresses which can login using a specific key.</p>
<p>Here's what one of my <code>authorized_keys</code> looks like:</p>
<pre><code>from="192.0.2.2" ssh-rsa AAAAB3Nz...zvCn bot@example
</code></pre>
<p>You may also want to include the <code>restrict</code> option to each entry since it
will automatically disable powerful features.</p>
<h1 id="Client_configuration">Client configuration</h1>
<p>Since servers can sometimes create outbound ssh connections, for example as
part of an offsite backup, I tighten up the ssh client configuration on all
of my machines by putting the following in
<code>/etc/ssh/ssh_config.d/local.conf</code>:</p>
<pre><code>HostKeyAlgorithms ssh-ed25519-cert-v01@openssh.com,ssh-ed25519
KexAlgorithms curve25519-sha256@libssh.org,curve25519-sha256,diffie-hellman-group18-sha512,diffie-hellman-group16-sha512,diffie-hellman-group14-sha256,diffie-hellman-group-exchange-sha256
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
</code></pre>
<p>again, based on the <a href="https://infosec.mozilla.org/guidelines/openssh#modern">Mozilla
recommendations</a>
modified according to the
<a href="https://packages.debian.org/stable/ssh-audit">ssh-audit</a> report.</p>
<p>Note that if you need to connect to <a href="https://launchpad.net/">Launchpad</a>, you'll
need to relax these settings in your <code>~/.ssh/config</code>:</p>
<pre><code>Host *.launchpad.net
HostKeyAlgorithms rsa-sha2-512
MACs hmac-sha2-512
</code></pre>
Creating a Linode-based VPN setup using OpenVPN on Debian or Ubuntuhttps://feeding.cloud.geek.nz/posts/creating-a-linode-based-vpn-setup-using_openvpn_on_debian_or_ubuntu/
<a href="https://creativecommons.org/licenses/by-sa/4.0/">Creative Commons Attribution-ShareAlike 4.0 International License</a>
2023-12-22T05:40:11Z2013-12-22T10:00:00Z
<p>Using a
<a href="https://en.wikipedia.org/wiki/Virtual_private_network">Virtual Private Network</a>
is a good way to work-around
<a href="https://en.wikipedia.org/wiki/Geolocation">geoIP</a> restrictions but also to
protect your network traffic when travelling with your laptop and connecting
to untrusted networks.</p>
<p>While you might want to
<a href="https://feeding.cloud.geek.nz/posts/things-that-work-well-with-tor/">use Tor</a>
for the part of your network activity where you prefer to be anonymous, a
VPN is a faster way to connect to sites that already know you.</p>
<p>Here are my instructions for setting up <a href="http://openvpn.net/">OpenVPN</a> on
Debian / Ubuntu machines where the VPN server is located on a cheap
<a href="https://www.linode.com/">Linode</a>
virtual private server. They are largely based on the
<a href="https://wiki.debian.org/openvpn%20for%20server%20and%20client">instructions found on the Debian wiki</a>.</p>
<p>An easier way to setup an ad-hoc VPN is to use
<a href="https://github.com/apenwarr/sshuttle">sshuttle</a> but for some reason, it
doesn't seem work on Linode or Rackspace virtual servers.</p>
<h1 id="Generating_the_keys">Generating the keys</h1>
<p>Make sure you run the following on a machine with good entropy and not a VM!
I personally use a machine fitted with a
<a href="http://shop.gag.com/logo-items/chaoskey.html">Chaos Key</a>.</p>
<p>The first step is to install the required package:</p>
<pre><code>sudo apt-get install easy-rsa openvpn
</code></pre>
<p>Then, copy the following file in your home directory (no need to run any of
this as root):</p>
<pre><code>mkdir easy-rsa
cp -ai /usr/share/easy-rsa/* easy-rsa/
cd easy-rsa/
</code></pre>
<p>and put something like this in your <code>~/easy-rsa/vars</code>:</p>
<pre><code>export KEY_SIZE=2048
export KEY_COUNTRY="NZ"
export KEY_PROVINCE="AKL"
export KEY_CITY="Auckland"
export KEY_ORG="fmarier.org"
export KEY_EMAIL="francois@fmarier.org"
export KEY_CN="hafnarfjordur.fmarier.org"
export KEY_NAME="hafnarfjordur.fmarier.org"
export KEY_OU="VPN"
export KEY_ALTNAMES=""
</code></pre>
<p>Create this symbolic link:</p>
<pre><code>ln -s openssl-1.0.0.cnf openssl.cnf
</code></pre>
<p>and set the following in <code>openssl.cnf</code>:</p>
<pre><code>default_crl_days= 3650
</code></pre>
<p>to avoid having the <a href="https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=849909">CRL expire after one month</a> and throw this error in the logs:</p>
<pre><code>VERIFY ERROR: depth=0, error=CRL has expired:
</code></pre>
<p>Finally, generate the keys:</p>
<pre><code>. ./vars
./clean-all
./build-ca # press ENTER at every prompt
./build-key-server server # press ENTER at every prompt, no password
./build-key akranes # "akranes" as Name, no password
./build-dh
/usr/sbin/openvpn --genkey --secret keys/ta.key
</code></pre>
<h1 id="Configuring_the_server">Configuring the server</h1>
<p>On my server, called <code>hafnarfjordur.fmarier.org</code>, I installed the
<a href="http://packages.debian.org/stable/openvpn">openvpn package</a>:</p>
<pre><code>apt-get install openvpn
</code></pre>
<p>and then copied the following files from my high-entropy machine:</p>
<pre><code>cp ca.crt dh2048.pem server.key server.crt ta.key /etc/openvpn/
touch /etc/openvpn/crl.pem
chown root:root /etc/openvpn/*
chmod 600 /etc/openvpn/ta.key /etc/openvpn/server.key
</code></pre>
<p>Then I took the official configuration template:</p>
<pre><code>cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz /etc/openvpn/
gunzip /etc/openvpn/server.conf.gz
</code></pre>
<p>and set the following in <code>/etc/openvpn/server.conf</code> (which includes recommendations from <a href="https://bettercrypto.org/">BetterCrypto.org</a> and <a href="https://blog.g3rt.nl/openvpn-security-tips.html">Gert van Dijk</a>):</p>
<pre><code>dh dh2048.pem
topology subnet
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 74.207.241.5"
push "dhcp-option DNS 74.207.242.5"
tls-auth ta.key 0
auth SHA512
tls-cert-profile preferred
tls-version-min 1.3
cipher AES-256-GCM
user nobody
group nogroup
crl-verify crl.pem
</code></pre>
<p>(These DNS servers are the ones I found in <code>/etc/resolv.conf</code> on my Linode VPS.)</p>
<p>Finally, I added the following to these configuration files:</p>
<ul>
<li><p><code>/etc/sysctl.d/openvpn.conf</code>:</p>
<pre><code>net.ipv4.ip_forward=1
net.ipv4.conf.all.rp_filter=1
</code></pre></li>
<li><p><code>/etc/rc.local</code> (just before <code>exit 0</code>):</p>
<pre><code>iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
</code></pre></li>
<li><p><code>/etc/default/openvpn</code>:</p>
<pre><code>AUTOSTART="all"
</code></pre></li>
</ul>
<p>and ran <code>sysctl -p</code> before starting OpenVPN:</p>
<pre><code>/etc/init.d/openvpn start
</code></pre>
<p>If the server has a firewall, you'll need to <a href="http://docs.openvpn.net/frequently-asked-questions/">open up this port</a>:</p>
<pre><code>iptables -A INPUT -p udp --dport 1194 -j ACCEPT
</code></pre>
<p>as well as let <a href="https://wiki.debian.org/OpenVPN#Forward_traffic_via_VPN">forwarded packets</a> flow:</p>
<pre><code>iptables -A FORWARD -i eth0 -o tun0 -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -s 10.8.0.0/24 -o eth0 -j ACCEPT
</code></pre>
<h1 id="Configuring_the_client">Configuring the client</h1>
<p>The final piece of this solution is to setup my laptop, <code>akranes</code>, to
connect to <code>hafnarfjordur</code> by installing the relevant
<a href="https://wiki.gnome.org/Projects/NetworkManager/">Network Manager</a> plugin:</p>
<pre><code>apt-get install network-manager-openvpn-gnome openvpn-systemd-resolved
</code></pre>
<p>The laptop needs these files from the high-entropy machine:</p>
<pre><code>cp ca.crt akranes.crt akranes.key ta.key /etc/openvpn/
chown root:francois /etc/openvpn/akranes.key /etc/openvpn/ta.key
chmod 640 /etc/openvpn/ta.key /etc/openvpn/akranes.key
</code></pre>
<p>and my own user needs to have read access to the secret keys.</p>
<p>To create a new VPN, right-click on Network-Manager and add a new VPN
connection of type "OpenVPN":</p>
<ul>
<li>Gateway: <code>hafnarfjordur.fmarier.org</code></li>
<li>Type: <code>Certificates (TLS)</code></li>
<li>User Certificate: <code>/etc/openvpn/akranes.crt</code></li>
<li>CA Certificate: <code>/etc/openvpn/ca.crt</code></li>
<li>Private Key: <code>/etc/openvpn/akranes.key</code></li>
<li>Available to all users: <code>NO</code></li>
</ul>
<p>then click the "Avanced" button and set the following:</p>
<ul>
<li>Security
<ul>
<li>Cipher: <code>AES-256-GCM</code></li>
<li>HMAC Authentication: <code>SHA512</code></li>
</ul>
</li>
<li>TLS Authentication
<ul>
<li>Server Certificate Check: <code>Verify name exactly</code></li>
<li>Subject Match: <code>server</code></li>
<li>Verify peer (server) certificate usage signature: <code>YES</code>
<ul>
<li>Remote peer certificate TLS type: <code>Server</code></li>
</ul>
</li>
<li>Verify peer (server) certificate nsCertType designation: <code>YES</code>
<ul>
<li>Remove peer certificate nsCert designation: <code>Server</code></li>
</ul>
</li>
<li>Additional TLS authentication or encryption:
<ul>
<li>Mode: <code>TLS-Auth</code></li>
<li>Key File: <code>/etc/openvpn/ta.key</code></li>
<li>Key Direction: <code>1</code></li>
</ul>
</li>
</ul>
</li>
</ul>
<p>There are also compatible clients on <a href="https://feeding.cloud.geek.nz/posts/using-openvpn-on-android-lollipop/">Android</a>, <a href="https://feeding.cloud.geek.nz/posts/using-openvpn-on-ios-and-osx/">iOS and OSX</a>.</p>
<h1 id="Debugging">Debugging</h1>
<p>If you run into problems, simply take a look at the logs while attempting to
connect to the server:</p>
<pre><code>tail -f /var/log/syslog
</code></pre>
<p>on both the server and the client.</p>
<p>In my experience, searching for the error messages you find in there is
usually enough to solve the problem.</p>
<h1 id="Next_steps">Next steps</h1>
<p>With the basics working, you could now
<a href="https://feeding.cloud.geek.nz/posts/ipv6-and-openvpn-on-linode/">add support for IPv6</a>
to your VPN.</p>
<p>The next thing I'm going to add to this VPN setup is a
<a href="https://feeding.cloud.geek.nz/posts/setting-up-your-own-dnssec-aware/">local unbound DNS resolver</a>
that will be offered to all clients.</p>
<p>Is there anything else you have in your setup and that I should consider
adding to mine?</p>