From SixXS Wiki
Jump to: navigation, search

This should be a manual for how to set up a IPv6-tunnel using a Raspberry Pi running on Debian. We assume you have a little experience on how to use your Raspberry with a tool like Putty, so the doing is just shown, not explained too much.
Feel free to edit.


  • an approved user account
  • an approved tunnel with subnet, you chose the AYIYA-tunnel. If not, change it (that will cost credits)
  • a ready-to-go Raspberry (if not, please do sudo apt-get upgrade && sudo apt-get update)
  • connection to Raspberry with Putty is open

You will see, when logged into your user account, that there is an approved "Subnet" containing a few information:

  • Details, a Rxxxxx-number: We do not need that now.
  • A Subnet-prefix like 2001:xxxx:xxxx:xxxx::/64. That is what we need!
  • Tunnel endpoint: Not important now.
  • Tunnel ID: We do not need that for setting up.
  • Subnet name: Also not important now.
  • State: Enabled. It should be enabled, right?

Setting up the Raspberry


First, we'll set up Aiccu, the client, which opens the tunnel and keeps it alive:

  • sudo -i
  • apt-get install aiccu
  • During the installation, you will be asked for your SixXS-account. That is the user account information.
  • If you installed the package without typing in the proper information, or you just did a mistake, finish the installation and open:
    nano /etc/aiccu.conf
  • Here, you will find right at the first lines the "# Login information". Add your details there and save the file.
  • Restart the service afterwards: service aiccu restart
  • Let's check, if the tunnel is up:
    • There should be a separate entry called something like "sixxs". An IP-address in IPv6 should be written next to a tag called "Scope:Global". If yes: Fine.
  • I am sure you would love to see the result of your work, so let's ping an IPv6-page: ping6 google.de


We have to activate the routing between our LAN and the new tunnel:

  • sudo -i
  • nano /etc/sysctl.conf
  • Search for the line containing #net.ipv6.conf.all.forwarding=0, uncomment it and set the value to "1": net.ipv6.conf.all.forwarding=1
  • Let's restart our Raspberry: reboot
  • wait for restarting it and reconnect to it
  • sudo -i
  • Now, we do need a fixed IP-address for our machine:
  • nano /etc/network/interfaces
  • Add new lines:
# IPv6
iface eth0 inet6 static
pre-up modprobe ipv6
address 2001:db8::1
netmask 64

Attention: Replace "2001:db8::1" completely by the "subnet prefix" information provided by Sixxs, the one we noted above and add "1" at the very end. The /64-thing is noted at "netmask"
Attention: If your are connected to your LAN not using interface "eth0", change that as well!

  • Reboot it. reboot
  • wait for reboot and connect to your Raspberry again.
  • sudo -i
  • ifconfig
  • Check at eth0 by using ifconfig if your new address has been applied. The tag is once again "Scope:Global".


Now we need a tool called "Radvd", which does "Router-Advertising". It will distribute your IPv6-addresses to your network.

  • sudo -i
  • apt-get install radvd
  • nano /etc/radvd.conf
  • Now enter the following code:
