Implementing IPv6 6to4 on OpenWRT

As the IPv4 addresses begins to run out I finally invested the time to investigate and implement IPV6. As my ISP has not yet announced availability of IPV6 addresses I chose to implement a 6to4 tunnel. This is simple to implement, and currently well supported. My external firewall is an ASUS wireless router running OpenWRT.  As I have a static IP address, my implementation is simpler than is required by a dynamic address.  Support for dynamic IPv4 addresses is not covered here, but this configuration should work as long as your address does not change.

I initially created a 6to4 implementation without a firewall.  Then to secure my systems I implemented a firewall using Shorewall6-lite.  Until I figured out how to configure the 6tunnel script, I used the command line to bring up the network.  This documentation uses of the 6tunnel script instead of the manual commands.  My configuration does not yet include any IPsec functionality.

Preparation

A 6to4 tunnel creates a /48 subnet under 2002:: using the external interface address encoded in hexadecimal.  This subnet is required to configure the tunnel.  Your 6to4 IPv6 prefix can be generated with the following printf command.  (Replace 192.0.2.0 with your external IP address.)  Use your IPv6 prefix and IPv4 address when configuring your tunnel.

printf '2002:%02x%02x:%02x%02x:\n" `echo 192.0.2.0 | tr . ' '`

My existing Shorewall firewall disabled IPv6.  I modified the shorewall.conf file to no longer disable IPv6.  A tunnels configuration file to enable 6to4 to connect using protocol 41 as added.  The tunnel definition used is:

6to4                    net

On the router opkg was used toinstall the required packages. These are the packages are:

  • kmod-sit to enable the 6to4 tunnel
  • 6scripts to automate setup of the tunnel
  • radvd to enable IPv6 client auto-configuration
  • shorewall6-lite to configure the firewall (requires shorewall6 on another server)

6to4 Implementation

To start off I implemented a 6to4 tunnel from the command line. This is complicated and prone to error.  The configuration of 6tunnel to build the tunnel is described here. Configuration of the tunnel is done with the file /etc/config/6tunnel.  This file contains the parameters for a 6to4 tunnel.  The options localip4, localip6, and delegatedip6 need to be configured based on your IP address and IPv6 subnet.   Replace the example values 192.0.2.0 and  2002:c000:0200:1234/64 with your values.  You can  replace the 1234 subnet specification with any 4 hex digits.

config 6tunnel
    option tnlifname        'tun6to4'
    option localip4         '192.0.2.10'
    option remoteip4        'any'
    option localip6         '2002:c000:0200::1/16'
    option remoteip6        '::192.88.99.1'
    option delegatedip6     '2002:c000:0200:1234::1/64'

    # Standard values
    option mtu              '1480'
    option ttl              '64'

Test your configuration using the following commands.  These will start the tunnel, run a ping test, and shut it down again.  If the ping is working, you have IPv6 access to the Internet.

/etc/init.d/6tunnel start
ping6 -c 4 ipv6.google.com
/etc/init.d/6tunnel stop

You may need to change your ip6table policies.  The following rules with allow open IPv6 access without firewalling.

ip6tables -P INPUT ACCEPT
ip6tables -P FORWARD ACCEPT
ip6tables -P OUTPUT ACCEPT
ip6tables -L

Once you have this everything working you can permanently enable the tunnel with.  This does not include a firewall, so you may have open IPv6 access from the Internet.  The Shorewall-lite configuration below should close down access.

/etc/init.d/6tunnel enable
/etc/init.d/6tunnel start

Stop the tunnel or close the firewall if you aren’t able to finish the next steps.  Restart the tunnel as required for testing radvd and Shorewall-lite.

Using radvd to configure clients

The radvd (router advertisement daemon) program broadcasts the data required for a client to configure itself with a global address.  It should be run on each router you have in your IPv6 network.  You will need to configure routes to subnets served by a router manually.  Routes between routers should be configured automatically.   This is a sample configuration for the network created above.  (Update the prefix accordingly. )

config interface
    option interface        'lan'
    option AdvSendAdvert    1
    option MinRtrAdvInterval 180
    option MaxRtrAdvInterval 560
    option ignore           0

config prefix
    option interface        'lan'
    # If not specified, a non-link-local prefix of the interface is used
    option prefix           '2002:c000:0200:1234::/64'
    option AdvOnLink        1
    option AdvAutonomous    1
    option AdvRouterAddr    0
    option ignore           0

config rdnss
    option interface        'lan'
    # If not specified, the link-local address of the interface is used
    option addr             ''
    option ignore           1

This will be used to generate the /tmp/etc/radvd.conf file and start the daemon.  The resulting radvd.conf file will look something like this:

interface br0
{
    MaxRtrAdvInterval 560;
    MinRtrAdvInterval 180;
    IgnoreIfMissing on;
    AdvSendAdvert on;

    prefix 2002:c000:0200:1234::/64
    {
        AdvOnLink on;
        AdvAutonomous on;
        AdvRouterAddr off;
    };
};

The supported options can be found by examining the file /etc/init.d/radvd.   This is the file which will be used to start and stop the radvd daemon process.  Start and enable the service with the commands.

/etc/init.d/radvd enable
/etc/init.d/radvd start

If your radvd configuration is correct, any IPv6 compatible clients of the router will get global IPv6 addresses in the specified subnet.  You can test their ability to connect by pinging ipv6.google.com.  On Linux use the ping6 command instead of ping.  The windows ping command supports IPv6.

Firewalling with Shorewall6-lite

You will need a server capable of running Shorewall to build the firewall.   It helps if the account you use has been configured to use an authorized key for ssh login to your router.  I use ssh-agent to load the key into memory.

On the server you are building the rules create a directory from which to build the firewall.  I use an Ubuntu system, and the copies specified here are based on its directories.  As a target I am using /etc/shorewall/openwrt.

mkdir /etc/shorewall/openwrt
cd /etc/shorewall/openwrt
cp /usr/share/doc/shorewall6/examples/two-interfaces/* .
cp /usr/share/shorewall6/Makefile-lite Makefile

Review the files and make the following changes:

  • replace eth0 with tun6to4 in interfaces.
  • replace eth1 with br0 (or an appropriate device if you are not bridging wifi and local connections) in  interfaces and routestopped.
  • replace /etc/shorewall6 with /etc/shorewall6/openwrt or /etc/shorewall6/common in shorewall6.conf.
  • update the HOST = line in Makefile to refer to your router.
  • change LITEDIR to /etc/shorewall6-lite/state in Makefile.

This should give you a basic file allowing open access outward from your network, and access to the router using ssh from the local network. Further documentation can be found in the Shorewall documentation.

The Makefile script to get the capabilities of your router will not work as configured. Edit /usr/share/shorewall6-lite/configpath and add a line reading “PATH=$PATH:/sbin:/usr/sbin“.  This will provide the required path.

Run make from your configuration directory (/etc/shorewall/openwrt).  Examine the output and correct any errors.  When you are confident your firewall is being build correctly you can install your changes with the command make install.  Verify you can connect to your router using ssh over IPv6. Try ssh root@2002:c000:0200::1. (Use your router’s IPv6 address.)  You can also re-verify that you have IPv6 access to the network. If this all works your firewall should be working. The shorewall6-lite show command will display your firewall along with traffic counters for the various rules.