Sunday, 29. December 2013Week 51

Improve the security of your SSH private key files with PKCS#8

Instead of the easily brute-forceable one-pass MD5/AES128 password protection format used by SSH per default, you should use the PKCS#8 format to store your private key files. PKCS#8 allows to choose proper key-derivation functions and encryption schemes (for example PBKDF2 and PBES2).
The following commands convert an existing password protected SSH private key file to PKCS#8 format (using PBKDF2, PBES2 and AES-256):

mv ~/.ssh/id_rsa{,.old}
openssl pkcs8 -topk8 -v2 aes256 -in ~/.ssh/id_rsa.old -out ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
rm ~/.ssh/id_rsa.old

(via Martin Kleppmann)

Sunday, 15. December 2013Week 49

Make grep 50x faster

Found this neat trick in Brendan Gregg's Blazing Performance with Flame Graphs talk.

Switching to LANG=C improved performance by 2000x

In a quick test I directly got a performance gain of factor 50.22.
This is quite an achievement for only changing one environment variable.

real:~# du -sh /var/log/querylog 
148M	/var/log/querylog
real:~# time grep -i e /var/log/querylog > /dev/null 

real	0m12.807s
user	0m12.437s
sys	0m0.068s
real:~# time LANG=C grep -i e /var/log/querylog > /dev/null

real	0m0.255s
user	0m0.196s
sys	0m0.052s

I suspect that the performance gain may vary quite a lot depending on the search pattern. Also, please note that this trick only works when you know that the involved files and search patterns are ASCII only.

(via Standalone Sysadmin)

Sunday, 1. December 2013Week 47
Wednesday, 21. August 2013Week 33
Friday, 5. July 2013Week 26
Saturday, 1. June 2013Week 21

Run your own DynDNS server

After receiving yet another 'please login and click through our captcha for no reason' e-mail from a DynDNS provider, I decided to run my own DynDNS server.

As I already run my own DNS servers, this was just a matter of adding a dynamically updateable zone and writing a script which receives the IP change request via HTTP and sends out a DNS update.
Luckily the DynDNS API is quite well documented and I quickly came up with the PHP code below which performs the task well enough for me. Feel free to use it to run your own DynDNS server.

PS: to any friends reading this and looking for a DynDNS service: drop me a message and I'll set you up with an account.

Tuesday, 28. May 2013Week 21
Sunday, 26. May 2013Week 20
Saturday, 25. May 2013Week 20

less with colors

For a long time it annoyed me everytime that less only showed ASCII codes instead of colors when piping some 'color-enabled' output into it.

Turns out there is an easy fix for that:

colordiff a/foo b/foo | less -R

Thanks to Major Hayden for this very useful tip!

Wednesday, 27. February 2013Week 8
Monday, 25. February 2013Week 8

Orange Routing 2

I did another test of the Orange Routing.
Running a traceroute to my server in Zurich and one to my vhost in Frankfurt.
First another version of the already familier traceroute to my server in Zurich:

HOST: Andreass-MacBook-Pro.local  Loss%   Snt   Last   Avg  Best  Wrst StDev
  1.|-- 172.20.10.1                0.0%     5    8.0   3.7   2.1   8.0   2.5
  2.|-- 10.8.8.67                  0.0%     5  174.8 114.9  56.7 205.6  69.8
  3.|-- 10.8.12.10                 0.0%     5  126.8 108.4  67.7 171.3  42.8
  4.|-- 192.168.249.201            0.0%     5   73.4  82.7  61.9 111.5  20.5
  5.|-- 192.168.253.191            0.0%     5   54.0  64.9  54.0  75.9   9.3
  6.|-- 192.168.250.203            0.0%     5   64.7  69.2  57.3  79.2   8.4
  7.|-- 10.10.10.10                0.0%     5   56.8  65.5  56.8  72.1   7.7
  8.|-- 10.255.200.1               0.0%     5   65.9  87.3  60.1 146.6  35.1
  9.|-- pos0-1-1-1.gencr1.geneve.  0.0%     5   84.8 117.1  76.4 162.5  36.9
 10.|-- pos14-0-1.pascr4.paris.op  0.0%     5   88.1 118.0  88.1 168.3  36.7
 11.|-- ge6-0-0.br2.par2.alter.ne  0.0%     5   76.5  90.5  76.5 109.1  12.0
 12.|-- so-2-3-0.xt2.zur3.alter.n  0.0%     5   76.8 109.1  76.8 203.2  53.1
 13.|-- pos2-0.gw4.zur4.alter.net  0.0%     5   88.8  98.7  84.3 143.4  25.2
 14.|-- uch200193-gw.customer.alt  0.0%     5   90.7  85.3  74.1  93.5   8.0
 15.|-- whale29.open.ch            0.0%     5   88.9  97.7  88.9 104.7   6.3
 16.|-- orca8.open.ch              0.0%     5   90.8  94.8  90.8 102.8   4.9
 17.|-- real.jaggi.info           20.0%     5  234.8 130.0  92.8 234.8  69.9

