The Net Wizard HauptseiteISP SetupNetzwerkeVelotourenSoftwareKryptografieVaria

IPv6 Tunnel zu Hause

1. Vortrag am Linuxtag in Dornbirn

Am 23.11.2013. haben Axel, Martin und ich einen Vortrag zum Thema ipv6 zu Hause einrichten gehalten. Die Folien dazu finden sich hier bzw. hier.

2. Das Netwerk

Hier ein kleiner Überblick meines Heimnetzwerkes:

Network Diagram

Als Firewall setze ich ein Alix Board mit 3 Interfaces ein, auf dem ein Debian stable laeuft. Ein Interface ist mit dem Kabelmodem verbunden, eines mit dem LAN und wiederum eines mit dem Access Point, der für das Wireless network zuständig ist. Sämtliche Komponenten laufen unter Linux. Als Access Point dient ein TP WR1043ND, auf dem OpenWrt installiert ist.

3. Der Tunnel

Da mein Provider immer noch kein IPv6 anbietet, habe ich einen IPv6 Tunnel bei Hurricane Electric eingerichtet. Der Tunnelendpunkt ist dabei auf dem Alix board konfiguriert (siehe weiter unten). Nach der Anmeldung wird man auf eine Seite geleitet, welche die Konfigurationsdetails anzeigt. Unter Example Configurations kann man sich das verwendete OS auswählen, und schon werden die Befehle angezeigt, die zur Konfiguration des Tunnels benötigt werden. Für das von mir eingesetzte Debian sind die folgenden Schritte notwendig:

  • ip tunnel add he-ipv6 mode sit remote Server-IP4 local Client-IP4 ttl 255
  • ip link set he-ipv6 up
  • ip addr add client-IP6 dev he-ipv6
  • ip route add ::/0 dev he-ipv6

Wer nur eine IPv6 Adresse braucht, ist hier auch schon fertig. Wenn man aber eigene Netze betreiben will, kann man sich ein /48 Netz von Hurricane Electric zuteilen lassen. Das reicht aus, um bei sich daheim 2^16 (65 536) Netwerke zu betreiben. Ganz so viele IPv6 fähige Geräte habe ich aber nicht, weswegen ich mich für 2 /64 Netze entschieden habe. Diese habe ich auf das Lan-Interface resp. das wireless Interface konfiguriert. Zudem muss man dem kernel noch mitteilen, dass er ipv6 Pakete forewarden darf, und welche Netze wohin gerouted werden sollen:

  • echo 1 > /proc/sys/net/ipv6/conf/eth1/forwarding
  • echo 1 > /proc/sys/net/ipv6/conf/eth2/forwarding
  • echo 1 > /proc/sys/net/ipv6/conf/eth0/forwarding
  • echo 1 > /proc/sys/net/ipv6/conf/all/forwarding
  • ip -6 route add IPv6-Addr LAN dev eth1
  • ip -6 route add IPv6-Addr Wireless dev eth2
Als nächstes habe ich auf der Firewall den radvd konfiguriert. Einfach den prefix in der Sektion des entsprechenden Interfaces eintragen. Wenn nun ein ipv6- fähiger Client booted, bekommt er automatisch eine ipv6 Adresse.

Hurricane Electric bietet übrigens eine Zertifizierung an, die sehr zu empfehlen ist. Das Zertifikat sieht dann folgendermassen aus:
IPv6 Certification Badge for rmeyer

4. Firewall Regeln

