Subject: WRT54GL mit OpenWRT Firmware und OpenVPN
From: Boris Kraut <[email-masked]>
To: undisclosed-recipients: ;
Date: Fri, 16 May 2008 00:00:00 +0000

OpenWRT [1] laesst sich bequem ueber das Webinterface der Original-Firmware
beziehungweise jeder anderen Custom-Firmware einspielen -in meinem Fall
DD-WRT [2]. Fuer den Linksys WRT54GL [3] muss man noch auf die Version mit dem
alten 2.4er Kernel (openwrt-wrt54g-2.4-squashfs.bin [4]) zurueckgreifen, da
die Treiber fuer die WLAN-Komponente momentan nur dort stabil laufen, wer
WLAN nicht braucht, kann auch die 2.6er Version nehmen. Vor dem Flashen
der Firmware sollte man per Reset-Knopf alles auf die Standard-Einstellungen
zuruecksetzen und nach dem Flashen auch gut ein paar Minuten warten bis
alles fertig ist.

Standardmaessig nimmt der Router nach dem Flashen die IP 192.168.1.1 an und
wartet auf dem Telnet-Port auf Befehle. Zu aller erst habe ich einige
Einstellungen vorgenommen, die verhinden sollen, dass ich das Geraet durch
unvorsichtige Spielereien in einen Haufen Elektroschrott verwandle:

$ telnet 192.168.1.1

$ nvram set boot_wait=on
$ nvram set boot_time=10
$ nvram commit && reboot

In einem zweiten Schritt vergebe ich ein Passwort fuer den root-Account.
OpenWRT stellt dann auch gleich von Telnet auf SSH um. Wer will kann ja
auch gleich noch von Passwort-Auth in der /etc/config/dropbear auststellen
und auf PublicKey umstellen, hierzu bitte ins OpenWRT-Wiki schauen, wo sich
ein eigener Eintrag dem Thema Dropbear Public Key Auth [5] widmet. Fuer die
Einrichtung des Routers reicht mir vorerst allerdings ein..

$ telnet 192.168.1.1

$ passwd
$ reboot

Bei den meisten Leuten soll ein Router vor allem einen Zugang zum Internet
herstellen, so auch bei mir. Ich stelle also zum einen die ueblichen DSL-
Angaben ein und aendere bei der Gelegenheit auch gleich noch die IP und den
Hostnamen des Routers. Das meiste kann man auch ueber die /etc/config/network
einstellen:

$ ssh [email-masked]

$ uci set network.lan.ipaddr="192.168.0.1"
$ uci set network.wan.proto=pppoe
$ uci set network.wan.username=DSLBENUTZER
$ uci set network.wan.password=DSLPASSWORT
$ uci commit network
$ uci set system.cfg1.hostname=XSPHOSTNAME
$ uci commit system
$ ifup wan && reboot

Um weitere Programme besonders einfach auf dem Geraet zum Laufen zu bringen,
bietet OpenWRT ein eigenes Repository, das man mit dem Werkzeug ipkg sich zu
Nutze machen kann. Ich verbinde mich also wieder per SSH mit dem Router und
aktualisiere die lokale Liste der vorhandenen Programme und fuehre gleich ein
Upgrade von wget durch, dass angeblich im momentanen Release von OpenWRT
fehlerhaft sein kann:

$ ssh [email-masked]

$ ipkg update
$ ipkg -force-overwrite install wget

Als naechstes moechte ich, dass ich auch von aussen ueber das Internet auf
meinen Router und das dahinter liegende Netzwerk zugreifen kann; was auch
spaeter  beim Einrichten des OpenVPN sehr wichtig werden wird. Da ich meine
IP-Adresse dynamisch von meinem Provider zugewiesen bekomme und weil ich
natuerlich mir auch die IP nicht wirklich merken will, habe ich mir schon
vor einiger Zeit einen Account bei dem DynDNS-Anbieter No-Ip [6] besorgt, den
ich jetzt vom Router aus aktualisieren lasse. Neben No-Ip kann mann auch
noch andere Anbieter nutzen, muss dann aber entsprechende AEnderungen
vornehmen; zoneedit, tzo, changeip, dyndns, hn, noip, eurodyndns,
ods, ovh und regfish sind moeglich. Weitere Informationen gibt es natuerlich
im OpenWRT-Wiki DDNS-HowTo [7]; die Konfigurationsdatei ist die
/etc/config/updatedd.