Now the traceroute to the vhost in Frankfurt:

HOST: Andreass-MacBook-Pro.local  Loss%   Snt   Last   Avg  Best  Wrst StDev
  1.|-- 172.20.10.1                0.0%     5   15.2  13.1   1.9  44.5  18.4
  2.|-- 10.8.8.115                 0.0%     5   72.6  74.0  67.2  81.3   6.8
  3.|-- 10.8.12.10                 0.0%     5   80.7  75.0  64.0  89.6  10.3
  4.|-- 192.168.249.201            0.0%     5   65.1  78.9  65.1  94.0  12.3
  5.|-- 192.168.253.191            0.0%     5   73.1  70.4  66.5  73.3   2.8
  6.|-- 192.168.250.203            0.0%     5   69.5  73.9  66.3  86.6   7.7
  7.|-- 10.10.10.10                0.0%     5   67.0  72.7  67.0  80.0   4.9
  8.|-- 10.255.200.1               0.0%     5   70.9  74.4  69.7  86.4   7.0
  9.|-- pos0-1-1-1.gencr1.geneve.  0.0%     5   77.2  83.4  75.9  99.4   9.4
 10.|-- pos3-1-0.zurcr1.zurich.op  0.0%     5   83.8 103.2  83.8 146.9  26.3
 11.|-- pos0-9-4-0.ffttr1.frankfu  0.0%     5  102.9 103.6  98.7 108.8   4.9
 12.|-- leaseweb-9.gw.opentransit  0.0%     5   87.6  88.8  85.3  93.2   3.0
 13.|-- te3-1.core-2.fra.leaseweb  0.0%     5   85.4  91.5  85.4 106.1   8.5
 14.|-- hosted-by.leaseweb.com     0.0%     5   90.2  94.1  84.7 112.5  11.0
 15.|-- ???                       100.0     5    0.0   0.0   0.0   0.0   0.0
 16.|-- 0.jaggi.info              20.0%     5   89.9 117.5  86.3 205.5  58.7

As you can see, the RTT is higher for the server in Zurich than for the vhost in Frankfurt! (keep in mind that source of these measurement is my laptop in the train 8 minutes away from Zurich now)

