Dynamically-Routed IPv6 With Multiple Subnets Using tinc and Quagga

Michael Adams, 2-22-2010

Introduction

With the advent of Windows 7, advanced IPv6 support in Linux and OSX, and the exhaustion of IPv4 addresses, it becomes a matter of urgency to transition to IPv6 networking. This document is a successor to one I wrote back in 2007 that demonstrated static networking of a single subnet.

Platforms and software for this reference

1. tinc: a mesh-capapble VPN software created in the 2000s. This example should work with any 1.0.x version or later.
2. Quagga: an open-source routing software. Version 0.98 or later is required: version 0.99.x highly suggested!
3. Low-capacity sites may successfully use routers reprogrammed with OpenWRT: Kamikaze 8.09 works; 8.09.1 & .2 do not have Quagga 0.99.x available.
4. Higher-capacity or main node sites should use Debian or Ubuntu Linux: latest version of either preferred.

Getting your networks

For this setup, you will use have two networks: one internal and one to access Internet with.
Internal network: read up on unique local addressing, then generate a ULA range using SixXS or KAME.
External network:
obtain a /48 or /56 from your ISP, else sign up for tunnel access with Hurricane Electric or SixXS.

Table of abbreviations

PASSWORD Any password suitable for the config file in question.
LOCALNET Interface name that will host local subnets: usually "br-lan" on OpenWRT or "eth0" on Debian/Ubuntu.
GLOBAL First 3 parts of a globally-accessible IPv6 range, i.e. "2001:db8:beef".
ULA First 3 parts of an internally-routed IPv6 range.
SITENAME Name of the site being configured. In tinc, its also used to associate with hostname files.

System configuration

Using latest software versions (do after step 2 of either platform)

1. You can install updated versions of tinc that work for mips OpenWRT via http://0x1.net/openwrt/ . I have a blog entry on how to use it.
2. Updated Debian/Ubuntu packages for tinc & Quagga: use dpkg to install them and watch out for dependencies.

OpenWRT

1. Program the router and configure its local IPv4 setup as you need it via the web interface.
2. Use the following commands to prep the router...

opkg update
opkg install kmod-ipv6 kmod-ip6tables kmod-tun tinc ip ntpclient nano
opkg install quagga-unstable-ospf6d iptables-mod-extra kmod-sit
opkg remove luci-app-firewall firewall

3. Create /etc/init.d/firewall & /etc/firewall.user and "chmod a+x" them.
4. Write the sysctl.conf, quagga files, and tinc files as needed.
5. Sign the local tinc host file with tincd -n link -K

Debian/Ubuntu

1. Configure the system as you need to.
2. apt-get install tinc quagga
3. Edit /etc/modules to add "tcp_illinois".
4. Write the sysctl.conf, quagga files, and tinc files as needed.
5. Sign the local tinc host file with tincd -n link -K

/etc/sysctl.conf

