I'm working on an Android version of an app to connect to software defined networks. The native code behind it supports connecting to multiple virtual networks at a time, and I'm adapting this to Android's VpnService.
Since Android limits you to a single vpn interface, I call VpnService.Builder.addAddress()
and VpnService.Builder.addRoute()
once for each virtual network, then call establish()
. Once establish()
is called, I can ping the Android device on each of its assigned addresses from other devices on the two virtual networks, however I can only get routing to one of the virtual networks within Android OS.
Is it possible using VpnService.Builder to assign multiple addresses and routes to the tun interface?
Update: Jun 15, 2015
Things appear to be getting configured correctly. Looking around in logs and via adb shell, I have tun0 and tun0:1
# ifconfig tun0
tun0: ip 10.248.13.87 mask 255.255.240.0 flags [up point-to-point running]
# ifconfig tun0:1
tun0:1: ip 29.182.13.87 mask 254.0.0.0 flags [up point-to-point running]
And both TUN entries are in the routing table
Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT
eth0 00000000 0202000A 0003 0 0 0 00000000 0 0 0
eth0 0002000A 00000000 0001 0 0 0 00FFFFFF 0 0 0
tun0 0000F80A 00000000 0001 0 0 0 00F0FFFF 0 0 0
tun0 0000001C 00000000 0001 0 0 0 000000FE 0 0 0
However only one of the two routes is accessible. Here's a ping to two hosts up on the other end of the VPN connection:
ping -c 4 10.248.4.247
PING 10.248.4.247 (10.248.4.247) 56(84) bytes of data.
64 bytes from 10.248.4.247: icmp_seq=1 ttl=128 time=126 ms
64 bytes from 10.248.4.247: icmp_seq=2 ttl=128 time=93.5 ms
64 bytes from 10.248.4.247: icmp_seq=3 ttl=128 time=73.5 ms
64 bytes from 10.248.4.247: icmp_seq=4 ttl=128 time=53.4 ms
--- 10.248.4.247 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3029ms
rtt min/avg/max/mdev = 53.492/86.826/126.702/27.026 ms
root@generic_x86:/proc/net # ping -c 4 29.95.148.247
ping -c 4 29.95.148.247
PING 29.95.148.247 (29.95.148.247) 56(84) bytes of data.
--- 29.95.148.247 ping statistics ---
4 packets transmitted, 0 received, 100% packet loss, time 3013ms
It appears that I've run into a bug in Android.
After digging through tcpdump logs on both ends of the connection, I found that packets that are routed to tun0:1 have the source IP in the IP Header set to the IP address of tun0.
After writing code to replace the source IP and checksum in the IP packets, ICMP pings now work. I'll also need to do the same for TCP and UDP packets.