Dienstag, 17. Februar 2015

Bridged IPv6/Routed IPv4 an KabelBW/UnityMedia TC7200 (Update 1)

Nicht genug, dass mein Kabel-Internetanbieter mir nur DualStack-Lite anbietet (d.h. keine öffentliche IPv4 Adresse), es ist mir auch nicht erlaubt das beigesteuerte Kabelmodem TC7200 als solches zu verwenden.
Nach jedem Start des Gerätes gibt es eine Remote-Config Datei, die es in einen extrem kastrierten Router-Modus versetzt. Für IPv4 ist der Router ist der Endpunkt des DS-Lite Tunnels. Das NAT findet am anderen Ende des Tunnels im CGN Gateway statt. Somit sind sämtliche Port-Weiterleitungsfunktionen nicht zu gebrauchen.

Nun könnte man die IPv6 Firewall ausschalten und jedes Gerät im LAN mit seiner IPv6 Adresse ansprechen, aber das könnten dann auch die bösen Buben...
Ein zwischengeschalteter Router würde eine fein abstimmbare Firewall mit sich bringen, aber dieser Ansatz schlägt fehl, weil der TC7200 keine Prefix-Delegation beherrscht.

Nun möchte ich mich hier nicht über die Unzulänglichkeiten des TC7200 aufregen (grrrrrrr!!!!), sondern einen Weg aufzeigen, wie mit einem zusätzlichen OpenWRT Router doch noch eine zufriedenstellende Lösung gebastelt werden kann.

Es gibt im Netz viele Geschichten, OpenWRT würde ein wenig zaubern und die fehlende Prefix-Delegation des TC7200 überwinden können. Das ist mir mit keiner Lösung gelungen. Eigentlich kann es auch nicht funktionieren, da beim Routing klar sein muss, auf welchem Interface das Prefix weitergeroutet werden soll - blöd, wenn das Neighbor Discovery dann Prefixe zu kennen glaubt, die es auf dem Routing-Zweig garnicht gibt.

Im UnityMediaKabelBW-Forum bin ich auf einen Eintrag gestoßen, der auch im OpenWRT Wiki beschrieben ist (allerdings für die ältere 12.09 Version von OpenWRT).

Der Trick ist mit Hilfe von "ebtables" aus OpenWRT ein Router für IPv4 und eine Bridge für IPv6 zu machen. Dazu wird das WAN Interface auf die existierende LAN Bridge geschaltet und per ebtables Eintrag jeglicher nicht IPv6 Verkehr am WAN Interface verworfen. Der IPv6 Traffic landet dann im Netfilter und kann per Firewall-Regel inspiziert werden.

Man muss sich allerdings im Klaren sein, dass diese Firewall-Bridge etwas Performance kostet. In einem alten OpenWRT Wiki Eintrag ist die Rede von ca. 50% Leistungseinbußen auf einem WRT54GL.

Folgende Schritte beziehen sich auf die OpenWRT Barrier Breaker Version auf einem TP-Link WDR4300.
  1. Normale Konfiguration für IPv4 NAT - WAN Interface per DHCP angebunden
  2. LAN Interface: "IPv6 assignment length" = disabled
  3. LAN Interface -> DHCP Server -> IPv6 Settings (alle disabled)
  4. ebtables, kmod-ebtables-ipv6, ip6tables und luci-proto-ipv6 installieren
Die Firewall-Chains Default Targets ( Network -> Firewall -> General Settings ) sollten auf "Input - reject", "Output - accept", "Forward - reject" stehen.
Firewall Zone Default Settings
Firewall Zone Settings
Die Firewall-Zonen ( Network -> Firewall -> Zones ) müssen auf "IPv4 only" umgestellt werden ( Edit -> Advanced Settings ).
Firewall - Zone Settings to IPv4 only
IPv4 only - Settings for Standard Zones
Unter Network -> Firewall -> Traffic Rules gibt es schon einige Beschränkungen für IPv6-ICMP Nachrichten. Da IPv6 maßgeblich von ICMP Gebrauch macht, ist es wichtig, die Standard-Regeln etwas zu erweitern. Folgende ICMP-Nachrichten sollten weitergeleitet werden ("Any Zone - Any Zone(Forward)" und "Any Zone - Device(Input)")
  • echo-reply
  • echo-request
  • destination-unreachable
  • packet-too-big
  • time-exceeded
  • bad-header
  • parameter-problem
  • neighbour-solicitation
  • neighbour-advertisement
  • router-solicitation
  • router-advertisement
