Android VpnService with multiple addresses and routes?

2.7k views Asked by At

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
1

There are 1 answers

0
Grant Limberg On BEST ANSWER

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.