IKEv2 VPN server for Windows and Apple clients on Raspberry Pi

Table of contents
Preamble
The following tutorial did not claim to be fully comprehensive. It should only be seen as a framework to show the basic functions of an IPsec IKEv2 VPN server. It is intentionally limited to the onboard VPN clients in all OSes, cause they are included and there is no need to install any 3rd party VPN clients as its the case with e.g. Wireguard or OpenVPN.
Hence it has a close relationship with the forum pfSense / OPNsense Firewall VPN tutorial (see further links at the bottom). More or less every Unix based appliance uses the charon IPsec daemon as a foundation for IPsec.
Using IKEv2 onboard VPN clients on Windows and Apple always requires a server certificate. IKEv2 VPN clients use it to check the authenticity of the target VPN server to prevent being spoofed by a fake server.
It is not within the scope of this tutorial to be a fully basic knowledge tutorial for IPsec and PKI. The usage of a Raspberry Pi with Debian based Linux is only an example. Of course can this setup also be used with "bigger" hardware and different distros as well as with the famous free OpenWRT router firmware (strongswan- swanctl package).
A bit of Linux CLI knowledge and some basic network and PKI knowledge would be helpful to get familiar with the following configuration steps
A Raspberry Pi with ready installed OS-Lite version and SSH access with (e.g. PuTTY) is the starting point.
VPN server configuration
StrongSwan swanctl is a new portable command line utility for the IKE daemon charon. Its included since 5.2.0 and will replace the old starter syntax on a long term perspective.
To make Linux and here the Raspberry Pi IPsec capable, additional packages need to be installed with the APT package manager. This requires root user access rights (sudo su):
apt install strongswan strongswan-pki charon-systemd libcharon-extra-plugins
Also IPv4 forwarding (routing) needs to be activated and can be done editing the file (nano editor) /etc/sysctl.conf and changing the line
# Uncomment the next line to enable packet forwarding for IPv4
net.ipv4.ip_forward=1
If that step is completed continue with the CA and certificate setup...
CA setup and server certificate with StrongSwan PKI
As mentioned above, all the onboard VPN clients did a server certificate check to proof the servers authenticity. Hence it adds more security to the VPN and needs a small PKI infrastructure PKI. A CA is in a figurative sense an authority who issues an identiy card with a stamp (certificate) which can then be checked by the clients.
If there is an existing CA the only requirement is to issue another server certificate with that CA for the new RasPi server.
If no CA is active just follow the next steps to create one.
CA setup using StrongSwan PKI commands:
pki --gen --type rsa --size 2048 --outform pem > /etc/swanctl/private/raspica-key.pem
pki --self --ca --lifetime 3650 --in /etc/swanctl/private/raspica-key.pem --type rsa --dn "CN=RasPi CA" --outform pem > /etc/swanctl/x509ca/raspica-cert.pem
Setup server certificate:
pki --gen --type rsa --size 2048 --outform pem > /etc/swanctl/private/server-key.pem
pki --pub --in /etc/swanctl/private/server-key.pem --type rsa | pki --issue --lifetime 1825 --cacert /etc/swanctl/x509ca/raspica-cert.pem --cakey /etc/swanctl/private/raspica-key.pem --dn "CN=0a630187.nip.io" --san 0a630187.nip.io --flag serverAuth --flag ikeIntermediate --outform pem > /etc/swanctl/x509/server-cert.pem
Using an existing CA
If an exiting CA is active, the only need is to create a new, additional server certificate and export it together with the CA.
The following example shows it with a working CA on a pfSense/OPNsense firewall in the "Cert Manager" menu:
CA certificate and key export: (Menu "CA")
Server certificate and key export:: (Menu "Certificates")
Server is too exported with the "sun" icon (Mouseover) and the corresponting key with the "key" icon like with the above CA.
The server certificate can be safely erased afterwards from the CA, cause it is only needed on the VPN Server itself.
The exported certificate and key files can be moved to the server with a usb stick or via network copy using SCP tools like (e.g. WinSCP).
They need to be copied into the following server directories:
- All key files into: /etc/swanctl/private
- CA certificate into: /etc/swanctl/x509ca
- Server certificate into: /etc/swanctl/x509
All these certificates and keys can of course be generated with other tools of own choice, like OpenSSL or XCA as well.
The VPN enddevices (clients) only need the CA certificate to be imported.
StrongSwan configuration
The general StrongSwan configuration is placed in the directory /etc/swanctl/conf.d and needs to have a .conf suffix like vpn-server.conf.
This can quickly be done with a simple texteditor like nano. A single command like nano /etc/swanctl/conf.d/vpn-server.conf creates the file and the following configuration can be inserted with simply cut and paste. Never forget to save and exit with <ctrl o> und <ctrl x> (nano) !
It is useful to perhaps replace the example settings used here with individual ones.
- Replace PSKs with secret ones !
- Internal example VPN client network: 172.25.25.0 /24
- Local IP address on eth0 interface: 10.99.1.135 (DNS example: 0a630187.nip.io)
- DNS server IPs propagated automatically to clients at dialin: 172.16.7.254 and 10.99.1.254
- 2 VPN example users with username/passwd combination user/test123 and user2/user2
- Usernames/Passwords can not be used twice. (No multiple login with the same credentials, Parameter unique = replace). It can be allowed by simply omitting this parameter.
connections {
ikev2-mobile-defaults {
unique = replace
version = 2
proposals = aes256-sha256-modp2048,aes256-sha256-modp1024
send_cert = always
rekey_time = 0s
pools = pool-ipv4
dpd_delay = 300s
local_addrs = 10.99.1.135
remote_addrs = 0.0.0.0/0,::/0
local {
auth = pubkey
certs = server-cert.pem
id = fqdn:0a630187.nip.io
}
remote {
id = %any
auth = eap-mschapv2
eap_id = %any
}
children {
ikev2-mobile {
local_ts = 0.0.0.0/0
rekey_time = 0s
dpd_action = clear
esp_proposals = aes256-sha1-modp1024,aes256-sha256-modp2048,aes256-sha256-modp1024,aes256-sha384-modp1024
}
}
}
}
pools {
pool-ipv4 {
addrs = 172.25.25.0/24
dns = 172.16.7.254,10.99.1.254
}
}
secrets {
eap-1 {
id = user
secret = "test123"
}
eap-2 {
id = user2
secret = "user2"
}
}
swanctl -q
(It happens also automatically after every reboot) The daemon acknowledges this with
root@raspi:/home/pi# swanctl -q
loaded certificate from '/etc/swanctl/x509/RasPiServer.crt'
loaded certificate from '/etc/swanctl/x509ca/pfsenseCA.crt'
loaded RSA key from '/etc/swanctl/private/RasPiServer.key'
loaded RSA key from '/etc/swanctl/private/pfsenseCA.key'
loaded eap secret 'eap-1'
loaded eap secret 'eap-2'
no authorities found, 0 unloaded
loaded pool 'pool-ipv4'
successfully loaded 1 pools, 0 unloaded
loaded connection 'ikev2-mobile-defaults'
successfully loaded 1 connections, 0 unloaded
With every configuration change, a new swanctl -q is mandatory to activate the changes !
With these steps the server is ready and next is the VPN client setup...
Windows and Apple VPN client configuration
Usually Windows, Apple and all smartphones/tablets have 2 onboard VPN clients. One based on the L2TP VPN protocoll and on for native IPsec in Tunnel Mode with IKEv2. Here we deal with the latter one.
One caveat is the Microsoft VPN client, which uses weak ciphers in the default settings. When a higher security is required, tweaking with Powershell or a Registry setup is mandatory here. Apple uses stronger default security in their clients (AES256,SHA256,DH14) and is not affected. Btw. often the reason why Windows can connect but not Apple due to a higher cipher request which fail in the VPN client negotiation.
In a Windows setup that support the default, out-of-the-box settings without changes, SHA1 Hashing and DH Group 2 support need to be activated. It can be seen in the above StrongSwan configuration unter (proposals = ...).
Take note that ALL clients need to have the CA root certificate imported first !
The import into the trusted root certificates folder can be done under Windows with a simple doubleclick or via the certificate manager. Mac OS a doubleclick and set the certificate to always trust.
On mobile devices the easiest way is to send it via email attachment or USB and doubleclick it. More details can be found for Windows and Apple in the firewall tutorial.
Windows VPN client
Attention !: Patch KB5010793 installation is mandatory !! See here ! The Windows client setup via GUI is pretty easy and can be seen here:
Type IKEv2, Username/Password. Automatic deployment of username/passwd can be set with the checkmark in the VPN adapter attributes:
Also if the client should use the tunnel for his default gateway (Gateway Redirect) or should only reach the remote networks (Split Tunneling).

