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)
WLAN
- Verwendet wurde RT5370 USB Wlan Stick, da die Treiber im Paket firmware-ralink enthalten sind.
- Debian 8: RT5370 USB WLAN Stick Anpassungen
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.
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.
- Das Modem schickt mit dem DHCPRequest einen Identifier, welcher fehlerhaft ist und somit eine Antwort nichz erfolgreich zugestellt werden kann (Quelle)
- 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