OpenWRT Debian/Ubuntu
kernel.panic=3
net.ipv4.conf.default.arp_ignore=1
net.ipv4.conf.all.arp_ignore=1
net.ipv4.ip_forward=1
net.ipv4.icmp_echo_ignore_broadcasts=1
net.ipv4.icmp_ignore_bogus_error_responses=1
net.ipv4.tcp_fin_timeout=30
net.ipv4.tcp_keepalive_time=120
net.ipv4.tcp_syncookies=0
net.ipv4.tcp_timestamps=1
net.ipv4.netfilter.ip_conntrack_tcp_timeout_established=3600
net.ipv4.netfilter.ip_conntrack_udp_timeout=60
net.ipv4.netfilter.ip_conntrack_udp_timeout_stream=180
net.core.rmem_max=524288
net.core.wmem_max=524288
net.ipv4.tcp_rfc1337=1
net.ipv4.route.flush=1
net.ipv4.tcp_window_scaling=1
net.ipv4.tcp_sack=1
net.ipv4.tcp_fack=1
net.ipv4.tcp_low_latency=1
net.ipv4.tcp_ecn=1
net.ipv6.conf.all.forwarding=1
net.ipv4.tcp_frto=2
net.ipv4.tcp_frto_response=2
net.ipv4.tcp_workaround_signed_windows=1
net.ipv4.tcp_mtu_probing=1
kernel.printk = 4 4 1 7
fs.inotify.max_user_watches = 524288
net.ipv6.conf.all.forwarding=1
net.ipv4.ip_forward=1
net.ipv4.icmp_echo_ignore_broadcasts = 0
net.ipv4.icmp_ignore_bogus_error_responses = 1
net.ipv4.conf.default.rp_filter=1
net.ipv4.conf.all.rp_filter=1
net.ipv4.tcp_syncookies=0
net.core.rmem_max=524288
net.core.wmem_max=524288
net.ipv4.tcp_rfc1337=1
net.ipv4.route.flush=1
net.ipv4.tcp_window_scaling=1
net.ipv4.tcp_sack=1
net.ipv4.tcp_fack=1
net.ipv4.tcp_timestamps=1
net.ipv4.tcp_low_latency=1
net.ipv4.tcp_ecn=1
net.ipv4.tcp_fin_timeout=10
net.ipv4.ip_no_pmtu_disc=0
net.ipv4.tcp_congestion_control=illinois
net.ipv4.tcp_frto=2
net.ipv4.tcp_frto_response=2
net.ipv4.tcp_workaround_signed_windows=1
net.ipv4.tcp_mtu_probing=1
net.core.somaxconn=5000
net.core.netdev_max_backlog=5000
net.ipv4.conf.default.rp_filter=1
net.ipv4.tcp_mtu_probing=1
net.ipv4.tcp_tw_reuse=1
net.ipv4.tcp_tw_recycle=1

Quagga configs

For this to work, we will be using OSPFv3. OSPF routers use decimal notation for its purposes, but IPv6 addresses are hexadecimal, so you can either choose to use the same number (delinated as "#") for both, or you can use the hexidecimal number of # for the IPv6 ranges (example: 0.0.0.11 would represent 2001:db8:beef:b::/64).

/etc/quagga/daemons (Debian/Ubuntu systems)

zebra=yes
bgpd=no
ospfd=no
ospf6d=yes
ripd=no
ripngd=no
isisd=no

/etc/quagga/ospf6d.conf

password PASSWORD
!
!adapter setup
!
interface LOCALNET
interface vpn6
!
!router setup
!
router ospf6
router-id 0.0.0.#
redistribute static
redistribute connected
area 0.0.0.# range GLOBAL:#::/64
area 0.0.0.# range ULA:#::/64
interface LOCALNET area 0.0.0.#
interface vpn6 area 0.0.0.0

/etc/quagga/zebra.conf

hostname SITENAME
password PASSWORD
interface LOCALNET
link-detect
no ipv6 nd suppress-ra
ipv6 nd ra-interval 10
ipv6 address GLOBAL:#::ffff/64
ipv6 address ULA:#::ffff/64
ipv6 nd prefix GLOBAL:#::/64
ipv6 nd prefix ULA:#::/64
interface vpn6
link-detect
ipv6 address ULA::#/64
ipv6 address GLOBAL::#/64
interface lo
link-detect
ipv6 forwarding
ipv6 route ULA:#::/64 LOCALNET
ipv6 route GLOBAL:#::/64 LOCALNET

tinc configs

On the "master" node, it must have a copy of the hostfile from each of the other nodes, plus its own. The nodes only require the master + their own.

/etc/tinc/nets.boot

link

/etc/tinc/link/tinc.conf

Name=SITENAME
Device=/dev/net/tun
Mode=switch
Interface=vpn6
ConnectTo=master

/etc/tinc/link/tinc-up ("chmod a+x" this file)

#!/bin/sh
ip -6 link set vpn6 up mtu 1280
ifconfig vpn6 txqueuelen 10000

/etc/tinc/link/tinc-down ("chmod a+x" this file)

#!/bin/sh
ip -6 link set vpn6 down

/etc/tinc/link/hosts/master (change TCPOnly to "yes" if problems connecting)

Address=IP ADDRESS OF MASTER NODE
Port=655
Compression=10
TCPOnly=no

*tinc-generated SSL key*

/etc/tinc/link/hosts/SITENAME

Port=655
Compression=10

*tinc-generated SSL key*