blog · git · desktop · images · contact
2015-03-24
Ich habe zuhause noch kein IPv6, aber einen Server im Internet mit einem /64-Netz. Weil ich trotzdem daheim damit experimentieren will, hatte ich mir vor einiger Zeit einen Tunnel gebaut, der SSH benutzt hat. Das war keine besonders tolle Lösung, aber sie hat erstmal funktioniert.
Jetzt habe ich mir die Sache noch einmal angeschaut und gesehen, dass OpenVPN mittlerweile (seit 2.3.0, also schon seit Januar 2013) nativ IPv6 kann. Das heißt, man kann direkt aus OpenVPN heraus IPv6-Adressen an die Clients vergeben und ist nicht mehr darauf angewiesen, mit OpenVPN nur eine IPv4-Verbindung aufzubauen, über die man dann zum Beispiel einen SIT-Tunnel aufbaut (siehe auch). Man braucht auch keinen radvd oder irgendwas in dieser Richtung, sondern OpenVPN verwaltet den IPv6-Adresskreis eigenständig.
Mal angenommen, man hat schon eine ganz einfache OpenVPN-Konfiguration so wie hier beschrieben, die dem Client eine private IPv4-Adresse zuweist. Dann kann man das auf Seite des Servers so erweitern:
tun-ipv6
server-ipv6 fd00:aaaa:bbbb:cccc::/112
push "route-ipv6 ::/0"
script-security 2
learn-address /etc/openvpn/scripts/learn-address
Ich habe einfach aus meinem /64er-Netz einen /112er-Block genommen, aus dem dann die Clients eine meiner öffentlichen IPv6-Adressen bekommen. Die gepushte Route erzeugt ein Default-Gateway für IPv6, sorgt also dafür, dass ein Client, der eigentlich nur in einem IPv4-Netz ist, seinen IPv6-Traffic über das VPN schickt.
Was hat es mit „learn-address
“ auf sich? Angenommen, man hat auf
eth0
eine öffentliche IPv4- und IPv6-Adresse des Servers:
$ ip -4 a show dev eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
inet 37.221.198.6/22 scope global eth0
valid_lft forever preferred_lft forever
$ ip -6 a show dev eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qlen 1000
inet6 2a03:4000:2:364:aec2:3146:f481:13f6/64 scope global
valid_lft forever preferred_lft forever
...
Durch das OpenVPN entsteht erst einmal nur zusätzlich ein tun0
. Damit
das ganze Konstrukt funktioniert, muss man dem Server noch sagen, dass
er auch auf eth0
auf Pakete reagieren muss, die an eine der
IPv6-Adressen der VPN-Clients adressiert sind. Erst dadurch landen
Antworten von Remotes beim Client und de facto hat der Client dann eine
IPv6-Adresse, über die er direkt aus dem Internet heraus erreichbar ist.
Sprich, er hängt mit dem nackten Hintern im Internet ohne den üblichen
„NAT-Schutz“ des DSL-Routers – you have been warned. Dafür ist
einerseits das Skript „learn-address
“ zuständig, das für jeden Client,
der sich erfolgreich verbunden hat, einen entsprechenden
NDP-Proxy-Eintrag auf eth0
anlegt und beim Disconnect wieder entfernt:
#!/bin/bash
action="$1"
addr="$2"
pubif=eth0
if [[ "${addr//:/}" == "$addr" ]]
then
# not an ipv6 address
exit
fi
case "$action" in
add|update)
ip neigh replace proxy "$addr" dev "$pubif"
;;
delete)
ip neigh del proxy "$addr" dev "$pubif"
;;
esac
(Wenn OpenVPN mit „user
“ und „group
“ Privilegien abgibt, dann muss
hier natürlich „sudo
“ im Spiel sein o.ä.)
Andererseits muss proxy_ndp
und Forwarding aktiviert sein, was man zum
Beispiel über eine /etc/sysctl.d/10-openvpn.conf
lösen kann:
net.ipv6.conf.all.forwarding = 1
net.ipv6.conf.all.proxy_ndp = 1
Das war’s.
Auf Seite des Clients muss man nur „tun-ipv6
“ einfügen.
Ich finde, das ist eine recht schnucklige Lösung. Einfach aufzubauen. Bis auf das mit dem NDP-Proxy und abgesehen vom üblichen PKI-Overhead von OpenVPN auch recht elegant.