Nested Wireguard tunnels not working on Android

i iordanov iiordanov at gmail.com
Mon Feb 8 10:42:12 UTC 2021


Hello,

In order to allow traffic to assist devices that cannot reach each
other directly, I am setting up wireguard tunnels through a server
with a public IP (40.30.40.30 in the example below).

For reasons of privacy, I'd like for the server to not be able to
decrypt my traffic. As a result, I would like for one encapsulating
Wireguard tunnel (subnet 10.1.2.0/24) to be peered through the server,
while a second nested Wireguard tunnel (subnet 10.1.3.0/24) to be
established through the first tunnel, peered only at the two devices
(Android and Linux in this case) that need to communicate.

An attempt was made to use a single Wireguard interface. Doing it this
way works between two Linux machines and even between Linux and Mac OS
X, but does not work between a Pixel 3a XL running Android 11 with the
GoBackend Wireguard implementation and my Linux laptop.

The config on the Android device, obtained with toWgQuickString():
======================================
    [Interface]
    Address = 10.1.2.5/24, 10.1.3.5/24
    ListenPort = 46847
    MTU = 1200
    PrivateKey = PRIVATE_KEY

    [Peer]
    AllowedIPs = 10.1.2.0/24
    Endpoint = 40.30.40.30:10000
    PersistentKeepalive = 3600
    PublicKey = VF5dic+a+6MllssbV+ShVwEBRrX9gr4do2iNylWrPGs=

    [Peer]
    AllowedIPs = 10.1.3.1/32
    Endpoint = 10.1.2.1:51555
    PersistentKeepalive = 3600
    PublicKey = 0Awdb451Z4+3Gezm7UlbRquC1kcF52r68J9wG1x/zUE=
======================================

The 10.1.2.0/24 subnet is the one that is "visible" to the public
server. The 10.1.3.0/24 subnet is the one that is private to the two
devices.

The devices can actually reach each other with netcat over UDP at
10.1.2.5:46847 and 10.1.2.1:51555 respectively. So the "encapsulating"
tunnel is working, and iperf3 were used to test it over UDP and TCP
successfully.

The "nested" tunnel does not get established.

The following permutations of the above config have the commented problems:

# Only 10.1.2.0/24 works, 10.1.3.0/24 does not.
    Address = 10.1.2.1/24, 10.1.3.1/24

# Only 10.1.2.0/24 works, 10.1.3.0/24, as expected, does not.
    Address = 10.1.2.1/24

# Neither network works
    Address = 10.1.3.1/24, 10.1.2.1/24

Suspecting routing, i ran ip route over adb, and obtained:
===================================
$ ip route show table 0 | grep 10.1
10.1.2.0/24 dev tun0 table 1548 proto static scope link
10.1.3.0/24 dev tun0 table 1548 proto static scope link
10.1.3.1 dev tun0 table 1548 proto static scope link
10.1.2.0/24 dev tun0 proto kernel scope link src 10.1.2.5
10.1.3.0/24 dev tun0 proto kernel scope link src 10.1.3.5
broadcast 10.1.2.0 dev tun0 table local proto kernel scope link src 10.1.2.5
local 10.1.2.5 dev tun0 table local proto kernel scope host src 10.1.2.5
broadcast 10.1.2.255 dev tun0 table local proto kernel scope link src 10.1.2.5
broadcast 10.1.3.0 dev tun0 table local proto kernel scope link src 10.1.3.5
local 10.1.3.5 dev tun0 table local proto kernel scope host src 10.1.3.5
broadcast 10.1.3.255 dev tun0 table local proto kernel scope link src 10.1.3.5
======================================

ip addr over adb shows:
======================================
    550: tun0: <POINTOPOINT,UP,LOWER_UP> mtu 1200 qdisc pfifo_fast
state UNKNOWN group default qlen 500
    link/none
    inet 10.1.2.5/24 scope global tun0
       valid_lft forever preferred_lft forever
    inet 10.1.3.5/24 scope global tun0:1
       valid_lft forever preferred_lft forever
======================================

On the Android logcat, the log appears to show handshakes exchanged:
======================================
peer(VF5d…rPGs) - Received handshake response
peer(VF5d…rPGs) - Sending keepalive packet
peer(0Awd…/zUE) - Received handshake initiation
peer(0Awd…/zUE) - Sending handshake response
======================================

The other device (not the public server) is a Linux box. Dmesg shows
======================================
[334831.125034] wireguard: LinuxWg: Handshake for peer 520
(10.1.2.5:46847) did not complete after 5 seconds, retrying (try 17)
[334831.125062] wireguard: LinuxWg: Sending handshake initiation to
peer 520 (10.1.2.5:46847)
======================================

wg showconf shows:
======================================
[Interface]
ListenPort = 51555
PrivateKey = PRIVATE_KEY

[Peer]
PublicKey = BOApHt2nj7Tvm/LAGpYB9/2KsZ8iYkWjfEUEUm7x6Q0=
AllowedIPs = 10.1.3.5/32
Endpoint = 10.1.2.5:46847
PersistentKeepalive = 25
======================================

wg show:
======================================
interface: LinuxWg
  public key: 0Awdb451Z4+3Gezm7UlbRquC1kcF52r68J9wG1x/zUE=
  private key: (hidden)
  listening port: 51555

peer: BOApHt2nj7Tvm/LAGpYB9/2KsZ8iYkWjfEUEUm7x6Q0=
  endpoint: 10.1.2.5:46847
  allowed ips: 10.1.3.5/32
  transfer: 0 B received, 37.00 KiB sent
  persistent keepalive: every 25 seconds

interface: LinuxWg2
  public key: Bb92MANIA5rzukELvNdTXMDWaBAi8+T8s7C+nnytRiE=
  private key: (hidden)
  listening port: 51556

peer: VF5dic+a+6MllssbV+ShVwEBRrX9gr4do2iNylWrPGs=
  endpoint: 40.30.40.30:10000
  allowed ips: 10.1.2.0/24
  latest handshake: 1 minute, 22 seconds ago
  transfer: 11.89 KiB received, 61.08 KiB sent
  persistent keepalive: every 25 seconds
======================================

Kernel:
======================================
Linux hostname 5.4.0-59-generic #65~18.04.1-Ubuntu SMP Mon Dec 14
15:59:40 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
======================================

Would you expect for this to work with GoBackend, or is there an
inherent limitation that would break it?

Any suggestions on what to do differently are welcome!

Thank you very much,
iordan


-- 
The conscious mind has only one thread of execution.


More information about the WireGuard mailing list