0

Android 11 seems to support IKEv2/IPsec now, so I'm attempting to build a roadwarrior swanctl profile for it. So far I'm getting as far as having an SA established, but then immediately deleted. Any advice?

The Android VPN profile has:

  • Type: IKEv2/IPsec PSK
  • Server: moon.isuldor.com
  • IPsec Identifier: strongswan at isuldor.com
  • IPsec PSK: hunter2

My vpn gateway has:

$ swanctl --version
strongSwan swanctl 5.9.0

$ cat /etc/swanctl/conf.d/android11.conf
connections {
    rw-isuldor {
        local_addrs = moon.isuldor.com
        pools = android11_pool4, android11_pool6
        fragmentation = yes
        send_cert = always
        rekey_time = 0s
        dpd_delay = 30s
        local {
            auth = pubkey
            certs = moon.pem
            id = moon.isuldor.com
        }
        remote {
            auth = psk
            id = strongswan at isuldor.com
        }
        children {
            moon {
                local_ts  = 0.0.0.0/0,::/0
                rekey_time = 0s
                dpd_action = clear
            }
        }
    }
}
secrets {
    ike-isuldor {
        id_isuldor = strongswan at isuldor.com
        secret = hunter2
    }
}
pools {
    android11_pool4 {
        addrs = 192.168.2.0/24
        dns = 1.1.1.1,1.0.0.1
    }
    android11_pool6 {
        addrs = 2607:9cf3:0:ae::6:1300/120
        dns = 2606:4700:4700::1111,2606:4700:4700::1001
    }
}

Relevant Logs from charon-systemd:

X.X.X.X is initiating an IKE_SA
IKE_SA (unnamed)[11] state change: CREATED => CONNECTING
selected proposal: IKE:AES_CBC_128/HMAC_SHA2_256_128/PRF_AES128_XCBC/MODP_3072
remote host is behind NAT
...
looking for peer configs matching Y.Y.Y.Y[moon.isuldor.com]...X.X.X.X[strongswan at isuldor.com]
selected peer config 'rw-isuldor'
authentication of 'strongswan at isuldor.com' with pre-shared key successful
...
peer requested virtual IP %any
assigning new lease to 'strongswan at isuldor.com'
assigning virtual IP 192.168.2.1 to peer 'strongswan at isuldor.com'
peer requested virtual IP %any6
assigning virtual IP <redacted> to peer 'strongswan at isuldor.com'
...
CHILD_SA moon{4} established with SPIs cba17603_i 0f8dcc81_o and TS 0.0.0.0/0 ::/0 === 192.168.2.1/32
CHILD_SA moon{4} state change: INSTALLING => INSTALLED
generating IKE_AUTH response 1 [ IDr CERT AUTH CPRP(ADDR DNS DNS) SA TSi TSr ]
splitting IKE message (2416 bytes) into 3 fragments
generating IKE_AUTH response 1 [ EF(1/3) ]
generating IKE_AUTH response 1 [ EF(2/3) ]
generating IKE_AUTH response 1 [ EF(3/3) ]
sending packet: from Y.Y.Y.Y[4500] to X.X.X.X[38733] (1236 bytes)
sending packet: from Y.Y.Y.Y[4500] to X.X.X.X[38733] (1236 bytes)
sending packet: from Y.Y.Y.Y[4500] to X.X.X.X[38733]
sending packet: from Y.Y.Y.Y[4500] to X.X.X.X[38733] (84 bytes)
sending packet: from Y.Y.Y.Y[4500] to X.X.X.X[38733]
checkin IKE_SA rw-isuldor[7]
sending packet: from Y.Y.Y.Y[4500] to X.X.X.X[38733]
checkin of IKE_SA successful
received packet: from X.X.X.X[38733] to Y.Y.Y.Y[4500]
waiting for data on sockets
checkout IKEv2 SA by message with SPIs ce7fea937528e3ca_i 115e7e1303dd7bc4_r
IKE_SA rw-isuldor[7] successfully checked out
received packet: from X.X.X.X[38733] to Y.Y.Y.Y[4500] (80 bytes)
parsed INFORMATIONAL request 2 [ D ]
received DELETE for IKE_SA rw-isuldor[7]
deleting IKE_SA rw-isuldor[7] between Y.Y.Y.Y[moon.isuldor.com]...X.X.X.X[strongswan at isuldor.com]
IKE_SA rw-isuldor[7] state change: ESTABLISHED => DELETING
IKE_SA deleted
generating INFORMATIONAL response 2 [ ]
sending packet: from Y.Y.Y.Y[4500] to X.X.X.X[38733] (80 bytes)
checkin and destroy IKE_SA rw-isuldor[7]
sending packet: from Y.Y.Y.Y[4500] to X.X.X.X[38733]
IKE_SA rw-isuldor[7] state change: DELETING => DESTROYING
CHILD_SA moon{4} state change: INSTALLED => DESTROYING
deleting policy 0.0.0.0/0 === 192.168.2.1/32 out
deleting policy 192.168.2.1/32 === 0.0.0.0/0 in
deleting policy 192.168.2.1/32 === 0.0.0.0/0 fwd
deleting SAD entry with SPI cba17603
deleted SAD entry with SPI cba17603
deleting SAD entry with SPI 0f8dcc81
deleted SAD entry with SPI 0f8dcc81
lease 192.168.2.1 by 'strongswan at isuldor.com' went offline
checkin and destroy of IKE_SA successful

