1

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?

UPDATE:

Thank you to @AryaS for the hint about adb logcat.

That certainly sent me in the right direction of what is going on.

I am connected to my phone via wireless debugging and here is some of the output (slightly anonymized) from adb logcat -s charon:*

W charon  : 10[CFG] selected proposal: IKE:AES_CBC_256/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/MODP_2048
W charon  : 10[IKE] local host is behind NAT, sending keep alives
W charon  : 10[IKE] remote host is behind NAT
W charon  : 10[IKE] sending cert request for "C=US, O=Internet Security Research Group, CN=ISRG Root X1"
E charon  : 10[IKE] establishing CHILD_SA android{1}
W charon  : 10[ENC] generating IKE_AUTH request 1 [ IDi CERTREQ CPRQ(ADDR DNS) SA TSi TSr N(MOBIKE_SUP) N(ADD_6_ADDR) N(ADD_6_ADDR) N(MULT_AUTH) N(EAP_ONLY) N(MSG_ID_SYN_SUP) ]
W charon  : 10[NET] sending packet: from 192.168.0.175[56045] to SERVER.IP.ADDRESS[4500] (400 bytes)
W charon  : 11[NET] received packet: from SERVER.IP.ADDRESS[4500] to 192.168.0.175[56045] (2720 bytes)
W charon  : 11[ENC] parsed IKE_AUTH response 1 [ IDr CERT CERT AUTH EAP/REQ/ID ]
W charon  : 11[IKE] received end entity cert "CN=example.com"
W charon  : 11[IKE] received issuer cert "C=US, O=Let's Encrypt, CN=R3"
W charon  : 11[CFG]   using certificate "CN=example.com"
W charon  : 11[CFG]   using untrusted intermediate certificate "C=US, O=Let's Encrypt, CN=R3"
W charon  : 11[CFG]   using trusted intermediate ca certificate "C=US, O=Internet Security Research Group, CN=ISRG Root X1"
W charon  : 11[CFG] no issuer certificate found for "C=US, O=Internet Security Research Group, CN=ISRG Root X1"
W charon  : 11[CFG]   issuer is "O=Digital Signature Trust Co., CN=DST Root CA X3"
W charon  : 11[IKE] no trusted ECDSA public key found for 'example.com'
W charon  : 11[CFG] closed tun device due to charon will be shutdown
W charon  : 11[CFG] created abort file after scheduled shutdown job
W charon  : 11[ENC] generating INFORMATIONAL request 2 [ N(AUTH_FAILED) ]
W charon  : 11[NET] sending packet: from 192.168.0.175[56045] to SERVER.IP.ADDRESS[4500] (80 bytes)
W charon  : 00[DMN] signal of type SIGTERM received. Shutting down

... So I guess it all boils down to that DST Root CA X3 certificate from Let's Encrypt is not part of my phones list of trusted certificates?

  • Unrelated: Note that using _modp2048s256_ [isn't recommended](https://docs.strongswan.org/docs/5.9/howtos/securityRecommendations.html). If supported by the server, use _ecp384_, otherwise, use _modp2048_. – ecdsa Aug 22 '22 at 08:03
  • Have you tried using the RSA server certificate? Because the native Android client might not actually support ECDSA. – ecdsa Aug 22 '22 at 08:04
  • It seems that I can use my iOS profile - as long as I set `id` to `username@example.com` and I **do not** send `eap_id` field. However debugging Freeradius a bit further revealed that the username passed by Android client to Freedius is the one I set in "ipsec identificator". It completely ignore the username field that is set further down in configuration. So in other word Android VPN client is still broken? – Lasse Michael Mølgaard Aug 23 '22 at 08:02
  • Is this a Samsung device? if yes I might have a clue. No Idea about other. – Arya S. Nov 25 '22 at 18:41
  • Yes a Samsung Galaxy S20 Ultra. It was updated to Android 13 yesterday, but still cannot connect via native client. – Lasse Michael Mølgaard Nov 26 '22 at 13:02
  • 1
    @LasseMichaelMølgaard OK, so I found out Samsung is actually shipping out Strongswan (Charon daemon to be exact) OOTB. The native client is using Charon. You can bring up `adb logcat -s charon:*` to debug. I found out when I'm using Letsencrypt (or most public CA) the OCSP check will always fail b/c the OCSP server is returning no nonce (see https://wiki.strongswan.org/issues/3557). Whatever version Samsung uses still has this behaviour. Now, from the server side I got exactly the same log as yours `N(AUTH_FAILED)`. When I use self-signed cert (no OCSP) I can connect just fine. PSK also works! – Arya S. Nov 26 '22 at 20:53
  • I'm having the exact same issues. Native VPN on Samsung S21 works only with self-signed cert but not with LetsEncrypt cert. Strongswan client works fine with both. I think the issue has to do with fragmentation. The cert is over 3kB with LetsEncrypt. When I look at the logs when the strongswan client connects, the cert packet is sent fragmented, but I don't see this fragmentation when using the native VPN client. I also see no `N(FRAG_SUP)` in the `IKE_SA_INIT` request on connection. – oisyn Jan 02 '23 at 02:14
  • Thank you @AryaS. for the hint. Updating question with output from phone. – Lasse Michael Mølgaard Jan 03 '23 at 23:20

0 Answers0