IPv6 router with 6to4 and pf
This page is about IPv6 enabling an existing pf gateway. I will show the changes I have done to the setup to v6 enable the firewall and the network behind it. The current setup has worked fine for a while, and I decided to v6-enable the network mostly for the learning experience.
The firewall in question is one in a pair of redundant pf/pfsync/carp firewalls, but I will leave out the redundancy stuff to keep this article about IPv6 and not confuse things. I will be assigning IPv6 addresses to the carp interfaces rather than to the physical interfaces though.
The disadvantages with 6to4 are:
- No promises of uptime and stability
- There appears to be routing issues with 6to4 in some places/some providers, which (among other things) means that I can't see the dancing turtle on the KAME website because the connection falls back to v4.
- There are several security issues with 6to4 since it is an open-ended tunneling method. In practice this means that even though you send all your traffic to the non-6to4 part of the IPv6 internet to the anycast gateway at 18.104.22.168, reply traffic can come from the normal v4 address of the anycast server instead of 22.214.171.124. Also, IPv6 traffic from other 6to4 networks will come directly from the IPv4 address of the 6to4 network, and not from the anycast server. These two facts effectively prevent any filtering of the encapsulated traffic.
The advantages are:
- No registration is required, and it is free like the tunnel providers.
- I only need a public (preferrably static) IP address.
- I get automatic gateway failover since 6to4 uses an anycast gateway.
If you are located close (bgp-wise) to an anycast 6to4 gateway, and you are ok with the security issues, 6to4 is worth considering. You can check your pingtimes and route to your "local" 6to4 tunnel server by pinging or tracerouting the IP 126.96.36.199:
[tykling@fw2 ~]$ ping 188.8.131.52 PING 184.108.40.206 (220.127.116.11): 56 data bytes 64 bytes from 18.104.22.168: icmp_seq=0 ttl=254 time=1.801 ms 64 bytes from 22.214.171.124: icmp_seq=1 ttl=254 time=1.751 ms 64 bytes from 126.96.36.199: icmp_seq=2 ttl=254 time=1.825 ms ^C --- 188.8.131.52 ping statistics --- 3 packets transmitted, 3 packets received, 0.0% packet loss round-trip min/avg/max/stddev = 1.751/1.792/1.825/0.031 ms [tykling@fw2 ~]$
If your pingtimes are relatively low, like under 50ms, you should be able to get decent v6 connectivity using 6to4. The main selling point for 6to4 is how easy it is to configure. The main problem is security (spoofed IPv6 packets), but since I am playing around and not running a bank here I will take my chances.
Getting the firewall IPv6 connected
The first step is getting the firewall connected with a tunnel to the 6to4 tunnel server. I added the following lines to /etc/rc.conf and rebooted the firewall. The steps to apply the same settings without rebooting are included below:
#ipv6 6to4 stuff ipv6_enable="YES" stf_interface_ipv4addr="184.108.40.206" ipv6_defaultrouter="2002:c058:6301::"
Line-by-line, the first option enables IPv6 and sets the sysctl values needed for basic operation. The next line enables the stf tunneling device, which takes care of encapsulating IPv6 packets in IPv4 and sending them off to the default gateway, specified in the third line. Due to the anycast address, the ipv6_defaultrouter will always be 2002:c058:6301::, which translates to the v4 address 220.127.116.11.
To enable this configuration without rebooting, I need to manually calculate my 6to4 prefix from my public IP address. It is pretty simple, I just stick the hex form of the public v4 address on the end of the 6to4 prefix 2002:: and that is it. In this case, the v4 address is 18.104.22.168, the individual octets of the IP converted to hex are 59 e9 2b 42, so the 6to4 IPv6 prefix for 22.214.171.124 is 2002:59e9:2b42::/48. First I create the stf0 interface, then I give it an address in the prefix, then I add the default inet6 gateway. Note that I need to specify the prefix length for the stf0 interface as /16 as I want this to be an IPv6 gateway (eventually), according to this bit from the stf man page:
If you would like the node to behave as a relay router, the prefix length for the IPv6 interface address needs to be 16 so that the node would con- sider any 6to4 destination as ``on-link''.
So, on to the commands:
[tykling@fw2 ~]$ sudo ifconfig stf0 create up [tykling@fw2 ~]$ sudo ifconfig stf0 inet6 2002:59e9:2b42::1 prefixlen 16 [tykling@fw2 ~]$ ifconfig stf0 stf0: flags=1<UP> metric 0 mtu 1280 inet6 2002:59e9:2b42::1 prefixlen 16 [tykling@fw2 ~]$ sudo route add -inet6 default 2002:c058:6301:: add net default: gateway 2002:c058:6301:: [tykling@fw2 ~]$ sudo sysctl net.inet6.ip6.accept_rtadv=1 net.inet6.ip6.accept_rtadv: 0 -> 1 [tykling@fw2 ~]$ sudo sysctl net.inet6.ip6.auto_linklocal=1 net.inet6.ip6.auto_linklocal: 0 -> 1 [tykling@fw2 ~]$
The stf interface is up and running. I need to add a few things to pf.conf to allow:
- Traffic from 2002:c058:6301:: needs to be out on stf0
- IPv4 traffic using protocol 41 needs to and from all destinations. The nature of 6to4 and anycast prevents any filtering here, this is the main security concern with IPv6.
I added the following lines to the existing pf.conf:
[tykling@fw1 ~]$ grep -E "(stf|proto 41)" /etc/pf.conf stf_if="stf0" stf_prefix="2002:59e9:2b42::" pass out quick on ext_phys_if proto 41 from $carp_gateway_address to any pass in quick on ext_phys_if proto 41 from any to $carp_gateway_address pass out on $stf_if inet6 from $stf_prefix to any
After reloading pf.conf I tested basic IPv6 connectivity:
[tykling@fw1 ~]$ ping6 ipv6.google.com PING6(56=40+8+8 bytes) 2002:59e9:2b42::1 --> 2001:4860:a005::68 16 bytes from 2001:4860:a005::68, icmp_seq=0 hlim=54 time=33.483 ms 16 bytes from 2001:4860:a005::68, icmp_seq=1 hlim=54 time=33.621 ms 16 bytes from 2001:4860:a005::68, icmp_seq=2 hlim=54 time=33.445 ms ^C --- ipv6.l.google.com ping6 statistics --- 3 packets transmitted, 3 packets received, 0.0% packet loss round-trip min/avg/max/std-dev = 33.445/33.516/33.621/0.076 ms
So far so good. The next step is changing the setup to get auto configuration working for the network behind the firewall, and route IPv6 traffic to and from the network.
Configuring the firewall to route IPv6 traffic
First things first: For the firewall to be able to speak to the network using IPv6 it needs to have an IP address on the inside interface.
Assigning IPv6 addresses from the 6to4 prefix
I choose a /64 subnet for the inside and the outside interfaces and then assign the firewall an IP within them:
[tykling@fw1 ~]$ grep ipv6_ifco /etc/rc.conf ipv6_ifconfig_carp0="2002:59e9:2b42:0:1::/64" ipv6_ifconfig_carp1="2002:59e9:2b42:1:1::/64"
Note: The outside interface is carp1 and the inside interface is carp0. Given this, the subnet that the network behind this firewall will be using is 2002:59e9:2b42:1:1::/64.
Enabling rtadvd for stateless autoconfiguration
I also enable rtadvd in rc.conf, and specify the interface I want to advertise the prefix on. rtadvd is the FreeBSD routing advertisement deamon. It works out of the box with no configuration other than telling it which interface to use.
Enabling rtadvd will enable the network behind this firewall to use stateless auto configuration, which basically means that the firewall will periodically broadcast router advertisements using ICMPv6. Clients can also request a router advertisement by using their auto configured link-local IPv6 address. The firewall will respond with a router advertisement, which contains the prefix in use on the network. The clients will then stick their mac/hardware address in something called modified EUI-64 format on the end of the prefix, to generate a valid globally unique IPv6 address. I add the following to /etc/rc.conf:
[tykling@fw1 ~]$ grep rtadvd /etc/rc.conf rtadvd_enable="YES" rtadvd_interfaces="carp1"
I reboot the firewall again (to avoid rebooting, set the IP addresses on the interfaces and then start rtadvd manually), and I can see with tcpdump that rtadvd is doing its job of transmitting router advertisements to the network:
... to be continued...