I can see that Android native VPN client supports IKEv2/MSCHAPv2, so in theory it should be possible to connect to Strongswan VPN server from Android without installing additional software (like the Strongswan VPN client).
However: In practise it is not quite as easy to make it work.
My server is using FreeRadius as a backend and is working fine with:
- iPhone native VPN client
- Windows 10/11 native VPN client
- StrongVPN client for Android.
So I thought it should be easy to brute force support Android native client, since the above were not that hard.
Well turn out it was not quite as easy.
Reading the logs to find out what was needed, I found this line:
14[CFG] received proposals:
IKE:AES_CBC_256/AES_CBC_128/HMAC_SHA2_512_256/HMAC_SHA2_384_192/HMAC_SHA2_256_128/HMAC_SHA1_96/PRF_HMAC_SHA2_512/PRF_HMAC_SHA2_384/PRF_HMAC_SHA2_256/PRF_HMAC_SHA1/MODP_2048_256/ECP_384/ECP_256/MODP_2048/MODP_1536,
IKE:AES_GCM_16_256/AES_GCM_16_128/PRF_HMAC_SHA2_512/PRF_HMAC_SHA2_384/PRF_HMAC_SHA2_256/PRF_HMAC_SHA1/MODP_2048_256/ECP_384/ECP_256/MODP_2048/MODP_1536
As far as I have gathered that is Android telling Strongswan which encryption ciphre it supports.
Using: StrongSwans documentation for cipher suites I found out that I should make entry with a proposal for ciphres that contains either:
A combination of aes256/aes128
, sha512/sha384/sha256/sha1
, prfsha512/prfsha384/prfsha256/prfsha1
and modp2048s256/ecp384/ecp256/modp2048/modp1536
.
Or:
A combination of aes256gcm16/aes128gcm16
, prfsha512/prfsha384/prfsha256/prfsha1
and modp2048s256/ecp384/ecp256/modp2048/modp1536
.
This led me to this proposal for IKE transport: aes256-sha512-prfsha512-modp2048s256
.
My configuration for Android profile is as follows:
conn-defaults {
local_addrs = SERVER.IP.ADDRESS
local {
auth = pubkey
certs = example.com-ecdsa.cer
id = example.com
}
version = 2
send_certreq = no
send_cert = always
unique = never
fragmentation = yes
encap = yes
dpd_delay = 60s
rekey_time = 0s
}
# Default login method
eap-defaults {
remote {
auth = eap-radius
id = %any
eap_id = %any
}
}
eap-android : eap-default {
remote {
# Do NOT define eap_id, since Radius won't get triggered on login.
auth = eap-radius
id = *@example.com
}
}
connections
{
conn-android : conn-defaults, eap-android {
children {
net {
local_ts = 0.0.0.0/0
}
esp_proposals = aes256-sha512-prfsha512-modp2048s256
}
pools = IkeVPN-ipv4
proposals = aes256-sha512-prfsha512-modp2048s256
}
conn-windows : conn-defaults, eap-defaults {
children {
net {
local_ts = 0.0.0.0/0
}
esp_proposals = aes256-sha256-prfsha256-modp1024
}
proposals = aes256-sha256-prfsha256-modp1024
pools = IkeVPN-ipv4
}
conn-ios : conn-defaults, eap-defaults {
local {
auth = pubkey
certs = example.com-rsa.cer
id = example.com
}
children {
net {
local_ts = 0.0.0.0/0
}
esp_proposals = aes256-sha256
}
pools = IkeVPN-ipv4
proposals = aes256-sha256-prfsha256-modp2048
}
}
pools
{
IkeVPN-ipv4 {
addrs = 192.168.201.0/24
#My DNS server is hosted on another internal net.
dns = 192.168.200.1
}
}
A quick note on certificates on my VPN server. I got 2 Let's Encrypt certificates installed.
A 2048-bit RSA certificate (used by iPhone users, since they can't connect to a ECDSA certfificate?).
A 256-bit ECDSA certificate, which is used by all OS that supports ECDSA.
A little bit of trial and error led me to the configuration of the eap-android
section, but from there I was a bit stumped.
First off: During configuration of Andoid VPN I quickly learned that I had to define ipsec identifier
though I am a bit unsure what it is being used for during login.
I did notice that whatever I used as a value in ipsec identifier
would be matched against the id
attribute in the remote
section. Therefore I just copied the content from username
into ipsec identifier
.
However trying to login to VPN server Android native client gave me the following output in log (slightly redacted):
14[CFG] looking for peer configs matching SERVER.IP.ADDRESS[%any]...CLIENT.IP.ADDRESS[user@example.com]
14[CFG] selected peer config 'conn-android'
14[CFG] sending RADIUS Access-Request to server '192.168.200.1'
14[CFG] received RADIUS Access-Challenge from server '192.168.200.1'
14[IKE] initiating EAP_TTLS method (id 0x01)
14[IKE] peer supports MOBIKE
14[IKE] authentication of 'example.com' (myself) with ECDSA_WITH_SHA256_DER successful
14[IKE] sending end entity cert "CN=EXAMPLE.COM"
14[IKE] sending issuer cert "C=US, O=Let's Encrypt, CN=R3"
14[ENC] generating IKE_AUTH response 1 [ IDr CERT CERT AUTH EAP/REQ/TTLS ]
14[NET] sending packet: from SERVER.IP.ADDRESS[4500] to CLIENT.IP.ADDRESS[6727] (3056 bytes)
07[NET] received packet: from SERVER.IP.ADDRESS[6727] to CLIENT.IP.ADDRESS[4500] (96 bytes)
07[ENC] parsed INFORMATIONAL request 2 [ N(AUTH_FAILED) ]
07[ENC] generating INFORMATIONAL response 2 [ N(AUTH_FAILED) ]
07[NET] sending packet: from SERVER.IP.ADDRESS[4500] to CLIENT.IP.ADDRESS[6727] (96 bytes)
Digging further into FreeRadius by running it through freeradius -X
I found that Freeradius received username and sends a challange back to VPN client, but it never receives a response to the challenge from VPN client.
Is there anyone that knows what is going on since username authentication hangs up in the middle of login?