For reasons I don't care to defend, my internet connection looks something like this:
Since my firewall is connected to the hotspot via WiFi, bridging to my internal network is out of the question. While there are many tutorials and approaches to getting IPv6 into a topology that looks like this, none of them work for me for various reasons. eg: the hotspot will not delegate a prefix via dhcpv6
I really want IPv6 so ... let's see what we can do!
proxy_ndp
First of all, we need to fool the hotspot into thinking that the Linux WiFi link has a bunch of addresses that actually belong to other computers behind it. IPv6 uses neighbor discover protocol (ndp) and the linux kernel provides a feature called proxy_ndp. When enabled and configured, it does exactly what we want!
# enable proxy_ndp on the wireless link
sysctl -w net.ipv6.conf.wlan0.proxy_ndp=1
# tell the kernel to be discoverable for an IP it
# doesn't actually have
ip -6 neigh add proxy 2001:db8::100
radvd
# Find the current prefix for wlan0ip -6 route show dev wlan0(for illustration, maybe it shows 2001:db8::/64)# install/configure radvdapt install radvdvi /etc/radvd.confsystemctl start radvd
sample radvd.conf:
# eth0 is the internal network interface
interface eth0{AdvSendAdvert on;AdvDefaultPreference low;AdvHomeAgentFlag off;# Auto-configured prefix from wlan0prefix 2001:db8::/64{AdvOnLink on;AdvAutonomous on;AdvAutonomous on;};};
more-specific routes
# Add a specific route for 2001:db8::100 to the internal network
ip -6 route add 2001:db8::100 dev eth0
nftables
example /etc/nftables.conf:
define DEV_INTERNAL = eth0define DEV_INTERNET = wlan0define V6_PREFIX = { 2001:db8::/64 }
table inet filter {chain forward {type filter hook forward priority 0;policy drop;# stateless acceptance of all traffic to/from the
# internal network on the configured prefixip6 saddr $V6_PREFIX iifname $DEV_INTERNAL accept;ip6 daddr $V6_PREFIX oifname $DEV_INTERNAL accept;# these can help with debuggingip6 saddr $V6_PREFIX log prefix "filter-forward (s) " drop;ip6 daddr $V6_PREFIX log prefix "filter-forward (d) " drop;log prefix "inet-forward (dropped) ";}}
# Enable ipv6 forwarding for all interfacessysctl -w net.ipv6.conf.all.forwarding=1# reload firewall rulessystemctl restart nftables
Adding more nodes
At this point, only one node (2001:db8::/64) is online. It would be annoying to add each node manually, so we'll grab connection attempts and turn those into the requisite commands to run.
example nftables.conf:
define DEV_VETH veth0
table netdev v6traffic {chain ingress-internal {type filter hook ingress device $DEV_INTERNAL priority 0;ip6 saddr $V6_PREFIX tcp flags syn dup to $DEV_VETH;}}
example /etc/network/interfaces.d/veth0:
auto veth0iface veth0 inet manualpre-up ip link add veth0 type veth peer veth1pre-up ip link set veth1 uppre-down ip link del veth0 type veth peer veth1
example hackish script (ymmv):
#!/bin/shtcpdump --immediate-mode -i veth1 'ip6' -l 2> /dev/null | \awk -W interactive -F. '/IP6/ {sub(/.*IP6 /, "");print "ip -6 neigh add proxy " $1 " dev wlan0";print "ip -6 route add " $1 " dev eth0";}' | sh -v