Damit die Autoconfiguration funktioniert habe ich noch eine zusätzliche Regel, die alle ICMP Nachrichten-Typen 130/0, 131/0, 132/0, 143/0 von den LocalLink Adressen fe80::/10 zu den MultiCast Adressen ff00::/8 erlauben. (www.ietf.org/rfc/rfc4890.txt)
additional Traffic Rules for IPv6 Auto Config
Traffic Rules

Nun kann man unter Network -> Firewall -> Custom Rules das spezielle Bridge/Firewall Setup vornehmen:

if [ -f /tmp/ipv6prefix ] ; then
        PREFIX=`cat /tmp/ipv6prefix`
fi

if [ -z "$PREFIX" ] ; then
        PREFIX=`ifconfig eth0.2 | awk '/Global/ { print $3; }' | sed 's/[a-z0-9]*:[a-z0-9]*:[a-z0-9]*:[a-z0-9]*\/.*$//g'`
fi

echo $PREFIX > /tmp/ipv6prefix

ebtables -F
ebtables -t broute -F
ebtables -t broute -A BROUTING -i eth0.2 -p ! ipv6 -j DROP
brctl addif br-lan eth0.2

ip6tables -I FORWARD -s $PREFIX:/57 -j ACCEPT

# DNS6 Portumleitung auf den OpenWRT - braucht noch ein IPv6 faehigen DNS-Responder...
ip6tables -I INPUT -p tcp -s $PREFIX:/57 --dport 53 -j ACCEPT
ip6tables -I INPUT -p udp -s $PREFIX:/57 --dport 53 -j ACCEPT
ip6tables -t nat -I PREROUTING -p tcp --dport 53 -j REDIRECT --to-ports 53
ip6tables -t nat -I PREROUTING -p udp --dport 53 -j REDIRECT --to-ports 53

### open IPv6  port 80/22 on NAS
ip6tables -I FORWARD -i br-lan -p tcp -d nas-ipv6adresse.dyndns.org --destination-port 80 -j ACCEPT
ip6tables -I FORWARD -i br-lan -p tcp -d nas-ipv6adresse.dyndns.org --destination-port 22 -j ACCEPT


Als letzten Schritt fügt man unter System -> Scheduled Tasks noch eine Zeile zur IP-Prefix Überprüfung ein:

SHELL=/bin/sh
PATH=/usr/bin:/usr/sbin:/sbin:/bin
#Minuten #Stunden #Tag #Monat #Wochentag #Befehl
*/5 *  * * * PREFIX=`ifconfig br-lan | awk '/Global/ { print $3; }' | sed 's/[a-z0-9]*:[a-z0-9]*:[a-z0-9]*:[a-z0-9]*\/.*$//g'` ; if [ "$PREFIX" != "`cat /tmp/ipv6prefix`" ] ; then echo $PREFIX > /tmp/ipv6prefix ; /etc/init.d/firewall restart ; fi


Vor dem Neustart noch auf der Kommandozeile die /etc/sysctl.conf anpassen:

net.ipv6.conf.default.forwarding=0
net.ipv6.conf.all.forwarding=0

net.bridge.bridge-nf-call-arptables=0
net.bridge.bridge-nf-call-ip6tables=1
net.bridge.bridge-nf-call-iptables=0

Update 1:


Ich habe die DHCPv6 Durch- und Weiterleitungen in der Firewall wieder deaktiviert.
Problematisch war, dass dadurch auch die KabelBW IPv6 DNS-Server an meine Clients im LAN verteilt wurden und somit mein lokalen Geräte (Fernseher, Staubsauger, SatBox) nicht mehr per IPv4 Namensauflösung erreicht wurden.
Nicht alle Geräte verhielten sich konsistent, während der IPv4/6 Stack meines Win8.1 Laptops unter angabe des vollen Domänen-Namens auch lokale Geräte auflösen konnte, hat mein Nexus 7 mit Android 5 stur versucht, die Namen per IPv6 aufzulösen und schlug damit natürlich beim Provider DNS fehl.

Eine DNS6 Port-Umleitung hat leider auch nicht den erhofften Erfolg gebracht, ich habe es sowohl per IPv6 NAT Port-Redirect als auch per DNAT versucht. Im besten Fall kam die Meldung, dass die DNS-Antwort von einer unerwarteten IP-Adresse(OpenWRT Router) stammte...

Sollte jemand eine Idee haben, wie ich einen transparenten DNS-Proxy bauen kann, wäre ich für jeden Tipp dankbar!