Einen Router bauen
arrow.gif Entwicklungsumgebung
arrow.gif Hardware Plattformen
arrow.gif Slackware Router
arrow.gif Downloads
   
Weiterentwicklung
arrow.gif Tasks pending
arrow.gif Bugs
   
Informationen
arrow.gif Security
arrow.gif FAQ
arrow.gif Links
 
Slackware Linux Router
Prev Next

18. IPv6 Router

18.1 IPv6 und Linux

IPv6 wurde von der IETF (Internet Engineering Task Force) 1998 standardisiert. Alle grossen Linux-Distributionen, auch Slackware 11.0, das Basis-System von Linuxrouter, sind IPv6-fähig.

Für das vorliegende HowTo wurde Linuxrouter mit fixer IPv4 Adresse, FTTH (fiber-to-the-home) Anbindung, und mit der folgenden Software-Ausstattung betrieben:

Basis System: Slackware 11.0
Kernel: linux-2.6.39
gcc-3.4.6
libc-2.3.6
dhcpcd-2.0.4 (IPv4 DHCP client)
iptables-1.4.21
iproute2-3.1.0
wide-dhcpv6c-20080615
radvd-0.9.1 (optional)
 

18.2 Kernel

Zur Zeit (2019) stellen die Internet Service Provider (ISP) ihren Kunden IPv6 entweder nativ oder mittels einer IPv6-in-IPv4 Tunnel-Technologie namens 6RD (IPv6 Rapid Deployment) zur Verfügung.

6RD-Unterstützung ist im Linux-Kernel seit Version >=2.6.33 verfügbar, es empfiehlt sich somit, bei der Bereitstellung eines IPv6-Routers einen Kernel mit entsprechender Version zu verwenden. Es liegt auf der Hand, dass IPv6-Netfilter-Unterstützung ebenfalls erforderlich ist.

General Setup -->
Networking support --> Networking options --> 
[*] The IPv6 protocol --> 
  [*] IPv6: IPv6-inIPv4 tunnel (SIT driver)
  [*] IPv6: IPv6 Rapid Deployment (6RD))

Networking support --> Networking options --> 
[*] Network packet filtering framework (Netfilter) --> 
  IPv6: Netfilter Configuration -->
    [*] Select as required
 

18.3 Tools

iproute2, die Sammlung von Netzwerk-Tools von A. Kuznetsov ist zwingend erforderlich, wenn es nötig sein sollte, ein 6RD Tunnel-Interface zu konfigurieren. Das Kompilieren von iproute2 auf älteren Systemen kann herausfordernd sein. Eine Version wählen, die ungefähr dem Alter des verwendeten Kernels entspricht und nicht versuchen, sämtliche mögliche Features der Toolbox zu kompilieren.

18.4 Daemons

wide-dhcpv6 ist eine Implementation von DHCPv6, die ursprünglich für das KAME Projekt entwickelt wurde. Der wide-dhcpv6-client konfiguriert die Linuxrouter-Interfaces und ist erforderlich, wenn natives IPv6 eingesetzt wird.

BEACHTEN: wide-dhcpv6 lässt sich auf Slackware (auf Linux?) nur kompilieren, wenn zuvor die zugehörigen Debian-Patches eingespielt wurden! Der Dank für diesen entscheidenden Tipp geht an den Autor von https://www.blinkenlights.ch

wide-dhcpv6-20080615.tar.gz downloaden von: https://sourceforge.net
wide-dhcpv6_20080615-12.debian.tar.gz downloaden von: http://http.debian.net

wide-dhcpv6-20080615 kompilieren und auf dem Router installieren.

radvd, der «Router Advertisement Daemon» muss installiert werden, falls sich die Hosts der lokalen LANs mittels «IPv6 Stateless Address Autoconfiguration» (SLAAC) selbst konfigurieren und dafür von Linuxrouter mit ihrem IPv6-Address-Präfix versorgt werden müssen. Wenn die lokalen Maschinen manuell or mittels DHCPv6 konfiguriert werden, kann auf radvd verzichtet werden. Download: http://www.litech.org/

18.5 IPv6: Internes Netzwerk

IPv6 verwendet 128 bit Adressen. Eine IPv6 Adresse ist unterteilt in einen Netzwerk Teil («routing prefix») von 64 bit und einen «interface identifier» von 64 bit.

