Das Ziel war, einen Router für ein Kabelmodem auf Basis von Debian 8 mit mindestens drei, für Endgeräte nutzbaren, Gigabit LAN-Anschlüssen, sowie einer WLAN Karte für einen AccessPoint zu bauen. Bei der Auswahl der Hardware war wichtig, dass neben den Gigabit Netzwerkanschlüssen auch noch mindestens zwei USB 3.0 Anschlüsse vorhanden sind, um gegebenenfalls per USB weitere Gigabit LAN-Anschlüsse einrichten zu können. Die CPU sollte über genug Leistung verfügen, um das Routing, die Firewall mittels iptables, sowie einen VPN Tunnel stemmen zu können. Für den VPN-Tunnel ist es sinnvoll, dass die CPU über eine AES Erweiterung verfügt, um bei der Ver- und Entschlüsselung des Datenverkehrs keine zu großen Latenzen zu produzieren.

    Softwaretechnisch waren die Anforderungen:

    • Der Betrieb eines DHCP-Servers sowie eines DNS-Servers mit DNS-Zone für das lokale Netzwerk (home.local), in der sich alle Geräte mit Hostnamen und IP registrieren sollen.
    • Das Aufspannen eines WLAN Netzwerkes
    • Der Aufbau einer VPN-Verbindung beim starten des Gerätes um den gesamten Netzwerkverkehr ausgenommen einiger Geräte über den VPN-Tunnel zu routen
    • Das zusammenschließen der drei Gigabit-Anschlüsse mit dem WLAN zu einer Bridge um die Kommunikation der Geräte untereinander zu ermöglichen.
    • Die Installation eines UPnP-Dienstes um die Firewallanpassung seitens der Endgeräte zu ermöglichen.

    Letztendlich sollte das ganze System so robust sein, dass ein abruptes Trennen des Gerätes vom Strom nicht zu konsistenz Problemen auf dem Datenträger führt. Die nachfolgende Anleitung habe ich auf Basis meiner Notizen aus der Einrichtungsphase des Routers nachträglich erstellt. Sollten also kleine Zwischenschritte fehlen, wie das setzten von Rechten, so bitte ich das zu entschuldigen. Es kann gerne die Kommentarfunktion verwendet werden, um darauf hinzuweisen.

    Router Komponenten

    Hardware

    Der Fitlet XA-10 ist ein lüfterloser Mini-PC, der technisch aus:

    • einem 4-Kern AMD A10 Micro-6700T Prozessor mit AES Erweiterung
    • 4x GbE LAN Anschlüsse
    • 2x USB 3.0 Anschlüsse
    • 3x USB 2.0 Anschlüsse
    • 2x HDMI Ausgängen (AMD Radeon R6 Graphics)
    • 1x Full-size mSATA Steckplatz
    • 1x SO-DIMM 204-pin DDR3 SDRAM Speicher Steckplatz, der bis zu 8 GB Ram unterstützt
    • 1x Audio (Realtek ALC886)
    fitlet_x_-_two_pcs_1_1 fitlet_-_port_diagram

     

    WLAN

    Software

    Als Software würde die nachfolgende in Debian 8 bereits enthaltene Standard-Software verwendet:

    • Bind9 (1.9) als DNS-Server
    • ISC-DHCP-Server (4.3) als DHCP-Server
    • OpenVPN (2.3) als VPN-Client
    • Linux-IGD (1.0) als UPnP-Daemon
    • Hostapd (1.2) als WLAN AccessPoint
    • SystemD als init-Daemon

    Installation

    Installation des Grundsystems

    Bei der Installation des Fitlet habe ich die Erweiterungskarte für die Dauer der Installation entfernt, da ansonsten der einzelne LAN Anschluss auf der Rückseite nicht eth0 erkannt worden wäre, was ich jedoch wollte, um eth1-eth3 später als bridge verwenden zu können. Wer die Karte nicht ausbauen möchte, kann später in der Datei /etc/udev/rules.d/10-network.rules die Namen der Schnittstellen auch nachträglich ändern.

    Partitionierung

    Prinzipiell lässt sich mit ein paar kleinen Änderungen ein ganzes Linux System im read-only Modus betreiben. Die Ordner, welche zwingend beschreibbar sein müssen, können in eine Ramdisk ausgelagert werden. Dies hat den Vorteil, dass ein abrupter Stromverust die für den Betrieb wichtige Datenstruktur nicht beschädigen kann, jedoch das auch alle Log-Dateien oder Statistiken zur Schnittstellennutzung verloren. Da ich letztere jedoch behalten möchte, habe ich mich für folgende Partitionierung entschieden.

    Mount Punkt Größe später RW/RO Kommentar
    / 5 GB RO Root Partition
    /var/log 5 GB RW Log-Dateien
    /var/lib 2,5 GB RW Schnittstellenstatistik und DHCP-Lease Informatonen
    /root 5 GB RO Skripte etc.
           
    /var/cache/apt/ dynamisch,  da Ramdisk RW Paketinformationen für
    apt-get
    /var/cache/bind/ dynamisch,  da Ramdisk RW Schreibbare DNS Zonendatei
    /backup/ dynamisch,  da Ramdisk RW tägliches Backup welches per FTP gesichert wird.
     

     

    Softwareauswahl

    Die Installation des Grundsystems erfolgte anhand der aktuellen Debian Version 8.1.0 von CD. Es wurde im Experten-Modus nur das minimal-System installiert, also bei der Software-Auswahl alles abgewählt.

    debinstsoftware

    Während der Installation kann die Schnittstelle eth0, die sich auf der Rückseite des Gerätes befindet, einfach mit dem bereits vorhandenen LAN verbunden werden und im Verlaufe der Installation mittels DHCP eingerichtet werden. Wenn später das Kabel-Modem an eth0 angeschlossen wird (Crossover-Kabel notwendig), bekommt die Schnittstelle die öffentliche IP-Adresse ebenfalls per DHCP zugewiesen. Es muss später also nichts mehr an der Konfiguration von eth0 geändert werden.

    Nach Abschluss der Installation habe ich noch einige Pakete nachinstalliert, welche zum späteren Betrieb beziehungsweise der Administration benötig werden.

    apt-get install ssh htop ftp dnsutils screen vim cpufrequtils openvpn hostapd isc-dhcp-server bind9 linux-igd sudo apt-file locate iw firmware-ralink bridge-utils sysfsutils lsof vnstat iptraf nload firmware-linux-nonfree ncftp bash-completion unattended-upgrades psmisc openvpn whois lm-sensors linux-igd

    Systemd Bild-Reset nach Boot verhindern

    Sobald Debian 8 mit Systemd gebootet ist, wird der Bildschirminhalt resettet, so dass nur noch der Prompt zu sehen ist und alle vorherhigen Boot-Meldungen verschwinden. Mittels dmesg kann man sich zwar den Bootverlauf wieder anzeigen lassen, jedoch ist dies nicht die gleiche Darstellung wie im Boot-Bildschirm, was die Suche nach einer beim booten wahrgenommenen Meldung unnötig erschwert.

    Um bei späteren Einrichtung Boot-Meldungen in Ruhe lesen zu können, wurde das Löschen der Meldungen nach dem Boot, wie hier gefunden, abgeschaltet.

    mkdir -pv /etc/systemd/system/getty@tty1.service.d
    
    cat > /etc/systemd/system/getty@tty1.service.d/noclear.conf << EOF
    [Service]
    TTYVTDisallocate=no
    EOF

    DNS-Server einrichten

    Nach der Installation des Bind9 Paketes ist der DNS-Server selber schon Einsatzbereit. Damit der DHCP-Server die gleich anzulegende die DNS-Zone später auch aktualisieren kann, muss dafür eine key (rndc.key) erstellt werden.

    rndc-confgen -a

    Nun kann die DNS-Zone home.local sowie eine Reverse-Zone eingerichtet werden. Dazu werden einmal die nachfolgend verlinkten DNS-Zonen unter /etc/bind/ abgelegt und anschließend die /etc/bind/named.conf angepasst. Hierbei wird direkt der rndc.key mit eingebunden.

    # /etc/bind/named.conf
    
    include "/etc/bind/rndc.key";
    
    zone "home.local" IN {
            type master;
            file "home.local.zone";
            allow-query { any; };
            allow-update { key rndc-key; };
    };
    
    zone "10.168.192.in-addr.arpa" IN {
            type master;
            file "10.168.192.in-addr.arpa";
            allow-query { any; };
            allow-update { key rndc-key; };
    
    };

    Abschließend den DNS-Dienst neustarten und dem Router mitteilen, dass von nun an der lokale DNS-Server verwenden soll (etc/resolv.conf). Zusätzlich wird die /etc/resolv.conf noch vor Veränderungen geschützt.

    systemctl restart isc-dhcpserver
    
    echo "nameserver 127.0.0.1" > /etc/resolv.conf
    
    chattr +i /etc/resolv.conf

    DHCP-Server einrichten

    Für die Einrichtung des DHCP-Servers wird in der Datei /etc/dhcp/dhcpd.conf der DHCP-Bereich definiert, aus welchem die Clients später ihre IP-Adresse zugewiesen bekommen. An der markierten Stelle muss der Inhalt der Datei rndc.key eingefügt werden. Theoretisch kann der Key auch durch die Direktive include "/etc/bind/rndc.key"; eingebunden werden, jedoch funktionierte dies bei mir nicht.

    log-facility local7;
    
    option netbios-node-type 8;
    option netbios-name-servers 192.168.10.1;
    ddns-update-style interim;
    ddns-updates on;
    allow unknown-clients;
    use-host-decl-names on;
    ddns-domainname "home.local";
    update-static-leases on;
    key "rndc-key" {
     [...]
    };
    
    zone home.local. {
     primary 192.168.10.1;
     key rndc-key;
    }
    
    zone 10.168.192.in-addr.arpa. {
     primary 192.168.10.1;
     key rndc-key;
    }
    
    authoritative;
    default-lease-time 600;
    max-lease-time 7200;
    
    subnet 192.168.10.0 netmask 255.255.255.0 {
     option domain-name-servers 192.168.10.1;
     option domain-name "home.local";
     ddns-domainname "home.local";
     ddns-rev-domainname "in-addr.arpa.";
     option broadcast-address 192.168.10.255;
     option routers 192.168.10.1;
     range 192.168.10.100 192.168.10.150;
    }

    Abschließend einmal den DHCP Dienst durchstarten.

    systemctl restart isc-dhcp-server

    Um sich die aktuelle vergebenen Leases anzeigen zu lassen, gibt es den Befehl dhcp-lease-list. Dieser funktioniert in der Konfiguration jedoch nicht, da er die Datei für die Leases (dhclient.leases) unter /var/db erwartet, die jedoch unter /var/lib/dhcpd liegt. Das lässt sich aber durch eine Verlinkung beheben.

    mkdir /var/db
    ln -s /var/lib/dhcp/dhclient.leases /var/db/dhcpd.leases
    
    dhcp-lease-list

    Bridge einrichten

    Nachdem nun der DNS- sowie DHCP-Server laufen, kann die Bridge für die Netzwerkschnittstellen eth1 bis eth3 eingerichtet werden. Hierzu sind folgende Einträge in der /etc/network/interfaces notwendig. Die Paremter dazu können in der manpage nachgelesen werden.

    Die wlan0 Schnittstelle wird später über hostapd automatisch hinzugefügt.

    # /etc/network/interfaces
    
    
    auto eth1
    iface eth1 inet manual
            up ifconfig eth1 up promisc
            down ifconfig eth1 down -promisc
    
    auto eth2
    iface eth2 inet manual
            up ifconfig eth2 up promisc
            down ifconfig eth2 down -promisc
    
    auto eth3
    iface eth3 inet manual
            up ifconfig eth3 up promisc
            down ifconfig eth3 down -promisc
    
    auto wlan0
    iface wlan0 inet manual
    
    # Bridge setup
    auto br0
    iface br0 inet static
            bridge_ports eth1 eth2 eth3 wlan0
            bridge_waitport 0
            bridge_fd 0
            bridge_hello 0
            address 192.168.10.1
            broadcast 192.168.10.255
            netmask 255.255.255.0
            gateway 192.168.10.1
    

    Damit das Routing sauber funktioniert wird ipv6 deaktiviert, der Bridge erlaubt auf den entsprechenden Interfaces als Arp-Proxy zu fungieren, sowie die Weiterleitung der IP Pakete aktiviert.

    echo "# Disable IPv6"
    echo net.ipv6.conf.all.disable_ipv6 = 1 >> /etc/sysctl.conf
    echo >> /etc/sysctl.conf
    
    echo "# Allow Router to act as ARP Proxy"
    echo net.ipv4.conf.all.proxy_arp=1 >> /etc/sysctl.conf
    echo net.ipv4.conf.wlan0.proxy_arp=1 >> /etc/sysctl.conf
    echo net.ipv4.conf.eth1.proxy_arp=1 >> /etc/sysctl.conf
    echo net.ipv4.conf.eth2.proxy_arp=1 >> /etc/sysctl.conf
    echo net.ipv4.conf.eth3.proxy_arp=1 >> /etc/sysctl.conf
    echo >> /etc/sysctl.conf
    
    echo "# Enable forwarding on all interfaces"
    echo net.ipv4.ip_forward = 1 >> /etc/sysctl.conf
    echo net.ipv4.conf.wlan0.forwarding=1 >> /etc/sysctl.conf
    echo net.ipv4.conf.eth1.forwarding=1 >> /etc/sysctl.conf
    echo net.ipv4.conf.eth2.forwarding=1 >> /etc/sysctl.conf
    echo net.ipv4.conf.eth3.forwarding=1 >> /etc/sysctl.conf

    Nun die Änderungen noch aktivieren:

    sysctl -p

    Damit der DHCP-Dienst nun auch auf der Bridge (br0) auf DHCP-Anfragen lauscht, muss in der Datei /etc/default/isc-dhcp-server noch eine Zuweisung an br0 erfolgen.

    /etc/default/isc-dhcp-server
    INTERFACES="br0"

    Nach den Änderungen besten einmal den Router neustarten.

    AccessPoint einrichten

    Um den AccessPoint zu betreiben wurde am Anfang schon das Treiberpaket firmware-ralink mit installiert. Über der /etc/network/interfaces wird die Schnittstelle wlan0 auch bereits aktiviert. Jetzt kommt noch hostapd als AccessPoint oben drauf. Dazu muss die Konfigurationsdatei /etc/hostapd/hostapd.conf angepasst werden. Die SSID, sowie das WLAN-PASSWORT müssen bitte individuell gesetzt werden. Der Parameter bridge= veranlasst hostapd beim starten wlan0 automatisch zur Bridge br0 hinzuzufügen.

    /etc/hostapd/hostapd.conf
    
    interface=wlan0
    driver=nl80211
    bridge=br0
    ssid=<SSID>
    auth_algs=1
    channel=3
    
    country_code=OB
    
    #  yes, it says 802.11g, but the n-speeds get layered on top of it
    hw_mode=g
    
    #  this enables the 802.11n speeds and capabilities ...  You will also need to enable WMM for full HT functionality.
    ieee80211n=1
    wmm_enabled=1
    
    eap_reauth_period=360000000
    
    wpa=0
    ignore_broadcast_ssid=0
    wpa=3
    wpa_passphrase=<WLAN-PASSWORT>
    wpa_key_mgmt=WPA-PSK
    wpa_pairwise=TKIP CCMP

    Da hostapd leider keine Service-Unit für systemd mitliefert, muss diese manuell erstellt werden. Dazu wird die Datei /etc/systemd/system/hostapd.service mit folgendem Inhalt angelegt.

    /etc/systemd/system/hostapd.service
    
    [Unit]
    Description=Hostapd IEEE 802.11 AP, IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator
    Wants=network.target
    
    BindsTo=sys-subsystem-net-devices-wlan0.device
    After=sys-subsystem-net-devices-wlan0.device isc-dhcp-server.service
    
    [Service]
    Type=oneshot
    RemainAfterExit=yes
    ExecStart=/usr/sbin/hostapd -B /etc/hostapd/hostapd.conf -P /var/run/hostapd.pid
    ExecStart=/sbin/iptables --append FORWARD --in-interface wlan0 -j ACCEPT
    ExecStop=/usr/bin/killall -9 hostapd
    
    [Install]
    WantedBy=multi-user.target

    Anschließend hostapd systemd einmal die Konfiguration neu einlesen lassen, hotsapd als Start-Dienst aktivieren und den Dienst händisch starten.

    systemctl daemon-reload
    systemctl enable hostapd
    systemctl restart hotsapd

    Dateisystem durch Read-Only schützen

    Eines vorweg: Man kann das Dateisystem später im laufenden Betrieb problemlos wieder als RW mounten. Also nicht nervös werden, wenn das System später startet und nichts mehr geschrieben werden kann. Der Befehl dazu lautet:

    mount - / -oremount,rw

    /etc/fstab anpassen

    Um das Dateisystem zu schützen, müssen in der Datei /etc/fstab die read-only zu mountenden Partition einige Parameter ergänzt werden. Zusätzlich werden /var/log und /var/lib/ abgesichert, da diese beiden Ordner die einzigen beschreibbaren auf der Festplatte sind.

    # <file system>    <mount point>     <type>    <options>                                        <dump>  <pass>
    /dev/sda1          /                 ext4      defaults,ro,errors=remount-ro                    0       1
    /dev/sda8          /root             ext4      defaults,ro,errors=remount-ro                    0       2
    /dev/sda6          /var/log          ext4     defaults,nodiratime,noatime,nodev,nosuid,noexec   0       2
    /dev/sda7          /var/lib          ext4     defaults,nodiratime,noatime,nodev,nosuid          0       2

    /var/lib: Hier legen vnstat und der DHCP-Server Informationen über den Trafficverbrauch bzw. die aktuellen DHCP Leases ab. Ohne Schreibrechte wäre beides nicht möglich.

    Darüber hinaus müssen einige Teile des Dateisystems beschreibbar sein und werden daher über eine Ramdisk eingebunden.

    # <file system>    <mount point>     <type>    <options>                                        <dump>  <pass>
    tmpfs              /var/cache/bind/  tmpfs     defaults,noexec,noatime,mode=0755                0       0
    tmpfs              /backup/          tmpfs     defaults,noexec,noatime,mode=0755                0       0
    tmpfs              /var/cache/apt/   tmpfs     defaults,noexec,noatime,mode=0755                0       0

    /var/cache/bind/: Hintergrund ist, dass Bind9 nach der Vergabe einer IP Adresse mittels DHCP den neuen Host in die DNS-Zonendatei eintragen können muss. Die Original Zonen-Datei kann weiterhin unter /etc/bind/ liegen bleiben. Sie wird später beim Start nach /var/cache/bind/ umkopiert. Dieses Vorgehen hat für die DNS-Zonen den Vorteil, dass durch jeden Reboot wieder eine saubere Zone ohne jegliche Einträge geladen wird. Da nach einem Neustart der DHCP-Client die leases der Clients erneuert, werden auch automatisch alle eingeschalteten Clients wieder in der Zone registriert.

    /backup: Hier schreibe ich später meine täglichen Konfigurationsbackups hin, welche auch keinen Neustart überleben müssen, da es per FTP weg kopiert wird.

    /var/cache/apt: Um später updates installieren zu können, wird dieser Ordner auch in eine Ramdisk ausgelagert. Hier legt apt-cache seine Repository Informationen ab. Wer jetzt denke "Read-Only und Updates, wie passt das zusammen?" … kommt noch 😉

    Anschließend noch das Swapping verhindern:

    echo >> /etc/sysctl.conf
    echo "# Disable swapping"
    echo vm.swappiness=0 >> /etc/sysctl.conf
    echo >> /etc/sysctl.conf
    
    sysctl -p

    ramdisk.service anlegen

    Jetzt wird ein systemd service angelegt, welcher bei einem starten des Systems einige Dateien in die Ramdisk Ordner kopiert.

    /etc/systemd/system/ramdisk.service
    
    [Unit]
    Description=Copy necesarry files into ramdisk
    Wants=tmp.mount
    After=tmp.mount
    Before=bind9.service
    
    [Service]
    Type=oneshot
    RemainAfterExit=yes
    ExecStart=/bin/cp /etc/bind/managed-keys.bind /var/cache/bind/
    ExecStart=/bin/cp /etc/bind/10.168.192.in-addr.arpa /var/cache/bind/
    ExecStart=/bin/cp /etc/bind/home.local.zone /var/cache/bind/
    ExecStart=/bin/chown bind:bind /var/cache/bind/ -R
    
    [Install]
    WantedBy=local-fs.target

    Da die Anleitung aufeinander aufbaut, muss jetzt in der der Datei /etc/bind/named.conf der Pfad zu den DNS-Zonen home.local.zone sowie 10.168.192.in-addr.arpa vollqualifiziert angegeben werden. Abschließend noch den Dienst aktivieren.

    systemctl enable ramdisk.service

    .viminfo anpassen

    Wird vim später auf einem read-only System verwendet, wodurch auch das Homeverzeichnis geschützt wird, wirft vim folgende Fehlermeldung

    E886: Can't rename viminfo file to ~/.viminfo!

    Dem kann entgegen gewirkt werden:

    set viminfo="NONE"

    .bashrc anpassen

    Die bash kann, insofern konfiguriert, eine Historie der zuletzt verwendeten Befehle führen. Auf einem read-only geschützten Dateisystem wird dies schwierig und die bash wirft daher ebenfalls beim starten einen Fehler. Aus diesem Grund sollte die bash Historie deaktiviert werden.

    ~/.bashrc
    
    export HISTFILE=/dev/null

    apt-get read-only anpassen

    Auch wenn das Root-Dateisystem beim starte read-only gemountet wird, kann apt-get dennoch so angepasst werden, dass es wie immer verwendet werden kann. Wie hier beschrieben muss dazu nur die Datei /etc/apt/apt.conf mit folgendem Inhalt angelegt werden:

    /etc/apt/apt.conf
    
    DPkg {
        // Auto re-mounting of a readonly /
        Pre-Invoke { "mount -o remount,rw /"; };
        Post-Invoke { "test ${NO_APT_REMOUNT:-no} = yes || mount -o remount,ro / || true"; };
    };

    Hinweis zum random-seed.service

    Wie hier beschrieben ist die Generierung von qualitativer Entropie sehr schwierig und braucht seine Zeit. Entropie wird jedoch zum Beispiel bei VPN-Verbindungen oder der Schlüsselerstellung benötigt. Um beim starten eines Linux Systems nicht erst aufwendig Zufallszahlen generieren zu müssen, speichert der random-seed.service diese beim herunterfahren. Im read-only Modus wird dies jedoch scheitern. Beim nächsten starten kann der Dienst die Datei /var/lib/systemd/random-seed nicht laden und wirft den Fehler:

    Failed to start Load/Save Random Seed

    Leider ist es mir weder gelungen den Dienst zu deaktiviern, noch durch das umkopieren der Datei beim starten und herunterfahren den Dienst zufrieden zu stellen. Dies nur als Hinweis für die auftauchende Fehlermeldung.

    # ln -s /var/log/random-seed /var/lib/systemd/random-seed
    # systemctl disable systemd-random-seed

    Ob die Installation des haveged sich positiv auf die Generierung von Entropie auswirkt, kann ich nicht sagen, da ich mir die Arbeitsweise von haveged im Detail nicht angeschaut habe. Es könnte jedoch eine Option sein.

    OpenVPN Einrichten

    Ich möchte hier nicht beschreiben, wie OpenVPN in gänze einzurichten ist, sondern beschränke mich auf einige Anpassungen, welche ich an der OpenVPN Konfiguration gemacht habe.

    DNS-Server nicht per DHCP beziehen

    Per DHCP wird der Schnittstelle eth0 nicht nur eine IP Adressen, sondern auch der DNS-Server des Modems mitgeteilt. Dieses Verhalten wird deaktiviert, da auf dem Router ein eigene DNS-Server läuft, welcher verwendet werden soll.

    /etc/dhcp/dhclient-enter-hooks.d/nodnsupdate
    make_resolv_conf() {
            true
    }

    Systemd Service anlegen

    Die erste Änderung ist, dass ich für Systemd eine eigene OpenVPN Service-Datei angelegt habe. OpenVPN startet sobald das Netzwerk als auch der DHCP-Dienst am Router Einsatzbereit sind.
    Über die Parameter Restart und RestartSec wird sichergestellt, dass der Dienst automatisch neustartet, sollte er unerwartet beendet werden. –script-security ermöglicht das ausführen von Skripten beim Auf- und Abbau der VPN-Verbindung.

    [Unit]
    Description=OpenVPN
    After=network.target bind9.service
    Requires=networking.service bind9.service
    
    [Service]
    Type=forking
    PIDFile=/var/run/openvpn.pid
    ExecStart=/usr/sbin/openvpn --daemon --writepid /var/run/openvpn.pid --log-append /var/log/openvpn.log --script-security 2 --up /etc/openvpn/tun0-up.sh --down /etc/openvpn/tun0-down.sh --cd /etc/openvpn/vpn-config-folger --config /etc/openvpn/vpn-config-colder/vpn-config.ovpn
    ExecReload=/bin/kill -HUP $MAINPID
    ExecStop=/bin/kill -TERM $MAINPID
    Restart=always
    RestartSec=30
    KillSignal=SIGINT
    
    [Install]
    WantedBy=multi-user.target

    Die Service-Datei muss anschließend eingelesen und OpenVPN aktiviert werden.

    systemctl daemon-reload
    systemctl enable openvpn

    Routing nach Quell-IP

    Da der gesamte Netzwerkverkehr, über den VPN-Tunnel geroutet wird, kann es bei der Verwendung von Online-Video-Diensten wie Amazon Prime zu Probleme kommen. Endet der VPN-Tunnel außerhalb von Deutschland erkennt das Amazon Prime und verweigert das Abspielen von Videos. Hier kann man entweder die Verwendung eines lokalen DNS-Servers erzwingen oder aber, was mehr Sinn macht, den gesamten Verkehr von zum Beispiel einem Amazon FireTV am VPN vorbei routen. Dazu ist ein Routing auf Basis der Quell-IP Notwendig, welche über den DHCP Server anhand einer Reservierung fixiert werden kann.

    Um Quell-IP Adressen anders zu routen, als den restlichen Netzwerkverkehr muss eine eigene Routingtabelle angelegt werden, in welcher das Zielgateway angegeben werden muss. Da ein Quell-IP basiertes Routing erst durch den Aufbau einer VPN-Verbindung notwendig wird, sorgt das Skript /etc/openvpn/tun0-up.sh für deren Ausführung. Das Skript legt die Routingtabelle 1000 mit dem aktuellen Gateway (eth0) als Routingadresse an und nimmt anschließend die IP Adressen 192.168.10.251 bis 253 in die Routingliste auf. Diese Quelladresse können also trotz aktiver VPN-Verbindung direkt über den Unitymedia Anschluss raus.

    #!/bin/bash
    
    addSourceRouting() {
            if [ $(ip rule list |grep $1 -c) = 0 ]; then
                    ip rule add from $1/32 table 1000
            fi
    }
    
    gateway=$(ip addr show eth0 |grep -v "eth0:"| grep "inet " | cut -d / -f 1 | awk '{print $2}')
    if [ ! -z "$gateway" ]; then
            ip route del default table 1000
            ip route add default via $gateway dev eth0 table 1000
            logger "Openvpn Table 1000: new gateway $gateway"
    fi
    
    addSourceRouting 192.168.10.251
    addSourceRouting 192.168.10.252
    addSourceRouting 192.168.10.253
    

    Um sich die das Source-Routing anzuschauen, können folgende Befehle verwendet werden:

    # Show table informationen
    ip rule list
    ip route list table 1000
    

    Routing-Anpassung bei Änderung der öffentlichen IP-Adresse

    Wird nach 24 Stunden über das Unitymedia Modem dem Router eine neue IP Adresse zugewiesen, macht dies die Routingtabelle 1000 unbrauchbar. Das Problem kann gelöst werden, indem automatisch bei einer Aktualisierung der eth0 IP-Adresse durch den DHCP Client ein entsprechendes Skript ausgeführt wird. Die Lösung dazu habe ich hier gefunden.

    Das Skript löscht bei einer Erneuerung der DHCP Adresse für eth0 die alte Route und definiert diese mit der neuen öffentlichen IP Adresse neu.

    Es wird dazu die Datei /etc/dhcp/dhclient-exit-hooks.d/routing mit nachfolgendem Inhalt angelegt:

    # /etc/dhcp/dhclient-exit-hooks.d/routing
    
    set_routing() {
        case $reason in
            BOUND|RENEW|REBIND|REBOOT)
                    gateway=$(ip addr show eth0 | grep -v "eth0:" | grep "inet " | cut -d / -f 1 | awk '{print $2}')
                    if [ ! -z "$gateway" ]; then
                            ip route del default table 1000
                            ip route add default via $gateway dev eth0 table 1000
                            logger "dhclient: Table 1000 new gateway $gateway"
                    fi
                ;;
            EXPIRE|FAIL|RELEASE|STOP)
                    gateway=$(ip addr show eth0 | grep -v "eth0:" | grep "inet " | cut -d / -f 1 | awk '{print $2}')
                    if [ ! -z "$gateway" ]; then
                            ip route del default table 1000
                            ip route add default via $gateway dev eth0 table 1000
                            logger "dhclient: Table 1000 new gateway $gateway"
                    fi
    
                ;;
        esac
    }
    

    Massenhaft DHCPRequests

    Nach der Einrichtung füllte sich das log (/var/log/syslog) nach und nach mit jeder Menge DHCPREQUEST Einträgen, welche alle vom Kabel-Modem von UnityMedia stammen.

    Aug 14 15:54:47 router dhclient: DHCPREQUEST on eth0 to 10.145.20.1 port 67
    Aug 14 15:55:03 router dhclient: DHCPREQUEST on eth0 to 10.145.20.1 port 67
    Aug 14 15:55:12 router dhclient: DHCPREQUEST on eth0 to 10.145.20.1 port 67
    Aug 14 15:55:24 router dhclient: DHCPREQUEST on eth0 to 10.145.20.1 port 67
    Aug 14 15:55:35 router dhclient: DHCPREQUEST on eth0 to 10.145.20.1 port 67
    Aug 14 15:55:49 router dhclient: DHCPREQUEST on eth0 to 10.145.20.1 port 67
    Aug 14 15:56:10 router dhclient: DHCPREQUEST on eth0 to 10.145.20.1 port 67
    Aug 14 15:56:22 router dhclient: DHCPREQUEST on eth0 to 10.145.20.1 port 67
    Aug 14 15:56:42 router dhclient: DHCPREQUEST on eth0 to 10.145.20.1 port 67

    Bei der Suche nach der Ursache gab es zwei potentielle Lösungen.

    1. Das Modem schickt mit dem DHCPRequest einen Identifier, welcher fehlerhaft ist und somit eine Antwort nichz erfolgreich zugestellt werden kann (Quelle)
    2. Das Modem hat Probleme bei der Verarbeitung von Unicast Paketen (Gleiche quelle wie 1)

    Es traf jedoch beides nicht zu. Die tatsächliche Ursache war, dass der UDP DHCPRequest auf dem Interface eth0 ankommt und der Router ihn aufgrund seiner Routintabelle über tun0 beantwortet. Somit erhält das Modem nie eine Antwort und stellt die Anfrage nach kurzer Zeit erneut. Die Lösung ist daher denkbar einfach. Es muss für das Modem eine dedizierte Router definiert werden. Diese kann man z.B. in der /etc/rc.local eintragen da es kein Problem darstellt, wenn die Route auch ohne VPN Verbindung gesetzt wird.

    route add 10.145.20.1/32 dev eth0

    Hinweis zur Wärmeentwicklung

    Das Gerät wird im Betrieb sehr warm (Gehäuse 40-50° C im Normalbetrieb, CPU 65-68° C, bei 24° C Raumtemperatur), was der Hersteller aber auch in seinen FAQs erwähnt. Auch wenn sich die Anzahl der zu verwendenden Prozessoren sowie die maximale Leistungsaufnahme (1-25.000 mW) im Bios einstellen lassen, wirkt sich dies kaum auf die die Temperatur  aus.

    Die CPU Temperatur kann ab Kernel 3.1.6 ausgelesen werden, dazu muss jedich lm-sensors installiert werden.

    apt-get install lm-sensors

    Anschließend das Modul laden und die Temperatur auslesen

    $ modprobe k10temp
    $ sensors
    k10temp-pci-00c3
    Adapter: PCI adapter
    temp1:        +65.2°C  (high = +70.0°C)
                           (crit = +105.0°C, hyst = +104.0°C)
    
    

    Wer möchte, dass dieses Modul beim booten direkt geladen wird, kann es unter Debian in die /etc/modules eintragen:

    echo k10temp >> /etc/modules

    Links

    Wie im Artikel Kernel: Kernel für einzelnes System optimieren beschrieben, kann man einen Kernel für ein System individuell anpassen. Die minmal Konfiguration für Kernel 4.2.6 mit GrSecurity Erweiterung sowie Unterstützung des Logitech Unify Empfängers als des  RT5370 USB Wlan Stick auch kann hier heruntergeladen werden.

    Nachtrag vom 21.09.2015: Update auf Kernel 4.1

    Wer übrigens auf Debian Jessie auf den Kernel 4.1 (Neuerungen des Kernels) der Backports upgraden möchte, kann dies relativ einfach. Dazu müssen die Quelle angepasst werden und anschließend der Kernel expliziet aus der Quelle installiert werden.

    /etc/apt/sources.list
    deb http://ftp2.de.debian.org/debian/ jessie-backports main contrib non-free
    deb-src http://ftp2.de.debian.org/debian/ jessie-backports main contrib non-free
    

     

    apt-get update
    apt-get -t jessie-backports install linux-image-amd64 -y

    Die anschließende Kontrolle der sensoren fördert einen neuen Eintrag zutage, der leider nicht so aussagekräftig ist.

    fam15h_power-pci-00c4
    Adapter: PCI adapter
    power1:           N/A  (crit =   4.54 W)

    Nachtrag vom 25.11.2015: Kühlkörper

    Es gibt seit kurzem Austauschgehäuse mit besseren Kühlrippen. Dies kann etwender direkt beim Hersteller oder mittlerweile auch bei Amazon bestellt werden. Der Händle CompuLab bietet dort auch die restliche verfügbare Zubehör zu Kaufe an.

    In der Praxis zeigt sich, dass durch die tieferen Külrippen der Wärmeaustausch verbessert wird, so dass die Temperatur um 15-20° C auf 45-48° C im Normalbetrieb fällt.

    Nachtrag vom 08.12.2015: Kernel 4.2.6 GrSecuriy

    Wie im Artikel Kernel: Kernel für einzelnes System optimieren beschrieben, kann man einen Kernel für ein System individuell anpassen. Die minmal Konfiguration für Kernel 4.2.6 mit GrSecurity Erweiterung sowie Unterstützung des Logitech Unify Empfängers als des  RT5370 USB Wlan Stick auch kann hier heruntergeladen werden.

    Nachtrag vom 06.12.2015: geblockte Popups automatisch schließend

    Eine Änderung habe ich heute nich implementiert. Popups die per DNS geblockt sind, gehen auf, zeigen aber aufgrund des blacklistings keinen Inhalt an.
    Das ganze kann man noch etwas schöner lösen. Der Trick ist, geblockte Anfrage auf den Router umzuleiten. Der Router liefert dann eine Webseite aus, die sich sofort schließt.

    Ursprünglich hatte ich mich gegen eine Umleitung der geblockten Anfragen zurück auf den Router entschieden, um den Traffic zu vermeiden.

    Um die Konfiguration dementsprechend anzupassen sind 5 Schritte notwendig.

    Webserver installieren

    apt-get install lighttpd

    DNS Zone anpassen

    Der DNS Server muss für jede geblocke Domain sowie alle Subdomains (*) einen A record bereitstellen, der auf ihn verweist.

    /etc/bind/blacklisted.zones
    
         IN    A       192.168.10.1
    *    IN    A       192.168.10.1
         IN    AAAA    ::1
    *    IN    AAAA    ::1

     

    Blockpage erstellen

    Die durch die Umleitung aufgerufene Webseite soll sich sofort wieder schließen.

    # /var/www/html/index.lighttpd.html
    
    <html>
    <head>
    <script language="javascript" type="text/javascript">
      function closeWindow() {
      window.open('','_parent','');
      window.close();
      }
    closeWindow();
    </script>
    </head>
    <body>
    </body>
    </html>

    Einige Firefox Versionen erlauben das automatische Schließend von Fenstern nicht. Zu Beispiel unter OpenSUSE.
    Um dies zu aktivieren, muss der Wert dom.allow_scripts_to_close_windows in der about:config auf true gesetzt werden.

    Webseiten Umleitung

    Nun noch lighttpd mitteilen, dass alle Anfragen auf die Standard Seite umgeleitet werden sollen.

    # /etc/lighttpd/lighttpd.conf
    
    server.error-handler-404   = "/index.lighttpd.html"
    url.rewrite-once = ( "^/(.*)" => "/index.html" )

     

    /etc/init.d/lighttpd restart

     

    Leave A Reply