$ ipkg install updatedd updatedd-mod-noip
$ uci set updatedd.cfg1=updatedd
$ uci set updatedd.cfg1.service=noip
$ uci set updatedd.cfg1.username=NOIPBENUTZER
$ uci set updatedd.cfg1.password=NOIPPASSWORT
$ uci set updatedd.cfg1.host=NOIPHOSTNAME
$ uci set updatedd.cfg1.update=1
$ uci commit updatedd

Fuer die meisten ist es zwar eher uninteressant, ob auf dem Router die
richtige Uhrzeit eingestellt ist oder nicht, aber fuer Logdateien und spaeter
den OpenVPN-Einsatz ist es wichtig, einen korrekten Zeitgeber zu haben. Ich
lasse den Router ueber NTP die aktuelle Zeit vom Ubuntu-Server abrufen. Wer
zudem noch will, dass der Router die Zeit auch weiterverteilt, sollte
sich das openntpd-Paket anschauen. Mir genuegt der simple ntpclient:

$ ipkg install ntpclient
$ /usr/sbin/ntpclient -c 1 -s -h ntp.ubuntu.com
$ nvram set ntp_server=ntp.ubuntu.com
$ nvram set time_zone=UTC
$ nvram commit

Eher zufaellig habe ich festgestellt, dass standardmaessig ein HTTP-Server
gestartet wird, was mich ja bei DD-WRT schon sehr gestoert hat. Der Server
macht nicht viel, man kann ihn die Daten aus /www/ ausgeben lassen und wird
wohl fuer die optional verfuegbare GUI-Konfiguration benoetigt; ich dagegen
deaktiviere ihn also kurzer Hand:

$ /etc/init.d/httpd disable

Das Funknetzwerk ist dagegen standardmaessig deaktiviert und muss also erst
freigegeben werden. Ich stelle also den Channel und die SSID ein, sorge
dafuer, dass die SSID auch oeffentlich bekanntgegeben wird. Bei der
Verschluesselung kann man zwischen wep, wpa, wpa2, psk und psk2 waehlen. WPA
bezeichnet hier immer die Enterprise Variante, WPA Personal wird hier nach
dem Private Shared Key mit PSK bezeichnet.

$ ipkg install nas
$ uci set wireless.wl0.disabled=0
$ uci set wireless.wl0.channel=10
$ uci set wireless.cfg2.ssid=SSIDNAME
$ uci set wireless.cfg2.hidden=0
$ uci set wireless.cfg2.encryption=psk2
$ uci set wireless.cfg2.key=WPA2KEY
$ uci commit wireless && wifi

Weiterhin habe ich einige Einstellungen an der /etc/dnsmasq.conf vorgenommen,
die noch nicht ueber uci erreichbar sind:

> # hostname auf hostname.domain erweitern
> expand-hosts
>
> # Autoritativer Server
> dhcp-authoritative
>
> #
> domain=local
>
> # Rechner aus der Domain .local nur intern Aufloesen und nicht an einen
> # uebgergeordneten DNS-Server weitergeben; auch:
> # /local2.domain.tld/ip.ip.ip.ip. -  *.local2.domain.tld ueber ip.ip.ip.ip aufloesen
> # //ip.ip.ip.ip                   -  nicht FQDNs ueber ip.ip.ip.ip aufloesen
> # //                              -  FQDNslokal aufloesen
> local=/local/
>
> # Spezielle DHCP-Optionen; 3 gibt den Router an, 6 den DNS-Server. Weitere
> # Moeglichkeiten ueber dnsmasq --help dhcp.
> dhcp-option=3,192.168.0.1
> dhcp-option=6,192.168.0.1
>
> # Statische IPs an bestimme MAC-Adresse / Hostname vergeben:
> dhcp-host=MAC:MAC:MAC:MAC:MAC:MAC,HOSTNAME,IP.IP.IP.IP,infinite

