IPV6 Sixxs Mini-HOWTO
This Mini-HOWTO is a very brief discussion of what I had to do to get ipv6 working on my internal lan so that everybody could access outside ipv6 addresses, yet prevent people from outside being able to connect back in to our internal network. It works by having one Linux box act as the ipv6 gateway and tunnel ipv6 traffic to a tunnel broker (several free ones are available), and it can tunnel with either a direct internet connection, a firewalled internet connection, or a NAT'ed internet connection, and it will handle all of these automatically. This Mini-HOWTO discusses using Mandriva as the gateway and (in my case) Ubuntu and Windows as clients.
  1. Register an account at sixxs.net. (There are several ipv6 tunnel brokers out there that will give you a free ip or netblock, but I chose to use Sixxs and this Mini-HOWTO is based on that assumption.) There was no rocket science in my choice of Sixxs over, for example, Hurricane Electric. As a matter of fact, I have used freenet6 in the past and I am currently using Hurricane Electric for the tunnel to my website. They all seem to be equal in terms of what they offer, differing only slightly in how they go about offering it to you.
  2. Request a tunnel. It will take a day or less for it to get approved. This information will be used in the steps below. The Sixxs staff is all volunteers, so the fact that they get to it this fast is impressive.
  3. Decide which machine is going to be the gateway machine, the one that will connect to the Sixxs service and establish the tunnel. There are some very specific requirements. First, it must have a fairly recent kernel and iptables. For my gateway, I'm using a Mandriva box which is running kernel 2.6.22 and iptables 1.3.7. It should also work with the latest Fedora Core release, as well as the latest CentOS 5 or RedHat EL 5 release. This machine will need to have ipv6 support enabled and ipv6 autoconfiguration enabled. In the case of my Ubuntu box, this results in an eth0 interface that looks like this:
    # ifconfig eth0 eth0 Link encap:Ethernet HWaddr 00:90:27:E0:0A:00 inet addr: Bcast: Mask: inet6 addr: fe80::290:27ff:fee0:a00/64 Scope:Link
    The "Scope:Link" address is an automatically generated ipv6 address that is designed to work ONLY on the local LAN. (network fe80::/16) Step 14 shows what the ethernet IPs will look like once this procedure is finished. Note that you could use CentOS 4 as ipv6 clients, but since it cannot do the stateful ipv6 firewalling, you really shouldn't be using it for your router.
  4. Install the radvd package. We won't use it until later, but install it now and get that step over and done with. For CentOS, configure and enable the DAG repo and 'yum install radvd'. For Mandriva, it takes a few extra steps.
    useradd radvd mkdir /var/run/radvd chown radvd:radvd /var/run/radvd
  5. Compile and install the source for aiccu, which is the tunnel software. There is a great write-up on the Sixxs wiki, so I will just let you read their installation instructions.
  6. Edit the configuration file in /etc/aiccu.conf. Leave the defaults unchanged except for:
    username -> the user you registered at Sixxs password -> and the password for that user server tic.sixxs.net protocol tic tunnel_id YOUR_TUNNEL_ID makebeats true
    The YOUR_TUNNEL_ID is the name of the tunnel assigned to you by Sixxs in one of the earlier steps. There is one more potential setting: If you are behind a NAT (for example, a wireless gateway), then you'll also want to set:
    behindnat true
  7. Enable the service to start at boot.
    RedHat/CentOS and Mandriva:
    chkconfig aiccu --add chkconfig aiccu on # should be on by default, but just in case
  8. Configure the machine for ipv6 and forwarding those ipv6 packages across interfaces. In /etc/sysconfig/network:
    Set ipv6 settings in the /etc/sysconfig/network-script/ifcfg-eth0:
    Restart networking for these changes to take effect.
  9. At this point, you can start the aiccu service and test to see if it works. If it doesn't start properly, the next step discusses a couple of things to check. But how do you know if it works?
    a. Starting says OK:
    /etc/init.d/aiccu start
    If it doesn't say OK, then go look in /var/log/messages and read the next step.
    b. There is a process running named aiccu.
    c. There is a new virtual interface named "sixxs" and it has an ivp6 address:
    ifconfig sixxs sixxs Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 inet6 addr: 2001:1938:81:d2::2/64 Scope:Global inet6 addr: fe80::1838:81:d2:2/64 Scope:Link UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1280 Metric:1
    Note the new address with the 2001::/16 prefix. That is the new ipv6 address that has been automatically created on this new virtual interface by the aiccu tunnel client.
  10. At this point, the tunnel is up and running, and you should be able to ping6 and traceroute6 ipv6 hosts.
  11. The way that Sixxs works is using a virtual "credits" system. It costs credits to request things and change settings, you gain credits by successfully configuring the initial tunnel and for its stability (keeping the tunnel up for extended periods, two weeks is the initial requirement). When you request that first tunnel, you are only connection your tunnel host, you cannot hand out ip's from that /64 to other machines on the LAN because Sixxs will not route those, only the ip which gets assigned to your sixxs interface will be accepted.
  12. After you've had your tunnel up for a couple weeks, you will have earned enough credits to request a subnet. You will get assigned a /48, out of which you can use radvd to advertise a /64 to your LAN inside your house or office.
  13. The easiest thing to do is to statically assign the first IP from that subnet to your eth0. In this example I'll assume that you were assigned 2001:883:66::/48. Pick a single /64 from this (random, or 0, I'm using e0 here). In your /etc/sysconfig/network-scripts/ifcfg-eth0:
    Restart networking for it to take effect, and then restart the aiccu service.
  14. Test the connection by pinging some known good ipv6 site.
    ping6 www.mrball.net PING www.mrball.net(2001:5c0:8fff:fffe::7a55) 56 data bytes 64 bytes from 2001:5c0:8fff:fffe::7a55: icmp_seq=1 ttl=62 time=192 ms 64 bytes from 2001:5c0:8fff:fffe::7a55: icmp_seq=2 ttl=62 time=218 ms
  15. Configure radvd with the subnet information. This is the service which will advertise the ipv6 subnet to the rest of the ipv6 aware hosts on your LAN. In this example I'll again assume that you were assigned 2001:883:66::/48. Using the 201:883:66:e0::/64 from this, your /etc/radvd.conf looks like:
    interface eth0 { AdvSendAdvert on; prefix 2001:883:88:e0::/64 { AdvOnLink on; AdvAutonomous on; AdvRouterAddr on; }; };
    Start the radvd service
  16. Enable the service to start at boot.
    RedHat/CentOS and Mandriva:
    chkconfig radvd on # should be on by default, but just in case
  17. Turn off the service because currently it's not firewalled and anybody can ping/ssh to your machine, even if you're behind an ipv6 NAT gateway. Why? Because you're tunnelling to Sixxs and getting globally reachable IP addresses. The next step will take care of that.
    /etc/init.d/aiccu stop
  18. Make sure you have ipv6 iptables support, called ip6tables.
    yum install iptables-ipv6
    urpmi iptables-ipv6
  19. Set up a simple firewall for ipv6. For CentOS/RedHat and Mandriva the following will be in /etc/sysconfig/iptables:
    *filter :INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [0:0] :IPV6-INPUT - [0:0] [0:0] -A INPUT -j IPV6-INPUT [0:0] -A FORWARD -j IPV6-INPUT [0:0] -A IPV6-INPUT -i lo -j ACCEPT # [0:0] -A IPV6-INPUT -p ipv6-icmp -j ACCEPT [0:0] -A IPV6-INPUT -p esp -j ACCEPT [0:0] -A IPV6-INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT # The following line uses my internal LAN facing interface [0:0] -A IPV6-INPUT -i eth0 -m state --state NEW -j ACCEPT [0:0] -A IPV6-INPUT -j REJECT --reject-with icmp6-adm-prohibited COMMIT
    You can uncomment the line with ipv6-icmp if you choose. This line allows all ping6 and tracepath6/traceroute6 tests to work both inbound and outbound. If commented, ping6 and tracepath6/traceroute6 only work from the inside. PAY ATTENTION: People can ping your internal hosts from the outside with that line enabled. They can't ssh or browse to it, but they'll be able to ping it, so they will know things like when employees are at work (when not to try to break in to some machine or when they're not at home) and other social engineering type things like that.
    WARNING: IPv6 stateful filtering was broken until kernel 2.6.20. CentOS 5 uses 2.6.18, so the --state rules above won't work.
  20. Load the firewall with:
    /etc/init.d/ip6tables start
  21. Look at the firewall rules to make sure it loaded properly:
    # ip6tables --list -n Chain INPUT (policy ACCEPT) target prot opt source destination IPV6-INPUT all ::/0 ::/0 Chain FORWARD (policy ACCEPT) target prot opt source destination IPV6-INPUT all ::/0 ::/0 Chain OUTPUT (policy ACCEPT) target prot opt source destination Chain IPV6-INPUT (2 references) target prot opt source destination ACCEPT all ::/0 ::/0 ACCEPT icmpv6 ::/0 ::/0 ACCEPT esp ::/0 ::/0 ACCEPT all ::/0 ::/0 state RELATED,ESTABLISHED ACCEPT all ::/0 ::/0 state NEW REJECT all ::/0 ::/0 reject-with icmp6-adm-prohibited
  22. Now start the aiccu process back up:
    /etc/init.d/aiccu start
  23. Stateless autoconfiguration is the end goal of this whole procedure. The gist of stateless autoconfiguration is that the radvd process advertises a /64 network (the first 64 bits). The ipv6 enabled host will see this advertisement and the host generates the last 64 bits of the host address. Here's how to make sure that your host is ipv6 enabled.
    CentOS: If you didn't specifically disable ipv6 during the installation or at any time during the gui/ncurses configuration step, ipv6 should be enabled. Here's how to check:
    # in /etc/sysconfig/network NETWORKING_IPV6=yes # in /etc/sysconfig/network-scripts/ifcfg-eth0 (or whichever device needs to be ipv6 enabled) IPV6INIT=yes IPV6_AUTOCONF=yes # IPV6_PRIVACY="rfc3041"
    * For me, privacy extensions didn't work properly, but that may be because the machine I was testing it on was a wifi card so init scripts didn't quite work.
    Mandriva: If you didn't specifically disable ipv6 during any part of the gui/ncurses configuration step, ipv6 should be enabled.
  24. Go look at any host that has ipv6 and ipv6 autoconfiguration enabled and look to see if it has created the new address:
    ~$ /sbin/ifconfig eth0 eth0 Link encap:Ethernet HWaddr 00:1D:09:76:F5:58 inet addr: Bcast: Mask: inet6 addr: 2001:883:88:e0:21d:9ff:fe76:f558/64 Scope:Global inet6 addr: fe80::21d:9ff:fe76:f558/64 Scope:Link
    Again, this is stateless autoconfiguration at work. Your server is advertising 2001:883:88:e0::/64 as a valid network, but where did the second 64 bits of address come from? (the 21d:9ff:fe76:f558 portion). It is automatically generated using what's called EUI-64. It's based upon your 48 bit MAC address. Look at the MAC above and compare to the last 64 bits of the ipv6 address you'll see that it is very similar. The exact generation formula is described in Appendix A of RFC 4291.
  25. Test to see if you can ping6 www.kame.net or some other known ipv6 site. It should all be working now.
    ping6 www.mrball.net PING www.mrball.net(2001:5c0:8fff:fffe::7a55) 56 data bytes 64 bytes from 2001:5c0:8fff:fffe::7a55: icmp_seq=1 ttl=62 time=192 ms 64 bytes from 2001:5c0:8fff:fffe::7a55: icmp_seq=2 ttl=62 time=218 ms
  26. Add a little bit of resiliency by making a quick cronjob that will test if the daemon is still running and restart it if it is not. Like any service which is tunnelled, occassional disconnects happen and this is a simple way of correcting it. I achieve this using this:
    ~$ crontab -l -u root | grep aiccu 0 * * * * /sbin/pidof aiccu >/dev/null || /etc/init.d/aiccu restart
  27. Test from somewhere outside and make sure that your hosts are not reachable from the outside (several webbased ipv6 testers are available if you google for it). Note that if you allowed icmpv6 in the firewall by uncommenting that icmpv6 line, you'll be able to ping the host, but you won't be able to connect to anything via tcp or udp. If you specifically blocked icmpv6 by leaving that line commented, then you won't be able to ping the host either. In this example, I allowed ping:
    ping6 2001:883:88:e0:21d:9ff:fe76:f558 PING 2001:883:88:e0:21d:9ff:fe76:f558(2001:883:88:e0:21d:9ff:fe76:f558) 56 data bytes 64 bytes from 2001:883:88:e0:21d:9ff:fe76:f558: icmp_seq=1 ttl=62 time=188 ms 64 bytes from 2001:883:88:e0:21d:9ff:fe76:f558: icmp_seq=2 ttl=62 time=186 ms --- 2001:883:88:e0:21d:9ff:fe76:f558 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 999ms rtt min/avg/max/mdev = 186.161/187.506/188.852/1.413 ms # And on my system I run a webserver, can I connect to it? telnet 2001:883:88:e0:21d:9ff:fe76:f558 80 Trying 2001:883:88:e0:21d:9ff:fe76:f558... telnet: Unable to connect to remote host: Permission denied
  28. RFC's are technical documents that pertain to implementing things on computers. The are several ipv6 specific RFC's, the ones of particular interest are: Also interesting is 4193 if you choose to implement a local subnet that you manually create, do dns for, and maintain (it can still generate automatically the second 64 bits of space, same as is done here.) There is a webbased form that will do the autogeneration of your own unique local subnet that is supposed to be globally unique, but since it's not a routable prefix, it is relatively safe (think 192.168.*.* or 10.*.*.* in the ipv4 world but without NAT capability, you'd use your globally unique public routable IP instead and rely on the firewall to keep anything you don't want from penetrating to your box).
  29. I try to keep up with everything that's happening in the ipv6 world. See what things I have been reading when it comes to ipv6 on my Del.icio.us bookmark page.

Todd A. Lyons
Rev 0 - 2/4/2010