Site-To-Site OpenVPN mit Linksys WRT54GL und Shorewall Firewall

Es hat mich schon einige Stunden gekostet, bis ich endlich ein Site-to-Site VPN zwischen zwei Netzen aufgebaut bekommen habe mit OpenVPN. Um Leuten mit einem ähnlichen oder gleichem Vorhaben Zeit zu sparen, möchte ich hier Details bekannt geben zu meinem Setup. Mit folgenden Anleitungen bin ich dann doch noch zügig zu meinem Ziel gekommen, zwei Standorte miteinander zu verbinden:

Es gibt 2 private Netze:

A) 10.10.10.0/24 (VPN-Server, server.dyndns.org)
B) 192.168.1.0/24 (VPN-Client, client.dyndns.org)

Ip-Adressen
Ip-Adressen

Beide Netze sind über einen normalen ADSL-Router an das Internet angeschlossen. Auf dem ADSL-Router aus Netz A läuft ein OpenVPN service, der auf der öffentlichen, dynamischen IP-Adresse lauscht. Auf dem ADSL-Router aus Netz B läuft ein VPN-Client. Die öffentliche Adresse des Clients ist ebenfalls dynamisch.Um das Problem der dynamischen IP-Adressen zu lösen benutze ich auf beide Seiten den dyndns.org Dienst.

Der ADSL-Router von Netz A (Server) ist ein debian etch System mit der shorewall Firewall in Version 4.2.1 auf der ich entsprechend Port 1194 UDP geöffnet habe für Zugriff von Außen.
Der ADSL-Router von Netz B (Client) ist ein Linksys WRT54GL mit der dd-wrt Firmware Version 2.4 (SP1) in der VPN Version.

Das Webinterface des dd-wrt bietet leider nur relativ unflexible Möglichkeiten den OpenVPN Client einzurichten. Deswegen habe ich mich entschlossen den Client per Web-GUI abgeschaltet zu lassen uns lieber selbst für den Start und die Konfiguration des VPN-Client zu sorgen. Leider kann man nicht einfach config-dateien schreiben und im Dateisystem speichern. Diese gehen nach einem Neustart verloren. Deswegen muss man mit dem nvram arbeiten. Hier kann man Parameter, Configs und auch Zertifikats- oder Keydateien ablegen.
Wenn man sich per telnet oder besser ssh mit dem linksys verbindet, kann man sich per:

nvram show

alle im nicht-flüchtigen NVRAM gespeicherten Parameter des Linksys ansehen. Nun kann man eigene “Variablen” anlegen, die dann z.B. die client.conf beinhalten und die Inhalte der .crt, .ca und .key Dateien. Wie man mit dem NVRAM arbeitet lässt sich hier nachlesen.

Nun legt man die Variablen mit Inhalt an, um sie dauerhaft im NVRAM zu speichern:

nvram set client_conf=”dev tun
local client.dyndns.org
remote server.dyndns.org
ifconfig 10.10.40.2. 10.10.40.1
route 10.10.10.0 255.255.255.0 10.10.40.1
tls-client
cipher DES-EDE3-CBC
ca /tmp/openvpn/ca.crt
cert /tmp/openvpn/client.crt
key /tmp/openvpn/client.key
comp-lzo
verb 4
keepalive 20 180″

nvram set ca_crt=”—–BEGIN CERTIFICATE—–
safjkldsöjfkaji39prj2389hr89w3hozaf789h usw etc.pp
—–END CERTIFICATE—–”

nvram set client_crt=”—–BEGIN CERTIFICATE—–
safjkldsöjfkaji39prj2389hr89w3hozaf789h usw etc.pp
—–END CERTIFICATE—–”

nvram set client_key=”—–BEGIN RSA PRIVATE KEY—–
safjkldsöjfkaji39prj2389hr89w3hozaf789h usw etc.pp
—–END RSA PRIVATE KEY—–“

Anschließend speichert man die mit

nvram commit

noch die Eingaben dauerhaft im NVRAM. Jetzt haben wir schonmal die client-config gespeichert und die zugehörigen Dateien. Wenn man nun den Router neustartet und mit

nvram get client_conf
nvram get ca_crt
nvram get client_key
nvram get client_crt

eine entsprechende Ausgabe bekommt, hat das Speichern funktioniert. Geht man jetzt in das webinterface des WRT unter “Administration” auf “Commands” kann man ein Startskript schreiben, welches:

  1. Die NVRAM Parameter ausliest und in Dateien schreibt
  2. Die Firewall entsprechend auf die VPN-Verbindung vorbereitet und
  3. die VPN Verbindung automatisch herstellt.

Startskript:

sleep 10
iptables -I INPUT 2 -p udp –dport 1194 -j ACCEPT
iptables -I INPUT -i tun0 -j ACCEPT
iptables -I FORWARD -i br0 -o tun0 -j ACCEPT
iptables -I FORWARD -i tun0 -o br0 -j ACCEPT
sleep 10
mkdir /tmp/openvpn/
nvram get ca_crt > /tmp/openvpn/ca.crt
nvram get client_crt > /tmp/openvpn/client.crt
nvram get client_key > /tmp/openvpn/client.key
nvram get client_conf > /tmp/openvpn/client.conf
sleep 1
killall openvpn
sleep 11
openvpn –config /tmp/openvpn/client.conf &

Leider startet bei mir noch nicht der VPN-Dienst automatisch. Ich muss derzeit leider noch per cli die VPN-Verbindung starten:

openvpn –config /tmp/openvpn/client.conf &

Nun kann man mit

ifconfig tun0

auf beiden Routern prüfen, ob die VPN-Verbindung steht und ggf. mit ping in das jeweils andere Netz hinein pingen.

Hier noch die Konfiguration (server.conf) des VPN-Dienstes auf dem VPN-Server:

dev tun
local server.dyndns.org
remote client.dyndns.org
ifconfig 10.10.40.1 10.10.40.2
route 192.168.1.0 255.255.255.0 10.10.40.2
tls-server
comp-lzo
ca /etc/openvpn/keys/ca.crt
cert /etc/openvpn/keys/server.crt
key /etc/openvpn/keys/server.key  # This file should be kept secret
cipher DES-EDE3-CBC  # Triple-DES
dh /etc/openvpn/keys/dh2048.pem
keepalive 10 120
verb 3

Zu guter Letzt noch die Routing-Tabellen der beiden Router (statisch).

client-netz B (Linksys): (br0 ist die interne Schnittstelle)
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
10.10.40.1      *               255.255.255.255 UH    0      0        0 tun0
<<publicIP>>     *               255.255.255.255 UH    0      0        0 ppp0
192.168.1.0     *               255.255.255.0   U     0      0        0 br0
10.10.10.0      10.10.40.1      255.255.255.0   UG    0      0        0 tun0
169.254.0.0     *               255.255.0.0     U     0      0        0 br0
127.0.0.0       *               255.0.0.0       U     0      0        0 lo
default         <<public_dnsname> 0.0.0.0         UG    0      0        0 ppp0

server-netz A (debian): (br3 ist die interne Schnittstelle)
Ziel            Router          Genmask         Flags Metric Ref    Use Iface
<<poi>>  *               255.255.255.255 UH    0      0        0 ppp0
10.10.40.2      *               255.255.255.255 UH    0      0        0 tun0
192.168.1.0     10.10.40.2      255.255.255.0   UG    0      0        0 tun0
10.10.10.0      *               255.255.255.0   U     0      0        0 br3
default         *               0.0.0.0         U     0      0        0 ppp0