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 the192.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 proposals
and 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: [email protected]
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.
authentication of 'vpn.example.com' (myself) with ECDSA-256 signature successful
.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 (there is an optionCertificateType
that can be set toECDSA256
).