VPNHotspot
VPNHotspot copied to clipboard
IPv6 tethering
Currently AOSP only has support for IPv6 tethering when using mobile networks under supported carriers since Android 7.0.
It's unclear how to do this for IPv6-capable VPN or even Wi-Fi. The main issue is configuring a valid IPv6 address for clients. This is further complicated by the fact that sometimes dnsmasq
(actually I'm not 100% sure yet) will configure another valid IPv6 address using Router Advertisement.
Looks like a prob here too. My Xiaomi Mi6 has mobile IPv6 support. If I connect to IPv6 vpn-server my Android has the new default v6 route through tunnel. But all clients have an IPv6 leak even if "Disable IPv6 tethering" option is enabled. I 'll show all routes / routing tables if I 've more time.
@githuborer That would certainly be helpful. You should check if your clients have an IPv6 address after checking "Disable IPv6 tethering". If you want to do a follow-up, feel free to open another issue as this one is reserved for handling IPv6 tethering better.
You should check if your clients have an IPv6 address after checking "Disable IPv6 tethering".
Yes that's the point. Real IPv6 is leaking to connected clients. "Disable IPv6 tethering" option does nothing for my phone.
Hey I have a OnePlus6 on TMobile which prefers IPv6 by default. I noticed some interesting things recently:
- I always used Disable IPv6 and if you do whatismyip.com -- laptop only detects IPv4
- USB DNS has issue when #1 is turned on, so I turned it off and USB Tethering works.
- With a VPN (I sometimes use my home/vacation home using OpenVPN and have NordVPN -- both IPv4), if Disable IPv6 is turned off, turning on the VPN does nothing (causes all traffic to go around the VPN), whereas if Disable IPv6 is turned on, all traffic goes through the VPN. You can turn the VPN on and off and traffic will switch to going over the VPN or native at will. So on my phone, re-enabling the IPv6 totally defeats VPN's purpose -- all traffic goes around the VPN.
I am using rooted OnePlus Oxygen, but I think it is pretty close to vanilla Android -- the phone was bought unlocked...the TMobile version may have different tethering system.
I could contribute and look into fixing this -- assume most of this is implemented through iptables and ip6tables, right? Would also love to add a TTL (IPv4) hop limit (IPv6) option to help people using the app to get around tethering restrictions...
@glennbutler It would be great if you can look into this! I think this might be more than messing with ip6tables
as for some VPNs, a simple IPv6 forwarding rule may be enough, but for others some kind of IPv6 NAT might be required (I'm not sure if Android kernel supports this).
I took an additional look at this and here are my thoughts.
For now, I do not plan to support any kind of IPv6 NAT (because I think IPv4-only NAT should cover all the use cases). However, using a neighbor discovery proxy might be useful for local-only interfaces (portier might be useful but still in development) for advantages of IPv6 networks.
No plan on implementing this any time soon yet.
Verizon support IPv6 natively as well, but none of the wifi networks I use (college, library) do (mind you I only tether on data).
For whatever reason if I set up block IPv6 in VPN hotspot Firefox Nightly on my PC fails to connect to any website (getting an IPv6 address from DNS looks like, and it thinks it can connect but it can't).
@linuxandria Sounds like the browser cannot do IPv4 fallback gracefully. Try disabling and reenabling your WiFi on your laptop so that it no longer holds a global IPv6 address.
@Mygod you have any idea how many times I tried that? Lol
@linuxandria If you have this app's service active and disable IPv6 tethering enabled, your devices should not be able to obtain an IPv6 address from your carrier. If this is not the case, please open a separate issue (with more details) since this is off-topic.
I turned off the disable IPv6 tethering function, but I can't get an available IPv6 connection (I don't need IPv6 to connect through VPN), I know that disabling IPv6 can avoid VPN leakage. But sometimes I need to connect to the IPv6 network(Direct connection without VPN) through a relay, without ipv6 will cause problems to use. I don't know if this is a bug.
I tried to configure the default gateway of the client device to the IPV6 address used by the P2P interface. This address can be pinged normally. But unable to access other URLs, suggesting no route
Seems like my kernel is not built with ipv6 nat support, so even running a transparent proxy is out of the question. Still have hope bridging might work. VPN clients can be configured to offer a local subnet rather than just a single local ip, or a least I know the Android WireGuard client can, so that might actually be a workable solution.
How far were you able to get in experimenting with this, Mygod?
I did not try very hard to get this going because honestly the benefits are minimal. Feel free to submit a PR if you get it going though. ;)
Quickly found that bridging is also not possible, not without compiling tap support into the kernel and using native clients.
Just going to post my test script that I used to manually configure tethering, I couldn't find this elsewhere. Took an embarrassing amount of iteration to get this to work.
#!/system/bin/sh
#netID = 99 0x63
setprop sys.usb.config 'rndis,adb'
ndc interface setcfg rndis0 192.168.42.129 24 up
ndc ipfwd enable tethering
ndc network interface add 99 rndis0
ndc network route add 99 rndis0 192.168.42.0/24
ndc network route add 99 rndis0 fe80::/64
ndc tether interface add rndis0
ndc tether dns set 99 8.8.4.4 8.8.8.8
ndc nat enable rndis0 tun0 99
ndc ipfwd add rndis0 tun0
ndc tether start 192.168.42.10 192.168.42.99
I have not looked into this extensively but I am not sure why you say it is impossible. I think Android supports IPv6 tethering natively? Do they use something else?
It supports IPV6 tethering the correct way, each tethered device receives a unique address from the provider. This is clearly undesirable as any traffic through those addresses is defacto tethering and will be treated as such by the provider.
Tethering through a VPN gets around this, but to be possible, it needs a layer 2 TAP interface to use with bridging(similar to how it works with the provider) or support natting(to simply route traffic rather than hide topology). These features are not at all standard in Android, even with custom kernels/roms, so it doesn't make sense to support them here IMO.
Think I answered poorly. AFAICT public ipv6 addresses for tethered clients are configured via slaac server on the provider side, not anything on the client side. Guess this would be testable by blocking icmp6 between rndis0 and the ipv6 mobile interface and reconnecting.
I had some recent success getting tethering with ipv6 working. I grabbed Lineage sources for my phone and rebuilt my kernel with CONFIG_NF_NAT_IPV6 and CONFIG_IP6_NF_TARGET_MASQUERADE enabled. Also cross-compiled radvd for ipv6 provisioning. radvd.conf defines interface rndis0, prefix fd00::/64, and ipv6 dns servers.
#!/system/bin/sh
#netID = 99 0x63
setprop sys.usb.config 'rndis,adb'
ndc interface setcfg rndis0 192.168.42.129 24 up
ip -6 addr add fd00::1/64 dev rndis0 scope global
ip -6 route add fd00::/64 dev rndis0 proto kernel src fd00::1
ndc ipfwd enable tethering
ndc network interface add 99 rndis0
ndc network route add 99 rndis0 192.168.42.0/24
ndc network route add 99 rndis0 fd00::/64
ndc network route add 99 rndis0 fe80::/64
ndc nat enable rndis0 tun0 99
ndc ipfwd add rndis0 tun0
ip6tables -t nat -N tetherctrl_nat_POSTROUTING
ip6tables -t nat -A POSTROUTING -j tetherctrl_nat_POSTROUTING
ip6tables -t nat -A tetherctrl_nat_POSTROUTING -o tun0 -j MASQUERADE
ip6tables -t filter -D tetherctrl_FORWARD -g tetherctrl_counters
ip6tables -t filter -A tetherctrl_FORWARD -i tun0 -o rndis0 -m state --state RELATED,ESTABLISHED -g tetherctrl_counters
ip6tables -t filter -A tetherctrl_FORWARD -i rndis0 -o tun0 -m state --state INVALID -j DROP
ip6tables -t filter -A tetherctrl_FORWARD -i rndis0 -o tun0 -g tetherctrl_counters
ip6tables -t filter -A tetherctrl_FORWARD -j DROP
# These commands as written are blocking
dnsmasq --keep-in-foreground --no-resolv --no-poll --dhcp-authoritative --dhcp-range=192.168.42.10,192.168.42.99,1h --dhcp-option=6,8.8.8.8,8.8.4.4 --dhcp-leasefile=/sdcard/dnsmasq.leases --dhcp-option-force=43,ANDROID_METERED --pid-file=/sdcard/dnsmasq.pid --listen-mark 0xf0063
radvd -n
Here I set the ipv6 address and route, mark traffic for the global ipv6 subnet, and add the missing ip6tables rules to match. Found I needed to call dnsmasq directly as ndc tether seemed to interfere.
While I definitely applaud the efforts, I do not think we can implement anything close to recompiling the kernel within the app though. 😅
I think the worst we can do is to do everything in user space, which might not be super efficient. I currently do not have the luxury to investigate personally but please do keep me posted. 👍
Ideally rom and kernel maintainers will pick up on this use case and start building with these options. At the very least it could save advanced users a bunch of time. I imagine two device setups will ultimately be more popular since it's easier and doesn't require root(ex. run a transparent proxy like squid on the phone and configure a router to redirect all outgoing traffic to it).
Do tell if you can think of an entry point for a software solution. The obvious place to look is tunnels, which are widely supported, but only the layer 3 variants that are not useful here. This would also be a herculean task to implement.
Finally stumbled on how this can be done, I feel really dumb for not landing on this sooner. Turns out we can use TPROXY mangle rules to capture and redirect outbound IPv6 traffic to a local transparent proxy. transocks-wong and microsocks (for example) would be enough for TCP support, but I'm unsure about UDP atm.
The kernel module to achieve this is very widely supported on Android: CONFIG_NETFILTER_XT_TARGET_TPROXY
Sounds great. Did you get it working?
Could you set up a broute to accomplish this?
I use this command on my router to enable ipv6 on my network from a tethered phone. wan (the android phone to router connection) and lan is local network
ebtables -t broute -A BROUTING -i wan -p ! ipv6 -j DROP && brctl addif lan wan
Could you bridge the vpn connection for IPv6 and then do normal NAT tethering for IPv4? The biggest issue I can think of is kernel module support.
Nevermind. I just tried ebtables on my phone. Command not found. Leaving that failed idea up for the next person's info.
does disabling ipv6 tethering slow speed? what are the pros and cons?
@Poorav165 IPv6 tethering will not be routed through VPNs. You should disable that if you want everything to go through VPN.
Ok ,thx. But what if I am not using vpn? Will turning ipv6 on improve speed?
Finally stumbled on how this can be done, I feel really dumb for not landing on this sooner. Turns out we can use TPROXY mangle rules to capture and redirect outbound IPv6 traffic to a local transparent proxy. transocks-wong and microsocks (for example) would be enough for TCP support, but I'm unsure about UDP atm.
The kernel module to achieve this is very widely supported on Android: CONFIG_NETFILTER_XT_TARGET_TPROXY
This is supported on the Pixel 4 XL stock source, how did you get it to work though?
Sorry for the extremely late reply. https://github.com/heiher/hev-socks5-server https://github.com/heiher/hev-socks5-tproxy
The last line in Android.mk for hev-socks5-tproxy is set to 'BUILD_SHARED_LIBRARY', change to 'BUILD_EXECUTABLE'.
Both projects crash on localtime calls for me, so I disabled logging in hev-socks5-logger.c and hev-logger.c, example:
int
hev_socks5_logger_init (HevSocks5LoggerLevel level, const char *path)
{
req_level = level;
/*if (0 == strcmp (path, "stdout"))
fd = dup (1);
else if (0 == strcmp (path, "stderr"))
fd = dup (2);
else
fd = open (path, O_WRONLY | O_APPEND | O_CREAT, 0640);
if (fd < 0)
return -1;*/
return 0;
}
Then build. Configs are located under conf/main.yml. Enable the auth block for hev-socks5-server and set the username/password. Then run them(from /data/local/tmp):
./hev-socks5-server socks.yml
./hev-socks5-tproxy tprox.yml
And the iptables rules I used:
# IPv4
iptables -t mangle -A PREROUTING -d 0.0.0.0/8 -j RETURN
iptables -t mangle -A PREROUTING -d 10.0.0.0/8 -j RETURN
iptables -t mangle -A PREROUTING -d 127.0.0.0/8 -j RETURN
iptables -t mangle -A PREROUTING -d 169.254.0.0/16 -j RETURN
iptables -t mangle -A PREROUTING -d 172.16.0.0/12 -j RETURN
iptables -t mangle -A PREROUTING -d 192.0.0.0/24 -j RETURN
iptables -t mangle -A PREROUTING -d 192.0.2.0/24 -j RETURN
iptables -t mangle -A PREROUTING -d 192.88.99.0/24 -j RETURN
iptables -t mangle -A PREROUTING -d 192.168.0.0/16 -j RETURN
iptables -t mangle -A PREROUTING -d 198.18.0.0/15 -j RETURN
iptables -t mangle -A PREROUTING -d 198.51.100.0/24 -j RETURN
iptables -t mangle -A PREROUTING -d 203.0.113.0/24 -j RETURN
iptables -t mangle -A PREROUTING -d 224.0.0.0/4 -j RETURN
iptables -t mangle -A PREROUTING -d 240.0.0.0/4 -j RETURN
iptables -t mangle -A PREROUTING -d 255.255.255.255 -j RETURN
iptables -t mangle -A PREROUTING -p tcp -j TPROXY --on-port 1088 --tproxy-mark 1088
iptables -t mangle -A PREROUTING -p udp -j TPROXY --on-port 1088 --tproxy-mark 1088
ip rule add fwmark 1088 table 100
ip route add local default dev lo table 100
# IPv6
ip6tables -t mangle -A PREROUTING -d :: -j RETURN
ip6tables -t mangle -A PREROUTING -d ::1 -j RETURN
ip6tables -t mangle -A PREROUTING -d ::ffff:0:0:0/96 -j RETURN
ip6tables -t mangle -A PREROUTING -d 64:ff9b::/96 -j RETURN
ip6tables -t mangle -A PREROUTING -d 100::/64 -j RETURN
ip6tables -t mangle -A PREROUTING -d 2001::/32 -j RETURN
ip6tables -t mangle -A PREROUTING -d 2001:20::/28 -j RETURN
ip6tables -t mangle -A PREROUTING -d 2001:db8::/32 -j RETURN
ip6tables -t mangle -A PREROUTING -d 2002::/16 -j RETURN
ip6tables -t mangle -A PREROUTING -d fc00::/7 -j RETURN
ip6tables -t mangle -A PREROUTING -d fe80::/10 -j RETURN
ip6tables -t mangle -A PREROUTING -d ff00::/8 -j RETURN
ip6tables -t mangle -A PREROUTING -d AAAA:BBBB:CCCC:DDDD::/64 -j RETURN
ip6tables -t mangle -A PREROUTING -p tcp -j TPROXY --on-port 1088 --tproxy-mark 1088
ip6tables -t mangle -A PREROUTING -p udp -j TPROXY --on-port 1088 --tproxy-mark 1088
ip -6 rule add fwmark 1088 table 100
ip -6 route add local default dev lo table 100
Replace AAAA:BBBB:CCCC:DDDD with the first half of your public IPv6 address(the one assigned by your carrier). Wireguard in kernel mode breaks this configuration, but other VPNs work fine.
That's a lot to have just figured out, very nice and thank you for coming back with the well written instructions.
I'm not setup for compiling NDK binaries currently but I will certainly try this as soon as I can pull down the compiler, I used to write Android apps but lost interest in it several years ago