2

I have a StrongSwan VPN that for some reason unknown to me cannot connect iOS users to my VPN server.

A few quick notes:

  • My StrongSwan server is front for VPN clients who connects to my network. I used WireGuard for my backend site-to-site routing.

  • All StrongSwan VPN users are validated against a FreeRadius server.

  • StrongSwan clients are assigned an IP on the 192.168.201.0/24 subnet, while WireGuard backbone net is running on the 192.168.200.0/24 subnet.

  • All clients are also handed a public IPv6 address belonging to a /48 subnet assigned to me.

I run StrongSwan on Ubuntu 20.04 and my configuration file is located in the /etc/swanctl/config/ folder and is included by default due to filename ends on .conf.

The content are as follows:

# Default VPN server settings for all connections
conn-defaults {
    local_addrs = PUBLIC_IPV4, PUBLIC_IPV6

    local {
      auth = pubkey
      certs = vpn-ecdsa.cer
      id = vpn.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
  }
}

connections
{
  # Generic Android configuration that is extended further down.
  #
  # Works with StrongSwan VPN client for Android
  conn-unix : conn-defaults, eap-defaults {
    children {
      net {
        local_ts = 0.0.0.0/0, ::/0
      }

      net-unix : child-defaults {
      }

      esp_proposals = aes128gcm128-x25519
    }

    proposals = aes128-sha256-x25519
  }

  # All Windows klients matches this rule as username validation 
  # is done by 'eap_start = yes' in strongswan.conf. 
  #
  # Works with Windows 10 built-in VPN client.
  conn-windows : conn-defaults, eap-defaults {
    children {
      net {
        local_ts = 0.0.0.0/0, ::/0
      }

      esp_proposals = aes256-sha256-prfsha256-modp1024
    }

    proposals = aes256-sha256-prfsha256-modp1024
    pools = IkeVPN-site-ipv4, IkeVPN-site-ipv6

  }

  # A very similar configuration to Windows clients 
  # configuration, except iOS uses 2048 bit keys, 
  # while Windows uses 1024 bit keys.
  #
  # Does NOT work in its current state.
  conn-ios : conn-defaults, eap-defaults {
    children {
      net {
        local_ts = 0.0.0.0/0, ::/0
      }

      esp_proposals = aes256-sha2_256
      pools = IkeVPN-site-ipv4, IkeVPN-site-ipv6

    }

    proposals = aes256-sha256-prfsha256-modp2048
  }

  # Android users is matched against this connection as they are 
  # running the app StrongSwan VPN client. Username is passed in the
  # 'id' field to StrongSwan VPN server.
  conn-unix-site : connections.conn-unix {
    remote {
      id = *@site.example.com
    }
    pools = IkeVPN-site-ipv4, IkeVPN-site-ipv6
  }
}

pools
{
   IkeVPN-site-ipv4 {
      addrs = 192.168.201.0/24
      dns = 192.168.200.1
   }

   IkeVPN-site-ipv6 {
      addrs = 2001:db8:cafe::/97
      dns = 2001:db8::1
   }
}

My configuration is created using the structure given from the following webpage:

https://wiki.strongswan.org/projects/strongswan/wiki/Strongswanconf#Referencing-other-Sections

The reason why I use it is due to avoiding to repeat same configuration settings across all my connection profiles.

If you are not familiar to this setup the following configuration for conn-ios this should be considered equivalent:

conn-ios {
   # Obtained from conn-default
   local_addrs = PUBLIC_IPV4, PUBLIC_IPV6

   local {
      auth = pubkey
      certs = vpn-ecdsa.cer
      id = vpn.example.com
   }

   version = 2
   send_certreq = no
   send_cert = always
   unique = never
   fragmentation = yes
   encap = yes
   dpd_delay = 60s

   rekey_time = 0s

   # Obtained from eap-defaults
   remote {
      auth = eap-radius
      id = %any
      eap_id = %any
   }

   # Obtained from original conn-ios profile above.
   children {
      net {
         local_ts = 0.0.0.0/0, ::/0
      }

      esp_proposals = aes256-sha2_256
      pools = IkeVPN-site-ipv4, IkeVPN-site-ipv6
   }

   proposals = aes256-sha256-prfsha256-modp2048
}

The server certificate listed in the conn-default section is a ECDSA certificate obtained from Let's Encrypt using Acme.sh.