OpenVPN zu installieren ist relativ einfach und laesst sich wieder ueber
ipkg erledigen. Weiterhin leg ich noch ein gesondertres Verzeichnis fuer
OpenVPN an.

$ ipkg install openvpn
$ mkdir /etc/openvpn/ && cd /etc/openvpn

Die noetigen Schluessel - genauere Informationen liefert die Webseite von
OpenVPN [8] - erstelle ich aufgrund der staerkeren Rechenleistung auf einem
richtigen Rechner mit OpenSSL und OpenVPN und kopiere sie dann auf den
Router. Fuer jeden Teilnehmer im VPN sollte man natuerlich eigene
Clientzertifikate erstellen, hier die markierten Zeilen:

$ openssl req -nodes -new -x509 -days 1825 -keyout ca.key -out ca.crt

$ openssl req -nodes -new -keyout server.key -out server.csr
$ openssl ca -cert ca.crt -keyfile ca.key -out server.crt -in server.csr

$ openssl req -nodes -new -keyout client.key -out client.csr
$ openssl ca -cert ca.crt -keyfile ca.key -out client.crt -in client.csr

$ openssl dhparam -out dh.pem 2048

$ openvpn --genkey --secret shared.key;

$ scp * [email-masked]:/etc/openvpn

Zurueck auf dem Router lege ich noch eine Konfigurationsdatei an:

$ cd /etc/openvpn
$ chmod 0600 /etc/openvpn/server.key
$ vi server.conf

> ### network options
> port 1194
> proto udp
> dev tun
> ### certificate and key files
> ca /etc/openvpn/ca.crt
> cert /etc/openvpn/server.crt
> key /etc/openvpn/server.key
> dh /etc/openvpn/dh.pem
> ### (optional) use a shared key to initialize TLS negotiation
> tls-auth /etc/openvpn/shared.key 0
> ### VPN subnet
> server 10.8.0.0 255.255.255.0
> ### (optional) make local network behind the VPN server accessible for the VPN clients
> push "route 192.168.1.0 255.255.255.0"
> ### (optional) make the VPN server a gateway for the internet for the VPN clients
> push "redirect-gateway"
> ### (optional) compression (might make your WRT sluggish or not, depending on the model and what you have running...)
> comp-lzo
> keepalive 10 120
> status /tmp/openvpn.status

Einen ersten Testlauf des Servers starte ich mit dem folgenden Befehl:

$ openvpn --config /etc/openvpn/server.conf

Da keine Fehler aufgetreten sind, aktiviere ich den OpenVPN-Server beim
Booten und starte danach den Router neu.

$ /etc/init.d/openvpn enable
$ reboot

Da ich mich ja nicht nur aus dem lokalen Netzwerk mit dem OpenVPN-Server
verbinden will, sondern auch von aussen -also aus dem Interenet- eine
gesicherte Verbindung ins heimische Netz herstellen will, muessen auch noch
einige Einstellungen an der Firewall gemacht werden, die leider auf der
offiziellen Webseite von OpenVPN nicht komplett beschrieben waren;
zusaetlich gebe ich in diesem Schritt auch gleich noch den Port 22 frei,
um von aussen per SSH auf den Router zu kommen. Die noetigen Einstellungen
werden in der /etc/firewall.user gemacht:

