Dynamically-Routed IPv6 VPN With Multiple Subnets

Michael Adams, 2-22-2010, 11-27-2011, 4-22-2013 (current rev)

IPv6 example network layout

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. Babel: if you plan on using both IPv6 and IPv4 subnets (for security cameras, gate systems, and legacy industrial equipment).
3. Lower-capacity sites may successfully use routers reprogrammed with OpenWRT: use version 12.09 / Attitude Adjustment or later. This is also the easiest way to set this up.
4. Higher-capacity or main node sites should use Debian or Ubuntu Linux: latest version of either preferred.
5. IPFire 3.x (still in development as of 2013) appears to have support for IPv6, tinc, and Quagga. Babel support is less certain.
6. ClearOS as a platform works, but you'll need to hunt down the latest RPM files for RHEL or CentOS for tinc/Quagga/Babel; Fedora RPMs don't work with these variants.

Workstation-specific materials

Privacy Addressing

If you want to make it easier to administer Linux and Windows systems (as well as not clog up AD with a bunch of temporary addresses),  you can force your workstations to not use privacy addresses that are used for accessing external servers.

Windows: as an Administrator, run the following in command prompt...
netsh interface ipv6 set privacy state=disable

Linux: add the following to you /etc/sysctl.conf ...

net.ipv6.conf.all.use_tempaddr=0
net.ipv6.conf.default.use_tempaddr=0


Software

*. IPv6 workstation toolset : includes configuration batch files, copies of stone for 32-bit and x64 Windows, and a 3rd-party LPD for XP.
*. VNC viewer for IPv6: the original author's website went down in 2010; I have a copy of it.

Getting your networks

For this setup, you will use have two networks: one internal for your administrative needs; and one to access global Internet with.

* Internal network: read up on Unique Local Addressing, then generate a ULA range using UltraTools, SixXS, or KAME.
* External network: obtain a /48 or /56 from your main site's ISP, else sign up for tunnel access with Hurricane Electric or SixXS. If you can get a /64 for each of your sites, adjust the "GLOBAL /48" entries as if they were local.

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.
SUB
The octet of the local subnet, i.e. "a" in "2001:db8:beef:a::/64"
INT
Integer number

Configuration: System

OpenWRT

1. Login to the router with telnet (if no password was set yet) or SSH. Run the following commands...

opkg update
opkg install kmod-ipv6 kmod-ip6tables kmod-tun ip nano libreadline iptables-mod-extra kmod-sit
opkg install alive6 6tunnel tinc babeld quagga-libzebra quagga-zebra quagga-ospf6d
opkg install luci luci-sgi-uhttpd

/etc/init.d/uhttpd enable


1b. Optionally, you can add more packages for better router administration. Installing ip6tables will require firewall rules tweaking in the interface.

opkg install netstat-nat htop iftop snmpd ntpclient
opkg install ip6tables


2. nano /etc/config/uhttpd : remove comments on the [::] lines.
3. Using the web interface, add an exception for port 655 TCP+UDP to the firewall. Verify the IPv4 and other router settings are accurate for the site.
4. Write the sysctl.conf, and the quagga/tinc/babel configurations as needed (other half of this article). I assume you're using nano for this.
5. Sign the local tinc host file with tincd -n link -K
6. Add the following to /etc/rc.local as needed...

tincd -n link
/etc/init.d/quagga restart
killall -9 babeld
rm /var/run/babeld.pid
babeld -c /etc/babeld.conf -D

Debian/Ubuntu