Windows client: Increasing VPN security settings
The following topic is only for users who need to increase their Windows VPN client security. If the defaults are sufficient this step can be ignored.
The easiest option is to tweak the specific VPN connection with a Powershell command:
Set-VpnConnectionIPsecConfiguration -ConnectionName "RasPi" -AuthenticationTransformConstants None -CipherTransformConstants AES256 -EncryptionMethod AES256 -IntegrityCheckMethod SHA256 -DHGroup Group14 -PfsGroup None -PassThru -AllUserConnection
Note that the parameter -ConnectionName "RasPi" needs to match exactly the VPN connection name ! (Here the firewall turorial has more information for the VPN customization via Powershell).
Another alternative to gain higher VPN security is the Windows Registry:
- 1.) Edit Registry with regedit or use GPO: HKLM\SYSTEM\CurrentControlSet\Services\RasMan\Parameters\
- 2.) Create a new DWORD value: NegotiateDH2048_AES256
- 3.) DWORD value to 1 or 2
Please note:
If the Windows Registry has this VPN setting (DWORD), Windows will always use these stronger ciphers ! Hence it could effect existing VPN connections which perhaps use weaker or default ciphers !
The Powershell option is more flexible here, cause it can individually be configured on a per connection basis.
Apple VPN client
Apple uses strong ciphers by default. Here just the login credentials and the certificate DN or --san name (remote ID) are needed for access:
Mobile enddevices
As mentioned before, certificate and key files can be send by email attachment or USB. In case a larger amount of Apple mobile devices need to be configured the Apple Configurator 2 eases this step with a simple template which can be created and distributed automatically.
Jumphost setup with vserver
One exampe of a practical live setup is a jumphost design for DS-Lite customer connections. Due to DS-Lite there is no possibility to realize IPv4 connection from remote. All those connections stuck and are blocked at the provider CGN gateway. IPv6 is of course not effected DS-Lite is related to IPv4 only !
As a workaround a home IPsec VPN router like the popular AVM FritzBox, can establish a VPN connection with IPv4 to a public jumphost (vserver with StrongSwan) to connect the local LAN network. From the "other side" the server is conntacted via IPv4 from the VPN clients. The server acts more or less like a relay station to access the local LAN network from remote and avoid DS-Lite obstacles.
That way DS-Lite users can get rid of the CGN limitations or unsafe and dangerous public VPN companies.
Just to make sure: This design is ONLY useful for private home connections based on DS-Lite ! All (normal) connections with a public IPv4 on the WAN/xDSL router port can of course use the simple design above.
StrongSwan Jumphost configuration
The Strongswan configuration needs to be modified for this setup by adding the FritzBox connection. (For the FritzBox settings special thanks to @colinardo !)- Replace PSKs with safe ones !
- Replace vServer IP <server_hoster_ip> and FQDN <server_FQDN> with personal IP and FQDN values
- In case the AVM FritzBox uses a different local LAN as 192.168.178.0/24 it needs to be changed under "remote_ts = x.y.z.h"
connections {
fritzbox {
local_addrs = <server_hoster_ip>
remote_addrs = 0.0.0.0/0
local {
auth = psk
id = <server_hoster_ip>
}
remote {
auth = psk
id = keyid:strongswan@fritz.box
}
children {
net {
local_ts = 172.25.25.0/24
remote_ts = 192.168.178.0/24
ipcomp = no
esp_proposals = aes256-sha1-modp1024
rekey_time = 60m
}
}
version = 1
fragmentation = yes
proposals = aes256-sha1-modp1024
rekey_time = 60m
dpd_delay=0s
encap=no
}
ikev2-mobile-defaults {
unique = replace
version = 2
proposals = aes256-sha256-modp2048,aes256-sha256-modp1024
send_cert = always
rekey_time = 0s
pools = pool-ipv4
dpd_delay = 300s
local_addrs = <server_hoster_ip>
remote_addrs = 0.0.0.0/0,::/0
local {
auth = pubkey
certs = vServer.crt
id = fqdn:<server_FQDN>
}
remote {
id = %any
auth = eap-mschapv2
eap_id = %any
}
children {
ikev2-mobile {
local_ts = 0.0.0.0/0
rekey_time = 0s
dpd_action = clear
esp_proposals = aes256-sha1-modp1024,aes256-sha256-modp2048,aes256-sha256-modp1024,aes256-sha384-modp1024
}
}
}
}
pools {
pool-ipv4 {
addrs = 172.25.25.0/24
dns = 172.16.7.254,10.99.1.254
}
}
secrets {
eap-1 {
id = user
secret = "test123"
}
eap-2 {
id = user2
secret = "user2"
}
ike-3 {
id = keyid:strongswan@fritz.box
secret = "test1234"
}
}
FritzBox VPN configuration file
The corresponding FritzBox configuration file looks like this. It can be loaded into the FritzBox over the GUI.- Replace <server_hoster_ip> with the live vServer IP or FQDN
vpncfg {
connections {
enabled = yes;
editable = no;
conn_type = conntype_lan;
name = "StrongSwan";
always_renew = yes;
reject_not_encrypted = no;
dont_filter_netbios = yes;
localip = 0.0.0.0;
local_virtualip = 0.0.0.0;
remoteip = <server_hoster_ip>;
remote_virtualip = 0.0.0.0;
localid {
key_id = "strongswan@fritz.box";
}
remoteid {
ipaddr = <server_hoster_ip>;
}
mode = phase1_mode_idp;
phase1ss = "all/all/all";
keytype = connkeytype_pre_shared;
key = "test1234";
cert_do_server_auth = no;
use_nat_t = yes;
use_xauth = no;
use_cfgmode = no;
phase2localid {
ipnet {
ipaddr = 192.168.178.0;
mask = 255.255.255.0;
}
}
phase2remoteid {
ipnet {
ipaddr = 172.25.25.0;
mask = 255.255.255.0;
}
}
phase2ss = "esp-all-all/ah-none/comp-all/pfs";
accesslist = "permit ip any 172.25.25.0 255.255.255.0";
}
ike_forward_rules = "udp 0.0.0.0:500 0.0.0.0:500",
"udp 0.0.0.0:4500 0.0.0.0:4500";
}
Links with further information
Tutorial in 🇩🇪:
https://administrator.de/contentid/1754377434
Basic Raspberry Pi setup:
https://administrator.de/contentid/191718
pfSense/OPNsense Zertifikats gesichertes IKEv2 VPN für mobile Benutzer mit bordeigener VPN Software:
https://administrator.de/contentid/337198
StrongSwan command documentation:
https://wiki.strongswan.org/projects/strongswan/wiki/Swanctlconf
Windows 10: Schneller VPN Aufbau mit einem Mausklick:
https://www.heise.de/ct/ausgabe/2017-19-VPN-und-Remote-Desktop-Verbindun ...
Microsoft Power Shell VPN command syntax:
https://docs.microsoft.com/en-us/powershell/module/vpnclient/add-vpnconn ...
Apple iOS Configurator 2:
https://support.apple.com/apple-configurator
Please also mark the comments that contributed to the solution of the article
Content-Key: 1769120412
Url: https://administrator.pro/contentid/1769120412
Printed on: May 20, 2022 at 12:05 o'clock
1 Comment