IPv6 Adressen sind nicht nur länger als die gewohnten 32 bit IPv4 IPs, sie haben auch einen anderen Funktionsumfang. Eine Eigenschaft von IPv6 Netzen, die ein Umdenken erfordert, ist, dass es mit IPv6 normal - sozusagen Teil des Systems ist - dass mehrere IPs, die verschiedenen Klassen angehören und verschiedene Funktionen haben, an die gleiche Netzwerkkarte gebunden werden.

Beispielsweise wird ein IPv6-fähiger Kernel einem für IPv4 konfigurierten Interface selbständig eine «link-local» IPv6 Adresse zuweisen, die mit dem Präfix «fe80» beginnt und Teile der Hardware-Adresse der Netzwerkkarte beinhaltet. Link-local Adressen sind nicht «routable», werden aber für IPv6 Features wie das «Neighbor Discovery Protocol» benötigt.

Um die Kommunikation zwischen verschiedenen internen Netzwerk-Segmenten sicherzustellen, und auch aus Gründen der Übersichtlichkeit, ist es sinnvoll, ein internes IPv6-Address-Schema bereitzustellen. Das Stichwort hierzu lautet ULA «Unique Local Address». ULAs sind nicht im Internet aber zwischen verschiedenen internen Netzwerk-Segmenten «routable». ULAs beginnen mit dem Adressblock fd00::/8 und sind als /48 Präfix definiert. Die folgenden 16 bit dienen als Subnet ID, die letzten 64 bit definieren das Interface. RFC4193 beschreibt, wie die 40 bit des «routing prefix» generiert werden können, um einen global einmaligen Präfix sicherzustellen. Für ein internes Netzwerk mit drei Segmenten (aus Sicht des Routers eth0, eth2, eth3), kann ein Address-Schema somit wie folgt aussehen:


fdxx:yyyy:zzz::1 -> router address for eth0
fdxx:yyyy:zzz::2 -> first host in network 0 connected to eth0
fdxx:yyyy:zzz:2::1 -> router address for eth2
fdxx:yyyy:zzz:2::2 -> first host in network 2 connected to eth2
fdxx:yyyy:zzz:3::1 -> router address for eth3
fdxx:yyyy:zzz:3::2 -> first host in network 3 connected to eth3
 

18.6 IPv6: Internet Anbindung mittels 6RD

Für den Zugang zum globalen IPv6 Internet benötigt eine Netzwerkkarte zusätzlich zur ULA eine UGA (Unique Global Address). Der weltweit einmalige IPv6-Präfix der UGA kann nicht selbst generiert werden, sondern muss vom Internet Service Provider zugewiesen werden. Verbreitete Verfahren hierzu sind «native» IPv6 und die 6RD-Tunnel-Technologie.

Die Idee von 6RD besteht darin, dass ein IPv4 CE (Customer Equipment, hier Linuxrouter) IPv6-Pakete als Payload in IPv4-Paketen unterbringt und diese an den IPv4 BR (Border Relay) des Providers sendet. Der BR entpackt die ankommenden IPv4 Frames und leitet den IPv6 Content ins IPv6 Internet weiter.

6RD benötigt:
-Den IPv6 Präfix des Internet Service Providers. Beispiel: 2a02:1200::/28
-Die fixe IPv4 IP von Linuxrouter. Fiktives Beispiel: 172.20.121.122
-Die IPv4 Addresse des Tunnelendpunkts auf auf Seite ISP. Beispiel: 193.5.29.1

Aus den obigen Parametern wird der «delegated prefix» generiert, dazu wird die öffentliche IPv4 IP von Linuxrouter nach Hex konvertiert und zum IPv6 Präfix hinzugefügt:


printf "%02x%02x:%02x%02x\n" 172 20 121 122
ac14:797a
Your IPv6 delegated prefix (public address block) is therefore:
2a02:120a:c147:97a0::/60
 

Da der Provider einen /28 Präfix verwendet, bleiben 4 bit für die Definition von 2^4 Subnetzen. Es können somit die folgenden lokalen Netze konfiguriert werden:


2a02:120a:c147:97a0::/64
up to
2a02:120a:c147:97af::/64
 

Für die Konfiguration des 6RD-Tunnels gehen wir von vier Netzwerkkarten aus:
eth1 ist das Internet Interface, eth0, eth2, eth3 bedienen lokale Netze.
Den internen NICs werden UGAs zugewiesen:


# ifconfig eth0 inet6 add 2a02:120a:c147:97a0::1/64
# ifconfig eth2 inet6 add 2a02:120a:c147:97a2::1/64
# ifconfig eth3 inet6 add 2a02:120a:c147:97a3::1/64
 

Für eth1 wird «hugo», der 6RD-Tunnel konfiguriert.