So Orange has higher latency to hosts in the same region/city than to hosts in another country which are more than 350km away. :-(
The next time I choose a mobile provider it might be good to analyse its BGP peerings and routing policies first...

Orange Routing

While in the train from Bern to Zurich, I did a traceroute towards the server which currently hosts this weblog (it is located at Open Systems in Zurich). The connection starts on my laptop and is thethered via my cell to the Orange backbone.

HOST: Andreass-MacBook-Pro.local  Loss%   Snt   Last   Avg  Best  Wrst StDev
  1.|-- 172.20.10.1                0.0%     5    2.0  12.1   1.7  33.2  14.6
  2.|-- 10.8.8.67                  0.0%     5   52.2 373.4  52.2 1241. 504.8
  3.|-- 10.8.12.10                 0.0%     5   50.9 347.4  50.9 1143. 453.3
  4.|-- 192.168.249.201            0.0%     5   51.2 282.7  51.2 1042. 426.8
  5.|-- 192.168.253.191            0.0%     5   51.2 226.2  44.5 942.2 400.3
  6.|-- 192.168.250.203            0.0%     5   51.4 206.7  37.9 847.5 358.2
  7.|-- 10.10.10.10                0.0%     5   50.0 181.4  29.6 746.9 316.2
  8.|-- 10.255.200.1               0.0%     5   50.0 172.2  36.9 645.6 264.9
  9.|-- 193.251.248.145            0.0%     4   60.2  59.8  46.2  81.9  15.8
 10.|-- 193.251.240.53             0.0%     4   70.0  76.4  64.9 101.6  16.9
 11.|-- 146.188.112.77             0.0%     4   70.4  74.0  69.2  83.8   6.7
 12.|-- 146.188.5.1                0.0%     4   70.6  71.7  58.1  88.1  12.3
 13.|-- 146.188.4.194              0.0%     4   70.5  61.9  51.6  70.9  10.2
 14.|-- 146.188.64.74              0.0%     4   71.3  69.2  58.8  75.4   7.2
 15.|-- 213.156.230.29             0.0%     4   71.5  78.3  62.6 108.9  20.7
 16.|-- 213.156.229.8              0.0%     4   72.2  75.2  70.4  81.9   5.1
 17.|-- 213.156.229.222           25.0%     4   80.8  76.2  61.2  86.5  13.3

You can see that the traffic is passed through 8 different routers inside the Orange backbone (using IPs from all three RFC1918 ranges...) before it is let onto the Internet.
And then the real fun starts (let's use DNS names for this):

HOST: Andreass-MacBook-Pro.local  Loss%   Snt   Last   Avg  Best  Wrst StDev
  1.|-- 172.20.10.1                0.0%     5    2.0  12.2   1.9  33.3  14.5
  2.|-- 10.8.8.67                  0.0%     5   44.2 345.6  27.0 1167. 494.2
  3.|-- 10.8.12.10                 0.0%     5   52.2 308.9  27.0 1104. 462.4
  4.|-- 192.168.249.201            0.0%     5   33.4 264.9  27.2 1014. 427.1
  5.|-- 192.168.253.191            0.0%     5   30.3 227.5  27.3 952.9 406.4
  6.|-- 192.168.250.203            0.0%     5   50.4 200.7  27.0 860.0 368.7
  7.|-- 10.10.10.10                0.0%     5   72.4 193.5  30.5 779.2 327.8
  8.|-- 10.255.200.1               0.0%     5   31.8 166.8  27.6 688.0 291.5
  9.|-- pos0-1-1-1.gencr1.geneve.  0.0%     4   50.8  55.0  47.6  67.1   8.6
 10.|-- pos14-0-1.pascr4.paris.op  0.0%     4   61.0  64.4  57.7  78.5   9.5
 11.|-- ge6-0-0.br2.par2.alter.ne  0.0%     4   70.8  56.3  48.4  70.8   9.9
 12.|-- so-2-3-0.xt2.zur3.alter.n  0.0%     4  108.9  65.6  48.0 108.9  29.2
 13.|-- pos2-0.gw4.zur4.alter.net  0.0%     4   51.7  55.5  50.3  68.8   8.8
 14.|-- uch200193-gw.customer.alt  0.0%     4  171.8  83.6  50.7 171.8  58.8
 15.|-- whale29.open.ch            0.0%     4  132.1  90.0  59.2 132.1  32.7
 16.|-- orca8.open.ch              0.0%     4   72.4  66.8  58.6  73.5   7.3
 17.|-- real.jaggi.info           25.0%     4   80.2  64.7  56.2  80.2  13.4

As we see, Orange injects their mobile data traffic into the Internet in Geneva (pos0-1-1-1.gencr1.geneve.).
Then it is first sent to Paris (pas14-0-1.pascr4.paris.op and ge6-0-0.br2.par2.alter.ne) and from there back to Zurich (so-2-3-0.xt2.yur3.alter.n and all the following hosts).

I can kind of understand that the traffic is routed via Geneva (main Orange infrastructure is there), but why is it sent to Paris? (especially since Geneva<->Zurich is the main Internet connection inside Switzerland where most of the countries fiber is buried).

I guess this explains why my mobile data speed is not always as fast as I like it to be...

Monday, 18. February 2013Week 7

Administrative Distance

When using more than one dynamic routing protocol, make sure to know their administrative distance.

Further it is usually a bad idea to redistribute routes from a dynamic routing protocol into another one with a lower administrative distance. Especially when having multiple handover points between the two protocols.

Sunday, 17. February 2013Week 6
Thursday, 14. February 2013Week 6
Wednesday, 13. February 2013Week 6

Verify a BGP MD5 password before session turnup

When setting up a new BGP peering, you may want to test if your peering partner uses the correct MD5 password without bringing up your side of the session.
For this the tcpdump option -M can be used to supply the MD5 password when sniffing the traffic of the new peer:

tcpdump -ni eth0 -M MyBgPMd5PaSsWoRd tcp port 179

tcpdump will then verify the MD5 signature for every packet where it finds a MD5 signature TCP option as specified in RFC2385.
In the output you will see md5valid for packets where your password matches the MD5 signature or md5invalid for packets where your password does not match the MD5 signature.
If you see neither md5valid nor md5invalid then the peer did not configure any MD5 BGP password.

If you want to check for mismatching MD5 passwords after you bring up the BGP session, just look into the kernel log. Linux reports invalid MD5 TCP signatures like this:

MD5 Hash failed for (1.2.3.4, 56789)->(1.2.3.5, 179)
Tuesday, 5. February 2013Week 5

Configure unattached Bridge Interfaces in Debian

When working with virtualization technologies like KVM on Debian, you might need to configure bridge interfaces which are not attached to a physical interfaces (for example for a non-routed management network or similar).
Debian uses the directive bridge_ports in /etc/network/interfaces to indicate whether an interface is a bridge interface or not. The syntax checker does not accept an empty bridge_ports directive since he expects a list of physical interfaces to attach to the bridge interface.

When needing a bridge interface without any physical interfaces attached, usually people configure this interface by hand or with a special script.
Since I manage /etc/network/interfaces with my Puppet module, I would like to use it to configure all network interfaces including the unattached bridge interfaces.
It turns out that this can be done by passing none as parameter for the bridge_ports directive like this:

interface br0 inet static
	address 192.0.2.1
	netmask 255.255.255.0
	bridge_ports none
Saturday, 5. January 2013Week 0
Tuesday, 1. January 2013Week 0

HAVP PhishTank and Adserver Blacklist

For basic virus protection I'm running a proxy with HAVP and ClamAV.
Since some time I was using HAVPs blacklist functionality to block Ads (by blacklisting *.doubleclick.net and *.ivwbox.de). As such a manual blacklist is not very efficient I wanted to have an auto-updating list of adservers, thus I started to write the shellscript below which generates an up-to-date blacklist based on the adserverlist from pgl.yoyo.org.

Shortly after this I extended the script to also incorporate a Phising blacklist based on the data from PhishTank.
Currently I'm using the version below which runs in a cronjob every two hours and keeps the HAVP blacklist up-to-date. Please note that you need to insert your own free PhishTank API key when using this script.

#!/bin/sh

cd /etc/havp

OUTFILE=/etc/havp/blacklist

ADSERVERLIST=/etc/havp/adserverlist
PHISHTANK=/etc/havp/phishtank
MYBLACKLIST=/etc/havp/myblacklist

wget -q -N "http://pgl.yoyo.org/adservers/serverlist.php?hostformat=webwasher;showintro=0;mimetype=plaintext"
sed -e 's_^//_#_g' serverlist.php* | sort | uniq > $ADSERVERLIST

wget -q -N http://data.phishtank.com/data/<PhishTank API key>/online-valid.csv.bz2
bzcat online-valid.csv.bz2 | sed \
	-e 's/^[0-9]*,//' \
	-e 's@,http://www.phishtank.com/phish_detail.php?phish_id=[0-9]*,.*$@@' \
	-e 's/^"\(.*\)"$/\1/'  \
	-e 's_^https\?://__' \
	-e 's_/$_/*_' \
	-e 's_^\([^/]*\)$_\1/*_' \
	-e 's/?.*/*/' | \
grep -vF 'phish_id,url,phish_detail_url,submission_time,verified,verification_time,online,target' | \
iconv -f utf8 -t ascii -c - | sort | uniq > $PHISHTANK


echo "# blacklist file generated by $0, `date`" > $OUTFILE

echo "\n# MYBLACKLIST:" >> $OUTFILE
cat $MYBLACKLIST >> $OUTFILE

echo "\n# ADSERVERLIST:" >> $OUTFILE
cat $ADSERVERLIST >> $OUTFILE

echo "\n# PHISHTANK:" >> $OUTFILE
cat $PHISHTANK >> $OUTFILE