> ### OpenVPN
> ## -- Allow connections from outside
> iptables -t nat -A prerouting_wan -p udp --dport 1194 -j ACCEPT
> iptables        -A input_wan      -p udp --dport 1194 -j ACCEPT
> iptables -A INPUT   -i tun+ -j ACCEPT
> iptables -A FORWARD -i tun+ -j ACCEPT
> iptables -A OUTPUT  -o tun+ -j ACCEPT
> iptables -A FORWARD -o tun+ -j ACCEPT
>
> ### SSH (optional)
> ## -- Allow connections from outside
> iptables -t nat -A prerouting_wan -p tcp --dport 22 -j ACCEPT
> iptables        -A input_wan      -p tcp --dport 22 -j ACCEPT

Nachdem nun alles grundsaetzlich eingerichtet ist, kann man das VPN nun einem
ersten Funktionstest unterziehen. Dazu hole ich mir erstmal via SSH
beziehungsweise SCP die benoetiten Schluessel vom Router, erstelle eine
client.conf und starte OpenVPN; wohl gemerkt, alles auf dem Clientrechner,
auf dem natuerlich auch OpenVPN installiert sein muss:

$ mkdir -p /home/vpntest/openvpn/
$ cd /home/vpntest/openvpn/
$ scp [email-masked]:/etc/openvpn/client.crt ./
$ scp [email-masked]:/etc/openvpn/ca.crt ./
$ scp [email-masked]:/etc/openvpn/client.key ./
$ scp [email-masked]:/etc/openvpn/dh.pem ./
$ scp [email-masked]:/etc/openvpn/shared.key ./
$ scp [email-masked]:/etc/openvpn/client.csr ./
$ vi client.conf

Die angesprochene client.conf sieht in etwa so aus:

> client
> dev tun
> # dev-node TAP
> proto udp
> remote ACCOUNT.DYNDNSDOMAIN.TLD 1194
> nobind
> ### (optional) degrade privileges to this user and group after initialization
> #user nobody
> #group nogroup
> ca /home/vpntest/openvpn/ca.crt
> cert /home/vpntest/openvpn/client.crt
> key /home/vpntest/openvpn/client.key
> dh /home/vpntest/openvpn/dh.pem
> ### (optional) use a shared key to initialize TLS negotiation
> tls-auth /home/vpntest/openvpn/shared.key 1
> ### (optional) compression (use only if the server has it)
> comp-lzo

Gestartet wird das ganze dann ueber:

$ sudo openvpn --config /home/vpntest/openvpn/client.conf

Generell sollte eine grundlegende VPN-Verbindung nun aufgbeaut sein,
allerdings faengt hier ja der Spass erst an. Welche genauen Moeglichkeiten
man mit VPNs hat und wie man diese unter OpenVPN nutzt, sollte sich
leicht mit den folgenden Links und der jeweils bevorzugten Suchmaschine
herausfinden lassen. Ich hoffe, dass der Artikel einigen Leuten geholfen hat,
sei es in Sachen OpenWRT oder beim Einrichten von OpenVPN.

[1] http://www.openwrt.org/
[2] http://www.dd-wrt.com/
[3] http://www-de.linksys.com/servlet/Satellite?c=L_Product_C2&childpagename=DE%2FLayout&cid=1130276894513&pagename=Linksys%2FCommon%2FVisitorWrapper
[4] http://downloads.openwrt.org/kamikaze/7.09/brcm-2.4/openwrt-wrt54g-2.4-squashfs.bin
[5] http://wiki.openwrt.org/DropbearPublicKeyAuthenticationHowto
[6] http://www.no-ip.com/
[7] http://wiki.openwrt.org/DDNSHowTo
[8] http://www.openvpn.net/
[9] http://arctic-things.blogspot.com/2008/01/internet-gateway-openvpn-openwrt-on.html
[10] http://wiki.openwrt.org/OpenWrtDocs/KamikazeConfiguration
[11] http://forum.openwrt.org/viewtopic.php?id=12979
[12] http://wiki.openwrt.org/OpenVPNHowTo
[13] http://wiki.openwrt.org/OpenVPNTunHowTo
[14] http://www.openvpn-wiki.de/wiki/index.php/Hauptseite