Create your 6rd tunnel and bind it to your public IP:
# ip tunnel add hugo mode sit local 172.20.121.122 ttl 64

Add your provider's 6RD prefix to the tunnel:
# ip tunnel 6rd dev hugo 6rd-prefix 2a02:1200::/28

Assign an IPv6 address to the tunnel link:
# ip -6 addr add 2a02:120a:c147:97a1::1/28

Bring your link up:
# ip link set hugo up
# ip link show hugo

Add a route to direct outgoing IPv6 traffic into the tunnel:
# ip -6 route add 2000::/3 via ::193.5.29.1 dev hugo
 

Die so erstellte IPv6 Verbindung testen mittels:


# ping6 ipv6.google.com
# traceroute6 ipv6.google.com
https://test-ipv6.com/
 

Den internen Maschinen manuell oder mittels radvd und router-solicitation ihre UGAs und default Routen zuweisen. Beispiel:


# ifconfig eth0 inet6 add 2a02:120a:c147:97a3::2/64 -> first host in network 3 connected to eth3
# ip -6 route add 2000::/3 via 2a02:120a:c147:97a3::1 dev eth0 -> route to global IPv6 addresses
 

18.7 IPv6: Internet Anbindung mittels «native» IPv6

Falls der Internet Service Provider «native» IPv6 zur Verfügung stellt, IPv6 Pakete also nicht in IPv4 einzupacken sind, sollte sich die IPv6 Anbindung einfacher gestalten. Unter der Annahme, dass Linuxrouter via eth1 mit dem WAN verbunden ist, und die öffentliche IP mittels DHCP bezogen wird, wird der Router beim Booten für eth1:

-Per DHCP Client seine IPv4 Adresse konfigurieren.
-Mittels SLAAC eine fe80 Adress generieren.
-Mittels SLAAC/router-solicitation eine «Scope:Global» IPv6 Adresse zuweisen. (*)

Die IPv6 Verbindung zum Provider ist damit im Prinzip gegeben. Was noch fehlt sind die GUAs (Global Unicast Address) für die LANs. Diese werden mittels «Prefix Delegation» generiert. PD ist ein Verfahren, mit dem der Internet Service Provider seinen Kunden einen global einmaligen IPv6 Präfix aus seinem Address-Pool zur Verfügung stellt (für eine vertiefte Diskussion siehe ipv6_prefix_delegation). Basierend auf diesem Präfix generiert der wide-dhcpv6c Daemon die GUAs der internen Interfaces.

Die Konfiguration von wide-dhcpv6c erfolgt mittels /etc/dhcpv6/dhcp6c.conf, der Start des Daemons erfolgt in bewährter Slackware/BSD Manier mittels /etc/rc.d/rc.dhcp6c.

Die folgende Konfiguration weist eth0, eth2, eth3 je eine Unique Global Address von folgender Form zu:
2001:xxxx:yyyy:zzz3::1/64 -> eth3
2001:xxxx:yyyy:zzz2::1/64 -> eth2
2001:xxxx:yyyy:zzz0::1/64 -> eth0

# /etc/dhcpv6/dhcp6c.conf
# wide-dhcpv6-20080615 client configuration file.
# For dhcp6c configuration options see:
# /usr/local/wide-dhcpv6/man/man5/dhcp6c.conf.5
# 2019-05-28

# Send a prefix delegation request via WAN interface to the ISP's pd server
interface eth1 {
   send ia-pd 0;
};

# Assign Unique Global Addresses to eth3, eth2, eth0
id-assoc pd 0 {
    prefix-interface eth3 {
            sla-id 3;       # Set your subnet address to :xxx3:
            sla-len 8;      # Subnet bits (provider uses /56 prefix )
            ifid 1;         # Configure eth3 as link ::1
    };
    prefix-interface eth2 {
            sla-id 2;
            sla-len 8;
            ifid 1;
   };
    prefix-interface eth0 {
            sla-id 0;
            sla-len 8;
            ifid 1;
   };
};
 

Den internen Maschinen, manuell oder mittels radvd und router-solicitation ihre UGAs zuweisen. Beispiel:


# ifconfig eth0 inet6 add 2001:xxxx:yyyy:zzz3::2/64 -> first host in network 3 connected to eth3
# ip -6 route add 2000::/3 via 2001:xxxx:yyyy:zzz3::1 -> route to global IPv6 addresses
 

 

*) BEACHTEN: Eine Linux Maschine, die sich als Router fühlt, wird router-advertisements ignorieren. Dies ist nachvollziehbar, denn eine Service Maschine wie ein Router sollte manuell und statisch konfiguriert werden. Im vorliegenden Fall ist dieses Verhalten jedoch nicht erwünscht.

