Observations on tethering IPv6
Posted: Fri Feb 25, 2022 3:41 pm
The information here is from my own research and experiments. If you know better, please do share.
The standard way to classify hotspot/tether traffic on mobile networks is through the the APN settings. Android phones will set this through a hidden dun APN entry, while modems will only have metered dun APN by default. Bypassing this is always the first step.
The standard TTL for traffic exiting the device is 64, you add 1 for each hop after that. An example you might use on an Android phone:
This command sets the TTL for all traffic from USB that is not destined for the phone. An example for a phone tethered to a router:
This command sets the TTL for all traffic exiting through the USB interface. These two commands work because your phone and router are using NAT Masquerading. If you were to bridge your phone to lan, you'd need to use a command like this:
Unlike the previous two, this command loads the physdev module so the rule can apply to bridged traffic.
And here's a rule commonly shared here for IPv6:
But you must be running NAT6 for this rule to work. That's something not at all standard and must be set up manually. To check if your using NAT6, run 'ip6tables-save' and scroll to the '*nat' table.
If you don't see a rule like this, your not using NAT6.
Adding NAT6 support to your router will allow this rule to work, but it is worth considering that it is very likely your carrier can see each IPv6 device connected. With this setup, your carrier would see two devices, your phone and router. The public IP for devices behind the router will be the same, but that IP will be different than the one for your phone. The physdev rule from before:
Seems to just drop traffic, afaict. Maybe it's unimplemented.
The obvious solution is to just give up and live with an IPv4 only network, but if you want IPv6 connectivity, the easiest way is using a VPN. You'd bypass the dun and set the protocol to IPv4(or block/disable IPv6). Then on the router you override the TTL, set usb0 to wan, and setup the VPN to serve the network. Many VPNs can act as a 4to6 translation layer, granting your network IPv6 connectivity.
I ultimately just built the kernel modules for NAT6 and TTL modification for my phone so I could do a router(phone) -> wireless switch type setup. It's the best I've been able to come up with, but it requires an unlocked bootloader and is too technical for most.
Added notes:
-I see some people using ping to test if their firewall rules work. This is not ideal, as it is trivial to modify the TTL of ICMP6 packets and still leak IPv6. The best way to test your rules is to daisy chain two routers. You apply the rules on the second router and sit downstream behind the first, dumping traffic to check if your rules work.
-The DHCP6 services on routers are configured to relay standard IPv6 connections. Setting up VPNs or NAT6 usually requires that you change this behavior to serve a local network instead, similar to how IPv4 is handled. This is something that is not at all obvious and well hidden even when it's possible. The setting for this is in OpenWRT 21.02 is:
Network -> Interfaces -> LAN -> Advanced Settings -> IPv6 assignment length: Disabled
This setting will unlock 'IPv6 address' and 'IPv6 gateway' under 'General Settings', allowing you to set your own local IP and prefix.
The standard way to classify hotspot/tether traffic on mobile networks is through the the APN settings. Android phones will set this through a hidden dun APN entry, while modems will only have metered dun APN by default. Bypassing this is always the first step.
The standard TTL for traffic exiting the device is 64, you add 1 for each hop after that. An example you might use on an Android phone:
Code: Select all
iptables -t mangle -I FORWARD -i rndis0 -j TTL --ttl-set 64
Code: Select all
iptables -t mangle -I POSTROUTING -o usb0 -j TTL --ttl-set 65
Code: Select all
iptables -t mangle -I POSTROUTING -m physdev --physdev-out usb0 -j TTL --ttl-set 65
And here's a rule commonly shared here for IPv6:
Code: Select all
ip6tables -t mangle -I POSTROUTING -o usb0 -j HL --hl-set 65
Code: Select all
-A POSTROUTING -o [Interface] -j SNAT --to [Address]
or
-A POSTROUTING -o [Interface] -j MASQUERADE
Adding NAT6 support to your router will allow this rule to work, but it is worth considering that it is very likely your carrier can see each IPv6 device connected. With this setup, your carrier would see two devices, your phone and router. The public IP for devices behind the router will be the same, but that IP will be different than the one for your phone. The physdev rule from before:
Code: Select all
ip6tables -t mangle -I POSTROUTING -m physdev --physdev-out usb0 -j HL --hl-set 65
The obvious solution is to just give up and live with an IPv4 only network, but if you want IPv6 connectivity, the easiest way is using a VPN. You'd bypass the dun and set the protocol to IPv4(or block/disable IPv6). Then on the router you override the TTL, set usb0 to wan, and setup the VPN to serve the network. Many VPNs can act as a 4to6 translation layer, granting your network IPv6 connectivity.
I ultimately just built the kernel modules for NAT6 and TTL modification for my phone so I could do a router(phone) -> wireless switch type setup. It's the best I've been able to come up with, but it requires an unlocked bootloader and is too technical for most.
Added notes:
-I see some people using ping to test if their firewall rules work. This is not ideal, as it is trivial to modify the TTL of ICMP6 packets and still leak IPv6. The best way to test your rules is to daisy chain two routers. You apply the rules on the second router and sit downstream behind the first, dumping traffic to check if your rules work.
-The DHCP6 services on routers are configured to relay standard IPv6 connections. Setting up VPNs or NAT6 usually requires that you change this behavior to serve a local network instead, similar to how IPv4 is handled. This is something that is not at all obvious and well hidden even when it's possible. The setting for this is in OpenWRT 21.02 is:
Network -> Interfaces -> LAN -> Advanced Settings -> IPv6 assignment length: Disabled
This setting will unlock 'IPv6 address' and 'IPv6 gateway' under 'General Settings', allowing you to set your own local IP and prefix.