1. Use an appropriate reference to turn said box into a router (if you haven't already): try to use a newer one.
2. iptables firewall rules to add

-A INPUT -p tcp -m multiport -j ACCEPT --dports 655
-A INPUT -p udp -m multiport -j ACCEPT --dports 655

2b. If you're using a firewalling script/software, add TCP+UDP port 655 to its config as "allowed".
3. apt-get update && apt-get install tinc quagga babeld
4. Write the sysctl.conf, and the quagga/tinc/babel configurations as needed (other half of this article). I assume you're using nano for this.
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.ipv6.conf.all.forwarding=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.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=0
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.netfilter.nf_conntrack_checksum=0
net.netfilter.nf_conntrack_max=16384
net.netfilter.nf_conntrack_tcp_timeout_established=3600
net.netfilter.nf_conntrack_udp_timeout=60
net.netfilter.nf_conntrack_udp_timeout_stream=180
net.netfilter.nf_conntrack_checksum=0
net.netfilter.nf_conntrack_max=16384
net.bridge.bridge-nf-call-arptables=0
net.bridge.bridge-nf-call-ip6tables=0
net.bridge.bridge-nf-call-iptables=0
vm.min_free_kbytes=1024

net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1
net.ipv4.conf.default.rp_filter = 0
net.ipv4.conf.default.accept_source_route = 0
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_rfc1337=1
net.ipv4.tcp_window_scaling=1
net.ipv4.tcp_sack=1
net.ipv4.tcp_fack=1
net.ipv4.ip_no_pmtu_disc=0
net.ipv4.tcp_congestion_control=yeah
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.ipv4.tcp_low_latency=0
net.core.bpf_jit_enable=1
net.ipv4.tcp_limit_output_bytes=65536
net.ipv6.conf.all.use_tempaddr=0
net.ipv6.conf.default.use_tempaddr=0

Configuration: tinc

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. As for the hostfile, older versions of tinc support a "TCPOnly" flag, and all versions support a compression flag (0 none,1-9 gzip,10-11 zlib).

/etc/tinc/nets.boot

/etc/tinc/link/tinc.conf

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

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

/etc/tinc/link/hosts/master

/etc/tinc/link/hosts/SITENAME
link Name=SITENAME
Device=/dev/net/tun
Mode=switch
Interface=vpn6
ConnectTo=master
#!/bin/sh
ip -6 link set vpn6 up mtu 1280
ip link set vpn6 qlen 4096
#!/bin/sh
ip -6 link set vpn6 down
Address=IP ADDRESS OF MASTER NODE
Port=655
Compression=4

*tinc-generated SSL key*
Port=655

*tinc-generated SSL key*

Configuration : Babel

As of April 2013, the Quagga module for Babel remains difficult to use for this project. As documentation improves, that can be pursued. This documentation is for the original Babeld server.

The Babel protocol will allow you to route both IPv4 and IPv6 subnets over your tinc VPN. It may also work better than OSPFv3: your mileage may vary.

* On Debian/Ubuntu systems, edit /etc/default/babeld with the local network interface. Debian/Ubuntu boxes can restart Babel with service babeld restart .
* On OpenWRT routers, add the /etc/restart-babel.sh script. Use the script to restart Babel if needed.
* There are two interface settings for Babel: "wired" and "split-horizon". It tries to detect the appropriate setting automatically, but I find that forcing "wired false" on the tinc interface, better accommodates its nebulous mesh-nature.
* Babel routing relies on specific firewall-style rules to include/exclude networks. You'll need to experiment to find what works for you: an IPv6-only VPN won't require IPv4 filtering rules; an IPv4 route that conflicts with the gateway, will cut the device off.

/etc/babeld.conf
/etc/restart-babel.sh (chmod a+x)
interface vpn6 wired false split-horizon true
interface lo split-horizon true wired true
in ip CRITICAL_IPV4_SUBNET eq 16 deny
redistribute ip LOCAL_IPV4_SUBNET/24 eq 24 metric 128
redistribute ip ULA:SUB::/64 eq 64 metric 128
redistribute ip GLOBAL:SUB::/64 eq 64 metric 128
redistribute local deny
#!/bin/sh
killall -9 babeld
rm /var/run/babeld.pid
babeld -c /etc/babeld.conf -D

Configuration: Quagga

Babel users will need the basic routing setup from this; they can skip OSPFv3 (ospf6d) configuration. There is also a Babel module for Quagga, but its still being developed and documented.

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 "SUB") for both, or you can use the hexidecimal number of SUB for the IPv6 ranges (example: 0.0.0.11 would represent 2001:db8:beef:b::/64).

* Debian/Ubuntu users will need to edit the /etc/quagga/daemons file.
* If you're using DHCPv6 for DNS (via Dibbler or ISC DHCP 4.x), you can add ipv6 nd other-config-flag as a command to /etc/quagga/zebra.conf (after the "suppress ra" command). An example setup for DHCPv6 is at the end of this document.

/etc/quagga/daemons

/etc/quagga/ospf6d.conf /etc/quagga/zebra.conf
zebra=yes
bgpd=no
ospfd=no
ospf6d=yes
ripd=no
ripngd=no
isisd=no
babeld=n
password PASSWORD
!
!adapter setup
!
interface LOCALNET
interface vpn6
!
!router setup
!
router ospf6
router-id 0.0.0.INT
redistribute static
redistribute connected
area 0.0.0.INT range GLOBAL:SUB::/64
area 0.0.0.INT range ULA:SUB::/64
interface LOCALNET area 0.0.0.SUB
interface vpn6 area 0.0.0.0
hostname SITENAME
password PASSWORD
ipv6 forwarding
!
interface LOCALNET
 link-detect
 no ipv6 nd suppress-ra
 ipv6 nd ra-interval 10
 ipv6 nd prefix GLOBAL:SUB::/64
 ipv6 nd prefix ULA:SUB::/64
 ipv6 route GLOBAL:SUB::/64 LOCALNET
 ipv6 route ULA:SUB::/64 LOCALNET
 ipv6 address GLOBAL:SUB::ffff/64
 ipv6 address ULA:SUB::ffff/64
!
interface vpn6
 link-detect
 ipv6 address ULA::SUB/64
 ipv6 address GLOBAL::SUB/64
!
interface lo
 link-detect

Configuration: DHCPv6

This document supposes the use of Stateless Autoconfiguration to support IPv6. However, for DNS address distribution, DHCPv6 is still needed. If you have ISC DHCP version 4 or later installed, you can define a separate IPv6 configuration for DNS assignment.

Debian/Ubuntu: add to /etc/rc.local
/etc/dhcpd6.conf
/etc/reset-dhcp.sh (chmod a+x)
/usr/bin/touch /var/lib/dhcp/dhcpd6.leases
/usr/sbin/dhcpd -6 -lf /var/lib/dhcp/dhcpd6.leases -cf /etc/dhcpd6.conf LOCALNET
option dhcp6.domain-search "DOMAIN";
option dhcp6.name-servers SERVER1, SERVER2;
default-lease-time 3600;
max-lease-time 7200;
authoritative;
log-facility local7;

#subnet6 ULA::/64{
#allow unknown-clients;
#}

subnet6 GLOBAL::/64{
allow unknown-clients;
}
#!/bin/sh
/usr/sbin/service isc-dhcp-server stop
/usr/bin/killall -9 dhcpd
/usr/sbin/service isc-dhcp-server start
/usr/bin/touch /var/lib/dhcp/dhcpd6.leases
/usr/sbin/dhcpd -6 -lf /var/lib/dhcp/dhcpd6.leases -cf /etc/dhcpd6.conf LOCALNET

Return to unquietwiki.com

This page uses the Metro UI CSS