Der Kernel sieht sich dann als Router, wenn ip_forward aktiviert ist - was bei Linuxrouter aus naheliegenden Gründen gegeben ist.

Um das Default-Verhalten des Kernels zu übersteuern, muss für Kernel >=2.6.37 der Kernel-Parameter accept_ra für eth1 auf den Wert 2 gesetzt werden (vorzugsweise im Firewall Script nachdem ip_forward=1 gesetzt wurde). Ohne diesen Eintrag wird SLAAC für das WAN Interface eth1 fehlschlagen und IPv6 wird nicht funktionieren.


echo 2 > /proc/sys/net/ipv6/conf/eth1/accept_ra
 

18.8 IPv6: Firewall Regeln

Der grundsätzliche Aufbau eines Firewalls für IPv6 Pakete unterscheidet sich nicht von IPv4:

-Alle Verbindungen per Default-Regeln unterbinden.
-Überlegen, welche Verbindungen benötigt werden.
-Diese zulassen.

Da lokale IPv6 Hosts über globale, eindeutige, «routable» IPs verfügen, entfallen Hilfskonstrukte wie NAT oder Port Forwarding, was das Firewall Script übersichtlicher macht. («stateful» Paket-Filter-Regeln sind selbstverständlich nach wie vor möglich.)

NAT wurde bekanntermassen nie als Security-Feature konzipiert, hat aber trotzdem eine gewisse Trennung zwischen Internet und LAN bewirkt. Mit IPv6 entfällt diese Trennung. IPv6 IPs sind im Internet bekannt und werden von den Routern weitergeleitet. Wenn ein IPv4 Firewall Script nicht ordnungsgemäss zu Ende läuft, wird der Administrator oder User dies bemerken, weil Verbindungsversuche ins Internet fehlschlagen. Mit IPv6 ist dies nicht notwendigerweise der Fall, und es ist möglich, dass ein LAN ohne Firewall-Schutz mit dem Internet verbunden wird. Es ist daher empfehlenswert ip_forward erst am Schluss des Firewall-Scripts zu aktivieren - was auch bei einem IPv4-Firewall kein schlechtes Vorgehen sein dürfte!

Der grösste Unterschied zu IPv4 betrifft ICMP. Pings haben unter IPv6 eine wichtige Rolle, und einige Typen müssen zwingend zugelassen werden, ansonsten das IPv6 Netzwerk nicht funktionieren wird. Eine ICMPv6 Parameterliste wird von ICMPv6 bereitgestellt.

Ein IPv6 Referenz-Firewall-Script ist auf cert_firewall verfügbar. Es handelt sich allerdings um einen Vorschlag für eine LAN-Maschine und nicht für einen Router. Das Script kann aber angepasst werden und ist als Referenz für den ersten Wurf eines Router-Scripts sehr hilfreich, denn - wie der folgende Abschnitt zeigt - ist ICMPv6 nicht unkomplex!

Beispiel für die ICMPv6 Regeln eine Router-Firewalls:

#
# ===========================================================================
# RULES FOR ICMPV6
# ===========================================================================
#
# ---------------------------------------------------------------------------
# Allow incoming and outgoing ICMPv6 packets from the Internet to the router
# ---------------------------------------------------------------------------
#
# Allow mandatory ICMPv6 types in the INPUT and OUTPUT chains.
${IP6TABLES} -A INPUT -p ICMPV6 -i ${EXT6} --icmpv6-type destination-unreachable -j ACCEPT
${IP6TABLES} -A INPUT -p ICMPV6 -i ${EXT6} --icmpv6-type packet-too-big -j ACCEPT
${IP6TABLES} -A INPUT -p ICMPV6 -i ${EXT6} --icmpv6-type time-exceeded  -j ACCEPT
${IP6TABLES} -A INPUT -p ICMPV6 -i ${EXT6} --icmpv6-type parameter-problem -j ACCEPT

${IP6TABLES} -A OUTPUT -p ICMPV6 -o ${EXT6} --icmpv6-type destination-unreachable -j ACCEPT
${IP6TABLES} -A OUTPUT -p ICMPV6 -o ${EXT6} --icmpv6-type packet-too-big -j ACCEPT
${IP6TABLES} -A OUTPUT -p ICMPV6 -o ${EXT6} --icmpv6-type time-exceeded  -j ACCEPT
${IP6TABLES} -A OUTPUT -p ICMPV6 -o ${EXT6} --icmpv6-type parameter-problem -j ACCEPT

