Archive for febbraio, 2012

Feb 4

Last year I wrote how to create and configure an IPv6 over IPv4 tunnel with Hurricane Electric.
Now I’m gonna write how to configure a Linux host with two NICs as an IPv6 router using an HE tunnel when behind a NAT-router.
The examples here are referred to a Debian 6 Linux distribution and may be sligthly different for other distros or *BSD OSs.

Let’s suppose your current IPv4 network is a classical with a netmask ( /16 in short ), and that your IPv4 NAT-router is located at
The first thing you need to do is to configure one of the interfaces of your IPv6 router, let’s say eth0, with a fixed IPv4 address in the same subnet of your router, like
Then you have to make sure that your NAT-router forward protocol 41 to your IPv6 router. If this is not the case, you can simply put you IPv6 router in the DMZ. Be careful when you do that! Be sure to apply strong IPv4 firewall policies and keep the daemons listening to that interface at the minimum, maybe on non-standard ports.
After configuring the IPv6 router default IPv4 route ( to your NAT-router of course ), test if you can reach an address outside the local subnet, like ( Google Domain Name Server ).
You’ll also like to assign an IPv4 address to the other network interface, for instance eth1, to allow some daemons to listen to an IPv4 local address ( like sshd or named for IPv4 ).

Debian and other Debian-related distros usually store the network configuration inside the /etc/network/interfaces file.

# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

auto lo
iface lo inet loopback

auto eth0
iface eth0 inet static

auto eth1
iface eth1 inet static

In the tunnel configuration page on the HE’s website you can find the routable /64 subnet. Mind the difference between the tunnel IPv6 addresses, that usually are something like 2001:1234:5678:abc::1 and 2001:1234:5678:abc::2, and your routable IPv6 subnet that will be something like 2001:1234:5679:abc::.
The IPv6 address of eth1 is static ( this is a router after all ) and  must belong to your routable subnet. You can choose of using a simple address, like 2001:1234:5679:abc::1, or, if you’re a bit paranoic, you can randomize it to something like 2001:1234:5679:abc:5f32:9b8c:d12e:15fa.
Because your routable subnet is not gonna change unless you destroy your HE’s tunnel and create a new one, you can configure the eth1 IPv6 address as static and put the configuration inside /etc/network/interfaces, by adding the following lines:

iface eth1 inet6 static
   pre-up /sbin/ip6tables-restore < /etc/iptables/ipv6firewall
   address 2001:1234:5679:abc:5f32:9b8c:d12e:15fa
   netmask 64

The second line is needed to enable the ip6tables firewall.

The configuration for ip6tables is based on a more or less ‘standard’ requirement: all the hosts behind the router have unlimited access to the internet on every protocol or port while they’re not reachable from the rest of world with the exception of some ICMPv6 messages.
Just to avoid some types of DOS attack, I’ve decided to limit the amount of ICMPv6 echo requests the router ( and the network behind ) is gonna receive.
The content of the /etc/iptables/ipv6firewall file is the following:

# Generated by ip6tables-save
:INPUT DROP [23:2392]
:OUTPUT ACCEPT [30:2888]
-A INPUT -i lo -j ACCEPT
-A INPUT -i sit1 -p ipv6-icmp --icmpv6-type echo-request -m limit --limit 5/sec -j ACCEPT
-A INPUT -i sit1 -p ipv6-icmp --icmpv6-type echo-request -j DROP
-A INPUT -i sit1 -p ipv6-icmp -j ACCEPT
-A INPUT -i eth1 -j ACCEPT
-A INPUT -i sit1 -m state --state RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o sit1 -j ACCEPT
-A FORWARD -i sit1 -m state --state RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i sit1 -p ipv6-icmp --icmpv6-type echo-request -m limit --limit 5/sec -j ACCEPT
-A FORWARD -i sit1 -p ipv6-icmp --icmpv6-type echo-request -j DROP
-A FORWARD -i sit1 -p ipv6-icmp -j ACCEPT

Then you need to enable IPv6 forwarding at boot time by putting the following file ( you can name it as you want, as long as it ends with .conf; I’ve called it ipv6_forwarding.conf ) inside the /etc/sysctl.d/ directory:

# /etc/sysctl.d/ipv6_forwarding.conf

net.ipv6.conf.all.forwarding = 1

The next thing to configure is the router advertisement daemon, that can be installed ( as root ) using the command:

# apt-get install radvd

The configuration file is /etc/radvd.conf and should be similar to this one:

interface eth1
   AdvSendAdvert on;
   AdvManagedFlag on;
   MinRtrAdvInterval 5;
   MaxRtrAdvInterval 15;
   AdvLinkMTU 1280;
   prefix 2001:1234:5679:abc::/64

Some flags are required ( like ‘AdvLinkMTU’ set to 1280 ) for the tunnel to work, some are optional ( like ‘AdvManagedFlag’ ). Maybe next time I’ll wrote how to configure a DHCPv6 server. DHCPv6 is a little more complex than DHCPv4 also because it must be deployed side-to-side with router advertisement, but allows far greater flexibility than its IPv4 counterpart.
In the meantime, with IPv4-reachable nameservers answering with AAAA records, there’ll be no real need for IPv6-reachable nameservers on the short term ( that is, until IPv4 will be the mainstream protocol ).

The last part is to set up the tunnel using a shell script. Actually, two scripts are used. The first one contains only variables like the username, the tunnel ID and the password that should be passed via http on SSL to configure the firewall at Hurricane Electric and tell it our public IP.
The file I created is named and is stored inside /root with 0700 permission. The content is the following:



The other file is that contains the real commands needed to create the tunnel. I’ve decided to launch it manually ( must be executed as root ) but you can decide to launch it at boot time writing an init.d script or by simply using another ‘pre-up’ directive in /etc/network/interfaces. The content is the following:


. /root/

rm ipv4_end.php*
wget --no-check-certificate https://$USERNAME:$$TID

ifconfig sit0 up
ifconfig sit0 inet6 tunnel ::123.45.678.90
ifconfig sit1 up
ifconfig sit1 inet6 add 2001:1234:5678:abc::2/64
route -A inet6 add ::/0 dev sit1

The –no-check-certificate flag for wget is needed because of a little issue with an HE’s SSL certificate. Mind the prefix of the sit1 interface and the remote endpoint of the IPv4 tunnel.

After rebooting the IPv6 router, ip6tables and radvd should be already up and running. After launching the script the tunnel should be configured without issuing any other command.

To check if the hosts had received an IPv6 Link-Global address you can use:

$ ifconfig -a

under any UNIX, Unix-like or Linux operating system or

> ipconfig /all

under Windows ( any version after Windows XP SP0 ).

Then you can test if the hosts can reach the IPv6 internet using ping6 under any UNIX, Unix-like or Linux operating system ( excluding Oracle Solaris ) or using ping under Windows or Solaris.