Nun muss noch die Firewall so konfiguriert werden, dass sich die beiden Netze sehen. Dazu habe ich ein kleines Startskript geschrieben, welched die Regeln enthaelt. Dabei muss man zwischen ipv4 und ipv6 unterscheiden, da es bei letzterem ja keine Net Address Translation (NAT) mehr gibt.
3.1. IPv4 mit NAT
In der IPv4 Welt bekommt man typischerweise genau eine IP Adresse zugeteilt. Das ist etwas problematisch, wenn man mehr als ein Gerät betreiben möchte. Darum wurden bestimmte Bereiche des Adressraumes definiert, die im globalen Internet nicht groutet werden. Diese Bereiche werden private Adresses genannt (im Gegensatz zu public Adresses). Diese kann man für ein eigenes Netzwerk benutzen. Dazu muss man allerdings den TCP Header von allen ausgehenden Paketen umschreiben. Dies geschieht unter Linux mit iptables. Wenn man eine Verbindung mit einem Rechner im Internet aufbaut geschieht im Wesentlichen folgendes:
  1. Das Paket verlässt den Client mit der Adresse des Clients
  2. Die Firewall ersetzt die IP Adresse im TCP Header mit der eigenen public Adresse
  3. Die Firewall merkt sich, welche Client Adresse gerade umgeschrieben wurde
  4. Die Firewall baut eine Verbindung zum Zielrechner auf
  5. Der Zielrechner schickt die Antwort an die Firewall zurück
  6. Die Firewall schreibt die IP Adresse im TCP Header wieder um und schickt das Paket an den Client zurück
Dieses Verhalten ist ziemlich kontrovers. Einerseits kann man so die Rechner im eigenen Netz sehr effizient schützen, da diese ja nicht direkt aus dem Internet ansprechbar sind. Andererseits wird es schwierig, Dienste aus dem eigenen Netzwerk heraus anzubieten. Wenn ich beispielsweise einen Webserver im eigenen Netz betreiben möchte, muss ich auf der Firewall definieren, dass alle Pakete, die an die public Adresse der Firewall kommen, an eine bestimmte Adresse weitergeleitet werden. Meine persönliche Meinung ist, dass es durchaus machbar ist, sein eigenes Netz zu schützen, auch wenn jeder Client eine Adresse hat, die von überall her erreichbar ist. Es kann aber durchaus sein, dass der Sicherheitsverantwortliche einer Firma hier anderst denkt.

Hier das Ruleset für ipv4:

01:
02:
03:
04:
05:
06:
07:
08:
09:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
#!/bin/sh

PATH=/usr/sbin:/sbin:/bin:/usr/bin

#
# delete all existing rules.
#
iptables -F
iptables -t nat -F
iptables -t mangle -F
iptables -X

echo -n "Installing Firewall..."
# Configure TCP/IP
echo "1" > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
echo "32768 61000" >/proc/sys/net/ipv4/ip_local_port_range

# Always accept loopback traffic
/sbin/iptables -A INPUT -j ACCEPT -i lo

# Allowin (most) ICMP requests to everyone
/sbin/iptables -A INPUT -j DROP -p icmp --icmp-type router-advertisement
/sbin/iptables -A INPUT -j DROP -p icmp --icmp-type router-solicitation
/sbin/iptables -A INPUT -j DROP -p icmp --icmp-type redirect
/sbin/iptables -A INPUT -j ACCEPT -p icmp -m limit --limit 120/minute

#Allow ssh from the outside
/sbin/iptables -A INPUT -p tcp --dport 22 -s 0/0 -d 0/0 -j ACCEPT

#allow proto 41 for ipv6
/sbin/iptables -A INPUT -p 41 -j ACCEPT
/sbin/iptables -A OUTPUT -p 41 -j ACCEPT

#allow sip
iptables -A INPUT -s $IP_SIP_PROVIDER -p udp --dport 5060 -j ACCEPT
iptables -A FORWARD -o eth0 -p udp --dport 5060 -j ACCEPT

# Allow established connections, and those not coming from the outside
/sbin/iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
/sbin/iptables -A INPUT -m state --state NEW ! -i eth0 -j ACCEPT
/sbin/iptables -A FORWARD -i eth0 -o eth1 -m state --state ESTABLISHED,RELATED -j ACCEPT
/sbin/iptables -A FORWARD -i eth0 -o eth2 -m state --state ESTABLISHED,RELATED -j ACCEPT

