Freitag, 13. Juli 2012

iOS IPSec VPN - revisited

Klar man hat 'ne Fritz!Box zu Hause und sichert sich so in offen WLANs mit seinem iPhone/iPad/iPod dank des super Artikels bei Heise.

Wenn da nicht die Uplink-Beschränkung des heimischen DSL-Anschlusses wäre... Was liegt näher, als auf dem eigenen Root-Server ein IPSec VPN einzurichten - dass ich da nicht schon früher dran gedacht habe...


Nun ja das liegt sicher auch daran, dass IPSec bisher immer ein wenig speziell war. Zum einen konnte der Protokollstapel immens anwachsen IPSec/L2TP/PPP und zum anderen benötigten viele Firewalls bis vor wenigen Jahren spezielle IPSec NAT-Module. Daher war bisher ein SSL-VPN wie OpenVPN bisher das VPN meiner Wahl (zur not über TCP und Port 443, um auch in halbwegs gut abgeschotteten Netzen den Firmenserver zu erreichen).

Evtl. hat die erheblich gestiegene Installationsbasis (Mobilgeräte, Telefone) dazu beigetragen, plötzlich scheint IPSec auch für den roaming User eine Alternative zu sein.

Mit Racoon gibt es eine "übersichtliche" Implementierung ganz ohne L2TP und wenn man möchte, sogar ohne Client-Zertifikate. (Schließlich geht es ja nur darum, dass nicht jeder im öffentlichen WLAN meine Google-Anfragen mitlesen kann.) Sehr hilfreich war übrigens dieser Artikel.

In Debian Squeeze ist Racoon in der Version 0.7.3 enthalten, die ich im folgenden verwende. Während der Konfigurationsphase muss man sich entweder für die Konfiguration per racoon-tool oder direct entscheiden. Debian empfiehlt direct und daher lasse ich sämtliches Auftauchen von raccon-tool links liegen. Demzufolge ist /etc/racoon/racoon.cfg die einzige Konfigurationsdatei, die ich benötige.

Zunächst ein paar Anmerkungen zu den Zertifikaten:
Das Stammzertifikat und die Certificate Revocation List (crl.pem) liegt im Verzeichnis /etc/ssl/certs/. (Es immer eine gute Idee, gelegentlich das /etc/ssl/certs/ Verzeichnis mit c_rehash zu indiziereren - insbesondere wenn sich die Certificate Revocation List ändert).

Für den IPSec Server habe ich ein neues Zertifikat vpn.crt mit zugehörigem Schlüssel vpn.key erzeugt. Da der Schlüssel nicht per Passwort geschützt ist, erfährt er ein chmod 600 und gehört root. (Bei Debian liegen die Private Keys i.d.R. unter /etc/ssl/private/.)

Weil's geht, habe ich auch gleich noch einen racoon-Benutzer angelegt, so gibt es zukünftig einen priviligierten Hauptprozess und für die eigentlichen Verbindungen Prozesse mit weniger Rechten.

#
# /etc/racoon/racoon.conf
#

log warning;
#log info;

path pre_shared_key "/etc/racoon/psk.txt";
path certificate "/etc/racoon/certs";
path script "/etc/racoon/scripts";
path pidfile "/var/run/racoon.pid";

privsep {
        user "racoon";
        group "racoon";
}

listen {
        isakmp 1.2.3.4 [500];
        isakmp_natt 1.2.3.4 [4500];
        adminsock disabled;
}

# kein remote IP Filter, alle Verbindungen akzeptieren
remote anonymous {
        # wir initieren selbst keine Verbindung
        passive on;
        # mode Konfiguration einschalten (siehe unten(
        mode_cfg on;
        exchange_mode main,aggressive;
        my_identifier fqdn "vpn.meinserver.de";
        verify_identifier on;
        # Server Zertifikat
        certificate_type x509 "/etc/ssl/certs/vpn.crt" "/etc/ssl/private/vpn.key";
        # Stammzertifikat
        ca_type x509 "/etc/ssl/certs/ca.crt";
        ike_frag on;
        proposal_check claim;
        # die IPSec policies werden automatisch generiert
        generate_policy on;
        nat_traversal force;
        dpd_delay 20;
        proposal {
                # iOS kann aes256
                encryption_algorithm aes256;
                hash_algorithm sha1;
                # Authentifizierung via Benutzer/Password - keine Zertifikate
                authentication_method xauth_psk_server;
                # iOS unterstützt anscheinend nur 1024bit
                dh_group 2;
        }
}

sainfo anonymous {
        encryption_algorithm aes256;
        authentication_algorithm hmac_sha1;
        compression_algorithm deflate;
        lifetime time 1 hour;
        pfs_group 2;
}

mode_cfg {
        # logins werden via PAM geprüft
        auth_source pam;
        # nur Mitglieder der Gruppe VPN dürfen sich verbinden
        auth_groups "vpn";
        # Clients dürfen das Passwort speichern
        save_passwd on;
        # VPN IP pool
        pool_size 254;
        # erste IP Adresse des Pools
        network4 192.168.17.1;
        netmask4 255.255.255.0;
        # Hetzner DNS Server
        dns4 213.133.100.100;
        dns4 213.133.99.99;
        dns4 213.133.98.98;
        default_domain "meinserver.de";
        banner "/etc/racoon/motd";
        pfs_group 2;
}

Da die Initialisierung der Kommunikation auf einem gemeinsamen shared Secret basiert muss in die /etc/racoon/psk.txt noch ein Gruppenname Passwort Paar eingetragen werden:

# /etc/racoon/psk.txt
testgruppe    geheimes_test_passwort

Außerdem muss in der pam-Konfiguration noch ein Eintrag für den racoon-Daemon vorgenommen werden, der die Benutzer authentifizieren soll.

meinserver:~# cp /etc/pam.d/sshd /etc/pam.d/racoon

Der Serverstart verläuft nun problemlos, allerdings lässt sich der Dienst nicht korrekt per /etc/init.d/racoon stop anhalten (evtl. liegt es an der Privilege Separation). Ich habe kurzerhand das init-Script in /etc/init.d/racoon_server umbenannt und die start/stop Sektion folgendermaßen abgeändert:

#/etc/init.d/racoon_server
...
case "$1" in
 start)
  echo -n "Starting IKE (ISAKMP/Oakley) server: racoon"
  start-stop-daemon --start --quiet --exec /usr/sbin/racoon -- ${RACOON_ARGS}
  /sbin/iptables -t nat -A POSTROUTING -s 192.168.17.0/24 -j MASQUERADE
  echo "."
  ;;

 stop)
  echo -n "Stopping IKE (ISAKMP/Oakley) server: racoon"
  /sbin/iptables -t nat -D POSTROUTING -s 192.168.17.0/24 -j MASQUERADE
  start-stop-daemon --stop --quiet --name racoon
  rm -f $PID_FILE /var/run/racoon/racoon.sock
  echo "."
  ;;
...

Hier kann man auch gleich die IPTables-Einträge sehen, welche den Tunnelverkehr maskieren.