Proper routing for HE Tunnelbroker on machines with native (and preferred) IPv6 on Gentoo (with `netifrc`)
On a machine with native IPv6 that's working quite well (e.g. CERNET2),
it's usually desirable to set the host's default IPv6 route to go through
native IPv6. Yet the cheap
/48 address block offered by HE Tunnelbroker
can be useful if one wishes to assign IPv6 addresses through VPN. This
article mainly serves as a memo for achieving the following goals:
- native IPv6 should work just fine (i.e.
- tunnelbroker's addresses should work as well (e.g. services that bind to the tunnelbroker's addresses should get correct routes)
For native IPv6, a
default route would normally look like this:
default via fe80::c256:27ff:fed2:90fd dev wlp3s0 proto static metric 600 pref medium
... which sets the router's link-local address (acquired via router advertisement) as the default gateway, thus defining route for all outgoing packets to go through the physical port.
The problem is, the native IPv6 routers usually filter the packets based on src address ACL. As a result, the packets with the tunnelbroker's address as the src address usually get dropped instead of further routed, thus making the tunnel effectively useless.
Linux's iproute2 tool has the
ip-rule tool, which handles policy routing, and can solve the
problem. What we need is a new
default route for packets with src addresses that fall in
the prefix allocated from tunnelbroker. The following works like a charm:
ip -6 route add default dev he-ipv6 table 101 ip -6 rule add from 2001:470:f838::/48 lookup 101 priority 500
he-ipv6 and the prefix correspond to what you get from HE.
To get things fixed and automatically set up across reboots, we'll need to configure the network
manager to automatically add the RPDB rules as well as the extra routes in the special table
On Gentoo this is handled via
netifrc, whose configuration lies in
/etc/conf.d/net. Things should
look like this:
rules6_he_ipv6=" from 2001:470:f838::/48 lookup he priority 500 " routes_he_ipv6=" ::/0 dev he-ipv6 table he "
table he is defined in
/etc/iproute2/rt_tables as an alias of
table 101 so that we can get
clearer (thus better memorable) rules and routes. Note that
::/0 is used here as I can't find a way
to separate IPv4 and IPv6 routes here (!), and the simple
default will result in the route got added
into IPv4 routing table.
One more thing
One thing that bothered me for quite some time is somehow unrelated to routing itself, but worth noting
as failing to notice this will result in strange results. Make sure your IPv4 firewall permits
packets (a.k.a. protocol 41)! Like this:
iptables -A INPUT -p ipv6 -j ACCEPT
I used to have things like this:
iptables -P INPUT DROP iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT iptables -P OUTPUT ACCEPT
... which results in incoming packets won't reach the destination unless the host sends a packet first, thus triggering the connmark. Inbound connections fail after the tunnel turns inactive for a while, when the conntrack expires.