# Allow outgoing connections from the LAN side.
/sbin/iptables -A FORWARD -i eth1 -o eth0 -j ACCEPT
/sbin/iptables -A FORWARD -i eth2 -o eth0 -j ACCEPT
/sbin/iptables -A FORWARD -i eth2 -o eth1 -j ACCEPT
/sbin/iptables -A FORWARD -i eth1 -o eth2 -j ACCEPT

# Masquerade.
/sbin/iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
#incomming sip
iptables -t nat -A PREROUTING -i eth0 -s $IP_SIP_PROVIDER -p udp -m udp --dport 5060 -j DNAT --to-destination $IP_SIPPHONE

# Don't forward new traffic from the outside to the inside.
/sbin/iptables -A FORWARD -i eth0 -o eth1 -j REJECT
/sbin/iptables -A FORWARD -i eth0 -o eth2 -j REJECT

# Set default rule to reject EVERYTHING
/sbin/iptables -A INPUT -j REJECT
/sbin/iptables -A FORWARD -j REJECT

# Enable routing.
echo 1 > /proc/sys/net/ipv4/ip_forward

Mit Hilfe der Kommentare sollten die meisten Regeln eigentlich verstädlich sein. Etwas speziell sind die Regeln für SIP. Da sich das VOIP Telephon hinter der Firewall befindet, müssen eingehende Pakete für VOIP entsprechend genatted werden.

3.1. IPv6 ohne NAT
Glücklicherweise braucht man bei IPv6 kein Nat Adress Translation mehr, da es ja genügend IP Adressen für jeden gibt. Trotzdem möchte man sein internes Netz natürlich gegen Zugriff von aussen möglichst gut schützen. Um das zu erreichen, blockt man im Wesentlichen jeglichen Verkehr von aussen, es sei den er gehöre zu einer bereits existierenden Verbindung. Dies stellt sicher, dass alle Verbindungen, die vom internen Netz initiert werden, erlaubt sind. Angriffe von aussen werden hingegen geblockt.

Hier das Ruleset dazu:

01:
02:
03:
04:
05:
06:
07:
08:
09:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
#!/bin/sh

PATH=/usr/sbin:/sbin:/bin:/usr/bin

# part for ipv6
# Clear our INPUT, OUTPUT and FORWARD chains
/sbin/ip6tables -F INPUT
/sbin/ip6tables -F OUTPUT
/sbin/ip6tables -F FORWARD

# Allow link-local (for neighbour discovery)
/sbin/ip6tables -A INPUT -s fe80::/10 -j ACCEPT

#allo icmp
/sbin/ip6tables -A INPUT -p ipv6-icmp -j ACCEPT
/sbin/ip6tables -A FORWARD -p ipv6-icmp -j ACCEPT

# Allow all inbound from our networks
/sbin/ip6tables -A INPUT -i eth2 -s 2001:470:b694:2::/64 -j ACCEPT
/sbin/ip6tables -A INPUT -i eth1 -s 2001:470:b694:1::/64 -j ACCEPT

# Allow packets related to existing connections
/sbin/ip6tables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
/sbin/ip6tables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT

# Allow all outbound from our networks
/sbin/ip6tables -A FORWARD -i eth2 -s 2001:470:b694:2::/64 -j ACCEPT
/sbin/ip6tables -A FORWARD -i eth1 -s 2001:470:b694:1::/64 -j ACCEPT

# Allo all traffic between internal net
/sbin/ip6tables -A FORWARD -i eth1 -o eth2 -j ACCEPT
/sbin/ip6tables -A FORWARD -i eth2 -o eth1 -j ACCEPT

# Allow all outbound from our gateway
/sbin/ip6tables -A OUTPUT -j ACCEPT

# Set the default policy to drop
ip6tables -P INPUT DROP
ip6tables -P FORWARD DROP

# route v6 traffic
echo 1 > /proc/sys/net/ipv6/conf/all/forwarding

echo "done"

Powered by w3.css