Thursday, August 3, 2017

Policy Based IPv6 Routing on LEDE

My home router runs LEDE 17.01. It has two IPv6 connections, an ISATAP tunnel and TunnelBroker. The ISATAP connection has shorter latency than the TunnelBroker. However, ISATAP only allows one IPv4 address to have one IPv6 address. In order to let my home computers have IPv6 connections, I have two choices. The first is to use NAT on IPv6 so that hosts behind the router appears as one hosts on the IPv6 Internet. The second choice is to assign home computers addresses allocated on TunnelBroker and route all their traffic through TunnelBroker. And installing a SOCKS/HTTP proxy on the router, so a host can enjoy the low latency ISATAP link via the proxy.

So, I configured the router to have the following IPv6 routing table

default from 2001:xxxxx::/64 dev 6in4-henet proto static metric 16 pref medium
default from 2001:xxxxx::/64 dev 6in4-henet proto static metric 16 pref medium
2000::/3 via 2001:da8:xxxx dev isatap src 2001:da8:xxxx metric 2 pref medium

As a result, the router will opt for the ISATAP link over the TunnelBroker link. However, I found that although hosts behind the router can get IPv6 addresses, they cannot connect to any IPv6 hosts outside my home, because the router puts all IPv6 traffic whose destination matches 2000::/3 through the ISATAP link!

Later, I came up with a solution. Linux supports policy-based routing. So the router can have two IPv6 routing tables, namely the `main` and `henet` table. For IPv6 packets whose source addresses are within my TunnelBroker's block, the router should lookup the `henet` table, which contains

2001:xxxxx/64 dev br-lan
default from 2001:xxxxx::/64 dev 6in4-henet

I wrote a script to achieve this effect

ip -6 route flush table henet
ip -6 route add 2001:xxxx/64 dev br-lan metric 128 table henet
ip -6 route add default dev 6in4-henet metric 256 table henet
ip -6 rule add from 2001:xxxxx/64 table henet

You should also add `252 henet` to /etc/iproute2/rt_tables before invoking the above commands.