Update: The issue became immediately apparent once I retrieved the android logs. Basically I used adb shell to access the device, then logcat with an appropriate filter. There's probably terminal apps that can do this as well. Root was not required.

130|sargo:/ $ whoami
shell
130|sargo:/ $ logcat *:S IkeV2VpnRunner:V
--------- beginning of system
--------- beginning of main
[..] IkeV2VpnRunner: com.android.internal.net.ipsec.ike.exceptions.AuthenticationFailedException: Expected the remote/server to use PSK-based authentication but they used: 14

Conclusion: the swanctl profile should have auth=psk under the local section and an additional line assigning the pre-shared key for the server like: id_moon = moon.isuldor.com under secrets.ike-isuldor. This worked exclusively for strongswan swanctl 5.9.0, but so far I was not able to reproduce the success with an earlier version 5.7.2. I suspect the syntax may have changed in some way. But the ultimate problem was the incorrect server authentication.

blee
  • 235
  • 4
  • 17
  • When adding a /64 to the pool, StrongSwan likely told you the range was too large, try assigning a subnet from your /64 instead. – Ginnungagap Nov 27 '20 at 07:33
  • 1
    While @Ginnungagap is right (the netmask is adjusted automatically, though), that's not the reason no IPv6 address is assigned. You need to define a separate pool for IPv6 and assign that to `pools` in addition to the IPv4 pool. If that's the reason for the deletion by Android we'll have to see. Actually, just noticed that your traffic selector looks weird (although, `0.0.0.0/0` is still negotiated). Should probably be `local_ts=0.0.0.0/0,::/0`. – ecdsa Nov 27 '20 at 08:45
  • Thanks, I fixed that local_ts up and tried assigning smaller IPV6 pool ranges: a /96, a /112, and a /128. I restarted strongswan-swanctl each time, but still to no effect. The client requests IPv6 and none is assigned. I've updated question to reflect that. – blee Nov 27 '20 at 17:18
  • I don't see any changes regarding the address pools in your updates. See [here](https://wiki.strongswan.org/projects/strongswan/wiki/VirtualIp#Responder-Configuration) on the strongSwan wiki for details. – ecdsa Nov 30 '20 at 08:29
  • @ecdsa thanks for following up on this. I finally sat down and fixed the IPv6 config, so an address is now assigned to the phone. ... And the behavior still appears to be the same! So much for hunch. – blee Nov 30 '20 at 22:31
  • 1
    You don't have any logs of the client? Possible issues on the client: authentication via server certificate fails (the client appears to authenticate via PSK, possible it expects the server to authenticate with PSK as well). – ecdsa Dec 01 '20 at 08:11
  • @ecdsa Negative result with `remote.auth=PSK`, but that was a very clever suggestion I hadn't thought of. I also tried replacing my self-signed certs with Let's Encrypt certs and had the same result. This is while adding my CA and LE-X3 root to the trusted CA list on the Android11 phone. I fully agree that this is a nightmare without clients logs. I will have to try to figure out how to dump the android IKE logs over adb shell when I have time. Might have to open a question on the Android stack exchange to solve that part... – blee Dec 01 '20 at 15:26
  • Okay, I have nominal client logging. For Android it's just `adb shell` and then `logcat *:S IkeV2VpnRunner:V`. Time to resume my troubleshooting. Will report back when I'm finished. – blee Dec 02 '20 at 00:29
  • @ecdsa Okay, I have a positive result now with `local.auth=PSK` afterall, exclusively on swanctl `5.9.0`. For reasons that still elude me, practically identical config fails on another server with swanctl `5.7.2` with `no shared key found`. This is why I had commented this morning that it was a negative result (ignore my comment typo `remote.auth`, I had it correct in the config). Still, that's a breakthrough and sufficiently solves this question. I'll add the client vpn logs momentarily. Feel free to answer the question with "try `local.auth=PSK`" and I'll mark it as solved. – blee Dec 02 '20 at 01:19

1 Answers1

2

As the client log confirms, it expected the server to authenticate with the PSK too, not a certificate. So instead of local.auth=pubkey you'd have to configure local.auth=psk.

Note that while using a certificate on the server and a PSK on the client is supported by the IKEv2 protocol, and it does protect against other hosts knowing the PSK impersonating the server (every client has to know it and could do so), it has the same issue as IKEv2's PSK authentication has in general: the client sends the AUTH payload before verifying the server's authentication. An active attacker could use this to determine a weak PSK via dictionary or brute force attacks. A far safer approach is to use certificate authentication for the server and username/password based EAP methods (e.g. EAP-MD5 or EAP-MSCHAPv2) for the client because then the client only sends its hashed password after verifying the server certificate.

ecdsa
  • 3,800
  • 12
  • 26
  • Curiously, Google decided to leave out IPsec certificate verification altogether in Android 11. Hopefully we'll see that in a future update. https://i.stack.imgur.com/poksz.png – blee Dec 02 '20 at 13:48
  • Yeah, that's a weird one. You can actually select something there, but only if you install the CA certificate as part of a PKCS#12 container in the system credential store ("Install a certificate" > "VPN & app user certificate"). As the latter indicates, these are usually used to install client certificate and private key, which are precisely not needed to authenticate with username/password. – ecdsa Dec 02 '20 at 16:23