The encryption values for proposalsand esp_proposals in the iOS configuration is taken from the hint in: https://wiki.strongswan.org/projects/strongswan/wiki/AppleClients.

When testing all combinations of Android or Windows users connects without any issues, but when somebody tries to login using iPhone the connection then stalls.

Output from log when an iPhone tries to connect is as follows:

10[IKE] CLIENT_IPV4 is initiating an IKE_SA
10[CFG] received proposals: IKE:AES_CBC_256/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/MODP_2048, IKE:AES_CBC_256/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/ECP_256, IKE:AES_CBC_256/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/MODP_1536, IKE:AES_CBC_128/HMAC_SHA1_96/PRF_HMAC_SHA1/MODP_1024, IKE:3DES_CBC/HMAC_SHA1_96/PRF_HMAC_SHA1/MODP_1024
10[CFG] configured proposals: IKE:AES_CBC_128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/CURVE_25519
10[IKE] no matching proposal found, trying alternative config
10[CFG] received proposals: IKE:AES_CBC_256/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/MODP_2048, IKE:AES_CBC_256/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/ECP_256, IKE:AES_CBC_256/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/MODP_1536, IKE:AES_CBC_128/HMAC_SHA1_96/PRF_HMAC_SHA1/MODP_1024, IKE:3DES_CBC/HMAC_SHA1_96/PRF_HMAC_SHA1/MODP_1024
10[CFG] configured proposals: IKE:AES_CBC_256/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/MODP_1024
10[IKE] no matching proposal found, trying alternative config
10[CFG] selected proposal: IKE:AES_CBC_256/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/MODP_2048
10[IKE] remote host is behind NAT
10[ENC] generating IKE_SA_INIT response 0 [ SA KE No N(NATD_S_IP) N(NATD_D_IP) N(FRAG_SUP) N(CHDLESS_SUP) N(MULT_AUTH) ]
10[NET] sending packet: from PUBLIC_IPV4[500] to CLIENT_IPV4[6452] (456 bytes)
06[NET] received packet: from CLIENT_IPV4[13549] to PUBLIC_IPV4[4500] (512 bytes)
06[ENC] unknown attribute type INTERNAL_DNS_DOMAIN
06[ENC] parsed IKE_AUTH request 1 [ IDi N(INIT_CONTACT) IDr CPRQ(ADDR MASK DHCP DNS ADDR6 DHCP6 DNS6 DOMAIN) N(ESP_TFC_PAD_N) N(NON_FIRST_FRAG) SA TSi TSr N(MOBIKE_SUP) ]
06[CFG] looking for peer configs matching PUBLIC_IPV4[vpn.example.com]...CLIENT_IPV4[PRIVATE_CLASS_A_ADDRESS]
06[CFG] selected peer config 'conn-ios'
06[IKE] initiating EAP_IDENTITY method (id 0x00)
06[IKE] received ESP_TFC_PADDING_NOT_SUPPORTED, not using ESPv3 TFC padding
06[IKE] peer supports MOBIKE
06[IKE] authentication of 'vpn.example.com' (myself) with ECDSA-256 signature successful
06[IKE] sending end entity cert "CN=vpn.example.com"
06[IKE] sending issuer cert "C=US, O=Let's Encrypt, CN=R3"
06[ENC] generating IKE_AUTH response 1 [ IDr CERT CERT AUTH EAP/REQ/ID ]
06[ENC] splitting IKE message (2816 bytes) into 3 fragments
06[ENC] generating IKE_AUTH response 1 [ EF(1/3) ]
06[ENC] generating IKE_AUTH response 1 [ EF(2/3) ]
06[ENC] generating IKE_AUTH response 1 [ EF(3/3) ]
06[NET] sending packet: from PUBLIC_IPV4[4500] to CLIENT_IPV4[13549] (1236 bytes)
06[NET] sending packet: from PUBLIC_IPV4[4500] to CLIENT_IPV4[13549] (1236 bytes)
06[NET] sending packet: from PUBLIC_IPV4[4500] to CLIENT_IPV4[13549] (500 bytes)
11[JOB] deleting half open IKE_SA with CLIENT_IPV4 after timeout