interface eth0 {
   AdvSendAdvert on;
   AdvManagedFlag on;
   AdvOtherConfigFlag on;
   AdvLinkMTU 1280;
   MaxRtrAdvInterval 300;
   prefix 2001:db8::/64 {
      AdvOnLink on;
      AdvAutonomous on;
      AdvRouterAddr on;

Attention: Remember to use your own prefix. And enter another interface, if you are not connected to your LAN with "eth0"!

  • service radvd start or service radvd restart, if the deamon is already up (you'd get an error message).
  • Now try to have a look, if the world can reach your Raspberry using IPv6. Visit Test-IPv6.com and ping it by entering the fixed IP-address you defined at /etc/network/interfaces.


Well, we are connected now, but everybody can access each machine in your network just as he or she wants. That's probably the worst idea we ever had.


  • sudo -i
  • cd /etc/network
  • nano ip6tables.rules.sh
# Flush all existing rules
ip6tables -F
ip6tables -X
ip6tables -t mangle -F
ip6tables -t mangle -X

# Allow all connections via the tunnel which came from inside our LAN
ip6tables -A INPUT  -i sixxs -m state --state ESTABLISHED,RELATED -j ACCEPT

# Allow connections from localhost to localhost
ip6tables -A INPUT  -i lo -j ACCEPT
ip6tables -A OUTPUT -o lo -j ACCEPT

# Allow all connections from our own LAN
ip6tables -A INPUT   -i eth0 -j ACCEPT
ip6tables -A FORWARD -i eth0 -o eth0 -j ACCEPT
ip6tables -A OUTPUT  -o eth0 -j ACCEPT

# Allow all outgoing connections via our tunnel
ip6tables -A OUTPUT -o sixxs -j ACCEPT

# Allow forwarding packages with No-Next-Header
ip6tables -A FORWARD -p ipv6-nonxt -m length --length 40 -j ACCEPT

# Allow all link-local connections
ip6tables -A INPUT  -s fe80::/10 -j ACCEPT
ip6tables -A OUTPUT -s fe80::/10 -j ACCEPT

# Allow all multicast-connections
ip6tables -A INPUT  -d ff00::/8 -j ACCEPT
ip6tables -A OUTPUT -d ff00::/8 -j ACCEPT

# Allow ICMPv6
ip6tables -I INPUT   -p icmpv6 -j ACCEPT
ip6tables -I FORWARD -p icmpv6 -j ACCEPT
ip6tables -I OUTPUT  -p icmpv6 -j ACCEPT

# Allow forwardings
ip6tables -A FORWARD -m state --state NEW -i eth0 -o sixxs -j ACCEPT
ip6tables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
ip6tables -A FORWARD -m state --state INVALID -j DROP

# Drop all packages with RH0-header
ip6tables -A INPUT   -m rt --rt-type 0 -j DROP
ip6tables -A FORWARD -m rt --rt-type 0 -j DROP
ip6tables -A OUTPUT  -m rt --rt-type 0 -j DROP

## Incoming connections from outside we wish to have ##
# Allow incoming connections to port 22 (SSH)
#ip6tables -A INPUT -p tcp --dport 22 -j ACCEPT

# Allow incoming connections to port 80 (HTTP)
#ip6tables -A INPUT -p tcp --dport 80 -j ACCEPT

# Default-Settings
ip6tables -P INPUT   DROP
ip6tables -P FORWARD DROP
ip6tables -P OUTPUT  DROP

ATTENTION: Please uncomment the "incoming port 22" and "incoming port 80" rules, or perform further rules, if you want to accept incoming connections on any port you need.
ATTENTION: Please note that these rules may not be correct and can cause severe damages to your network. SixXs and the author recommend to check these rules by yourself before applying them.

  • Let's make this file executable and execute it.
  • chmod 744 ip6tables.rules.sh
  • ./ip6tables.rules.sh
  • We'll check at IPv6Scanner.com, if the firewall is working as we wish. Do a ping on your Raspberry-IP (remember, the one you defined at /etc/network/interfaces). We should now see orange buttons only. If we allowed connections to specific ports, we should see them in green.
  • You can see at ip6tables -nvL, what has been accepted and which connections have been dropped.
  • If that is ok, we want to have these rules to be applied after each reboot. Otherwise, our Raspberry will forget them after rebooting.
  • cd /etc/network/if-pre-up.d
  • nano ip6tables-load
  • Enter text:
ip6tables-restore < /etc/ip6tables.rules
exit 0
  • Making it executable: chmod 755 /etc/network/if-pre-up.d/ip6tables-load
  • Execute it: cd /etc/network/if-post-down.d
  • nano ip6tables-save
  • Enter text:
ip6tables-save -c > /etc/ip6tables.rules
if [ -f /etc/ip6tables.downrules ]; then
    ip6tables-restore < /etc/ip6tables.downrules
exit 0
  • Making it executable: chmod 755 /etc/network/if-post-down.d/ip6tables-save
  • And execute it: /etc/network/if-post-down.d/ip6tables-save

Now you should be able to see all of your clients in the LAN to get IPv6-addresses. This should work pretty fast.

We're done!

NTP issues

On a Raspberry Pi (with Raspbian 8), the system clock is not set correctly on startup (although, thanks to the fake-hwclock package, on simple reboots it is only off by about 30 seconds which is within the 120 second margin AICCU demands). So, we want aiccu to start only when the time is synced. I (PVD99-RIPE) have tried various approaches regarding systemd's time-sync target, but that target does not promise synced time, it just promises the systemd-timesyncd has started. If you are using ntp, the time-sync target does nothing at all. For now I have worked around this by editing /etc/init.d/aiccu like this (inserting the until .. line at line 75):

	# Verify that it is in daemonize mode, otherwise it won't ever return
	if [ `grep -c "^daemonize true" /etc/aiccu.conf 2>/dev/null` -ne 1 ]; then
	        log_failure_msg "AICCU is not configured to daemonize on run"
	        exit 1;

	until ntpq -c 'rv 0' | grep -qw sync_ntp ; do sleep 1 ; done

	# Return
	#   0 if daemon has been started
	#   1 if daemon was already running
	#   2 if daemon could not be started

With this change, aiccu comes up for me reliably. This hack could be turned into a systemd unit file that waits for NTP to be synced in the same way and only then allows aiccu to start.

Note: the ntp-wait tool, which comes recommended for these situations, needs 15 minutes to be happy for leap second related reasons. The hack above introduces a 5-10 second delay for me for starting aiccu (while not holding up the rest of system boot, including sshd).

Another way could be installation of ntpdate (apt-get install ntpdate -y) and put "@ reboot /usr/bin/ntpdate -s 0.pool.ntp.org" in your crontab (crontab -e).