0

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?

  • 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

0 Answers0