iPhone users are connecting using the built-in VPN client using the following settings:

  • Type IKEv2

  • Description: VPN server

  • Server: vpn.example.com

  • Remote id: vpn.example.com

  • Local id: BLANK

  • Username and password authentication.

  • Username: user@site.example.com

  • Password: ItIsASecret

Does anyone know why the connection stalls for iOS users when it has loaded the conn-ios profile?

UPDATE And we have liftoff! :-)

As per advice from @ecdsa I have switched the certificate to a 2048-bit RSA certificate.

My Radius server gets called. User authentication succeeds and client gets assign ip-adresse. I am happy. :-)

My configuration for conn-ios is now:

  conn-ios : conn-defaults, eap-defaults {

    # Overriding defaults from 'conn-default'
    local {
      auth = pubkey
      certs = vpn-rsa.cer
      id = vpn.example.com
    }

    children {
      net {
        local_ts = 0.0.0.0/0, ::/0
      }

      esp_proposals = aes256-sha256
    }

    pools = IkeVPN-site-ipv4, IkeVPN-site-ipv6
    proposals = aes256-sha256-prfsha256-modp2048
  }

Everything else is as-is from my initial configuration.

  • There are no retransmits, so the most likely is that the client doesn't trust/support the server certificate. You use Let's Encrypt, which most clients should support. So the only thing I can think of is that the client has a problem with the ECDSA server certificate. Did you try with an RSA certificate? – ecdsa Jun 14 '21 at 09:48
  • Not in combination with iPhones, but it should be easy to test. However they output from log does say verification of certificate was successfull. See: `authentication of 'vpn.example.com' (myself) with ECDSA-256 signature successful`. – Lasse Michael Mølgaard Jun 14 '21 at 10:25
  • It would be strange that Lets Encrypt ECDSA does not work with VPN, as I do have iPhones and iPads using the same certificate when they are sending or receiving mail as my mail server is hosted on the same machine as my VPN. – Lasse Michael Mølgaard Jun 14 '21 at 10:58
  • The log message is from the server generating the signature (not verifying). That does not say anything about whether the client can verify it or not (you'd need to access the client log via Xcode for that). And the mail client is obviously a completely different piece of software than the VPN client, so you can't really compare the two. – ecdsa Jun 14 '21 at 13:41
  • Right. My biggest challenge debugging iPhone is that I not actually have an iPhone, so testning has been done by a friend remotely, who has basically only replied with "it works" or "don't work". Guess I have to do a bit over-the-shoulder debugging next time I meet my friend. – Lasse Michael Mølgaard Jun 14 '21 at 20:45
  • 1
    I'd try with an RSA certificate. The Apple clients evidently don't support [RFC 7427](https://datatracker.ietf.org/doc/html/rfc7427) (otherwise, you'd see a hash algorithm notify in `IKE_SA_INIT` messages) and in the base IKEv2 RFC the options for ECDSA are quite limited (specific curves and hash algorithms). So they might only accept/use it if configured explicitly in a [configuration profile](https://wiki.strongswan.org/projects/strongswan/wiki/AppleIKEv2Profile) (there is an option `CertificateType` that can be set to `ECDSA256`). – ecdsa Jun 15 '21 at 07:44
  • @ecdsa: And we have liftoff! :-) Can you please add an answer, so you can get the credit for correct answer? :-) – Lasse Michael Mølgaard Jun 15 '21 at 10:54

1 Answers1

0

As we can see in the log, the client doesn't support RFC 7427 (otherwise, hash algorithm notifies would get exchanged during IKE_SA_INIT), which defines flexible signature-based authentication.

While IKEv2 also supports ECDSA without that extension, RFC 4754 only added limited support for it (only the three NIST curves may be used and each has a specific hash algorithm assigned). So it's possible Apple clients only accept/use ECDSA if configured explicitly in a configuration profile (there is an option CertificateType that can be set to e.g. ECDSA256).

If using configuration profiles is not an option, the only alternative is to use RSA server certificates, at least until Apple implements support for RFC 7427 in their IKEv2 client.

ecdsa
  • 3,800
  • 12
  • 26
  • Thank you. The solution is for a school with 200+ users, so I wanted something that can be used with as little technical support for end users as possible. Hence the goal was to just tell them which server to connect to and what username and password to use. Anything beyond that is considered "too complicated" for end users. :-) – Lasse Michael Mølgaard Jun 15 '21 at 21:01