# Accept multicast listener messages.
${IP6TABLES} -A INPUT -p ICMPV6 -i ${EXT6} --icmpv6-type 130 -j ACCEPT
${IP6TABLES} -A INPUT -p ICMPV6 -i ${EXT6} --icmpv6-type 131 -j ACCEPT
${IP6TABLES} -A INPUT -p ICMPV6 -i ${EXT6} --icmpv6-type 132 -j ACCEPT

${IP6TABLES} -A OUTPUT -p ICMPV6 -o ${EXT6} --icmpv6-type 130 -j ACCEPT
${IP6TABLES} -A OUTPUT -p ICMPV6 -o ${EXT6} --icmpv6-type 131 -j ACCEPT
${IP6TABLES} -A OUTPUT -p ICMPV6 -o ${EXT6} --icmpv6-type 132 -j ACCEPT

# Allow router-solicitation and NDP (Neigbour Discovery Protocol) 
# between Linuxrouter and ISP.
${IP6TABLES} -A INPUT -p ICMPV6  -i ${EXT6} --icmpv6-type router-solicitation    -j REJECT
${IP6TABLES} -A INPUT -p ICMPV6  -i ${EXT6} --icmpv6-type router-advertisement   -j ACCEPT
${IP6TABLES} -A INPUT -p ICMPV6  -i ${EXT6} --icmpv6-type neighbor-solicitation  -j ACCEPT
${IP6TABLES} -A INPUT -p ICMPV6  -i ${EXT6} --icmpv6-type neighbor-advertisement -j ACCEPT

${IP6TABLES} -A OUTPUT -p ICMPV6 -o ${EXT6} --icmpv6-type router-solicitation    -j ACCEPT
${IP6TABLES} -A OUTPUT -p ICMPV6 -o ${EXT6} --icmpv6-type router-advertisement   -j REJECT
${IP6TABLES} -A OUTPUT -p ICMPV6 -o ${EXT6} --icmpv6-type neighbor-solicitation  -j ACCEPT
${IP6TABLES} -A OUTPUT -p ICMPV6 -o ${EXT6} --icmpv6-type neighbor-advertisement -j ACCEPT
${IP6TABLES} -A OUTPUT -p ICMPV6 -o ${EXT6} --icmpv6-type redirect -j REJECT

# Allow router-solicitation from internal hosts (Linuxrouter running radvd).
${IP6TABLES} -A INPUT  -p ICMPV6 -i ${INT} --icmpv6-type router-solicitation    -j ACCEPT
${IP6TABLES} -A OUTPUT -p ICMPV6 -o ${INT} --icmpv6-type router-advertisement   -j ACCEPT 
${IP6TABLES} -A INPUT  -p ICMPV6 -i ${DMZ1} --icmpv6-type router-solicitation    -j ACCEPT
${IP6TABLES} -A OUTPUT -p ICMPV6 -o ${DMZ1} --icmpv6-type router-advertisement   -j ACCEPT 
${IP6TABLES} -A INPUT  -p ICMPV6 -i ${DMZ2} --icmpv6-type router-solicitation    -j ACCEPT
${IP6TABLES} -A OUTPUT -p ICMPV6 -o ${DMZ2} --icmpv6-type router-advertisement   -j ACCEPT 

# Allow incoming pings to the router.
${IP6TABLES} -A INPUT -p ICMPV6 -i ${EXT6} --icmpv6-type echo-request -j ACCEPT
${IP6TABLES} -A OUTPUT -p ICMPV6  -o ${EXT6} --icmpv6-type echo-reply -j ACCEPT

# Allow outgoing pings from the router.
${IP6TABLES} -A OUTPUT -p ICMPV6 -o ${EXT6} --icmpv6-type echo-request -j ACCEPT
${IP6TABLES} -A INPUT  -p ICMPV6 -i ${EXT6} --icmpv6-type echo-reply   -j ACCEPT

# Drop all other ICMPv6 types.
${IP6TABLES} -A INPUT  -p ICMPV6 -j DROP
${IP6TABLES} -A OUTPUT -p ICMPV6 -j DROP

# Set ICMPv6 FORWARD rules as appropriate.
# ...
 

18.9 IPv6: Security Background

ipv6_security.pdf diskutiert das Thema «IPv6 Security» im Detail und enthält zahlreiche Hinweise, die im IPv6 Firewall-Script berücksichtigt werden können.

 


Prev Home Next
Linuxrouter v0.50 Content Ramdisk Router