@adi291 I just spent a few days researching and working on this very topic.. and here are my thoughts and experiences:
My problems started because a.) an existing road-warrior vpn setup (unrelated to OpenWRT) that i had and wanted to port to my shiney new OpenWRT setup was created using an ansible-based project on an old linux-VM i was running for router-duties before i decided to adopt/migrate to OpenWRT..
while that made my old (non-OpenWRT) setup work flawlessly, i didn't really understand how everything was working (maybe not a bad thing), until now when i (needfully) got my hands dirty
and b.) that still-working config (and 90% of the damn online examples... like this excellent one that i used for cert creation) are all based on the legacy /etc/ipsec.conf setup style, which seems has been deprecated in OpenWRT in favor of the newish swanctl.conf style-setup (for a "brief" (as if anything IPSec-related can be) overview on the new syntax, read this blog post).
But I finally saw the light the end of the tunnel when i came across this doc which was a game-changer, and also later found this conversion script from one of the StrongSwan contributors.
This at least helped me understand what the end result should be that the swanctl init script was generating (and creating the new-style /var/swanctl/swanctl.conf
).. which allowed me to work my way backwards, and discover where the gaps in existing support still might be (i'll probably open a PR per the below mentions, or at least a github issue).
Here's the /etc/config/ipsec file i ultimately ended up settling on, with comments on what additional work/considerations are needed
config 'ipsec'
option 'zone' 'vpn_clients'
list 'interface' 'wan'
option 'debug' '1' # to really understand strongswan/ipsec, i recommend: https://youtu.be/D-Esrw8wxA4
config 'remote' 'all_remote_ikev2'
option 'enabled' '1'
option 'gateway' 'any' # clients from anywhere
option 'authentication_method' 'pubkey' # settled on pubkey, examples used eap-tls but no support in swanctl init script :-(
option 'ca_cert' 'ca.crt' # goes in /etc/swanctl/x509ca/
option 'local_key' 'vpn-server_my_domain.key' # goes in /etc/swanctl/private/
option 'local_cert' 'vpn-server_my_domain.crt' # goes in /etc/swanctl/x509/
option 'local_identifier' 'vpn-server.my.domain' # is the CN (common name) in the cert, to view: openssl x509 -in /path/to/file.cert -noout -subject
option 'local_sendcert' 'always' # swanctl init script needs to be patched to support this, ugh
option 'remote_sendcert' 'no' # ditto
option 'force_encapsulation' 'yes' # ditto
option 'dpddelay' '300s' # dpdaction must be set to non-default value in below tunnel section
option 'fragmentation' 'yes'
option 'mobike' '1'
list 'crypto_proposal' 'ike_proposal'
list 'tunnel' 'esp_tunnel'
list 'pools' 'ipv4pool'
list 'pools' 'ipv6pool'
config 'crypto_proposal' 'ike_proposal'
option 'encryption_algorithm' 'aes256gcm16'
option 'hash_algorithm' 'prfsha512' # init script needs patching per - https://github.com/openwrt/packages/issues/22245
option 'dh_group' 'ecp384'
config 'tunnel' 'esp_tunnel'
list 'local_subnet' '0.0.0.0/0'
list 'local_subnet' '::/0'
option 'startaction' 'none'
option 'if_id' '357' # has an /etc/config/network component, based on official swanctl uci openwrt-wiki
option 'dpdaction' 'clear' # must be set in order for above IKEv2 "remote" block to honor dpddelay setting
list 'crypto_proposal' 'esp_proposal'
config 'crypto_proposal' 'esp_proposal'
option 'encryption_algorithm' 'aes256gcm16'
option 'dh_group' 'ecp384'
config 'pools' 'ipv4pool' # undocumented in wiki, added only in https://github.com/openwrt/packages/commit/08a0f7bb94f5577d5c04dcd8e3691e8ee69f76f9
option 'addrs' '172.18.18.16/28'
list 'netmask' '255.255.255.240'
list 'dns' '172.18.18.18'
config 'pools' 'ipv6pool' # ditto re undocumented
option 'addrs' '2xxx:xxxx:xxxx:1818:ffff::/112' # nothing larger than strangely a /97 is supported, otherwise errors such as: charon[6812]: 06[CFG] virtual IP pool too large, limiting to 2xxx:xxxx:xxxx:1818::/97
list 'dns' '2xxx:xxxx:xxxx:1818::'
here's the relevant /etc/config/network bits
config interface 'xfrm0'
option ifid '357'
option tunlink 'wan'
option mtu '1438'
option zone 'vpn_clients'
option proto 'xfrm'
option multicast 'true'
option delegate '0'
config interface 'xfrm0_s'
option proto 'static'
option device '@xfrm0'
list ipaddr '172.18.18.30/28' # each client get IPs sequentially, so here we pick very last IP for their default gateway so as not to clash w/ client's
option delegate '0'
option ip6assign '64'
option ip6ifaceid '::'
option ip6hint '1818'
list ip6class 'wan_6'
and the relevant /etc/config/firewall sections
config zone
option name 'vpn_clients'
option input 'ACCEPT'
option output 'ACCEPT'
option forward 'ACCEPT'
option mtu_fix '1' # not sure if needed
list network 'xfrm0'
list network 'xfrm0_s'
config forwarding
option src 'vpn_clients'
option dest 'wan'
# see: https://forum.openwrt.org/t/traffic-is-dropped-for-ipsec-with-firewall4/139777/2
config include
option type 'nftables'
option path '/etc/fwuser.nft'
option position 'chain-pre'
option chain 'input_wan'
config include
option type 'nftables'
option path '/etc/fwuser.nft'
option position 'chain-pre'
option chain 'forward_wan'
(the above bit parts of the ipsec config is from the official wiki, however i didn't set up the route section, yet it seems to work just fine.. though i did use this solution re nft/fw4 support).
oh and here's the patch of the swanctl init script you can git-am
From d5fa0f70897d7a9afe3257d72e779365e1d2371c Mon Sep 17 00:00:00 2001
From: aleks-mariusz <a+git-commit@alek.cx>
Date: Fri, 29 Sep 2023 13:28:44 +0100
Subject: [PATCH] strongswan: patching swanctl init script to support other swanctl config and fix a bug
for the details of what needs to be patched, see the /etc/config/ipsec block in this post:
https://forum.openwrt.org/t/confusion-regarding-setting-up-ikev2-vpn-service-with-strongswan-using-ipsec-and-swanctl/1695
also for the bug, see this: https://github.com/openwrt/packages/issues/22245
---
net/strongswan/files/swanctl.init | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/net/strongswan/files/swanctl.init b/net/strongswan/files/swanctl.init
index dcc065d..ed99620 100644
--- a/net/strongswan/files/swanctl.init
+++ b/net/strongswan/files/swanctl.init
@@ -199,12 +199,6 @@ config_ike_proposal() {
config_get dh_group "$conf" dh_group
config_get prf_algorithm "$conf" prf_algorithm
- # check for AEAD and clobber hash_algorithm if set
- if is_aead "$encryption_algorithm" && [ -n "$hash_algorithm" ]; then
- fatal "Can't have $hash_algorithm with $encryption_algorithm"
- hash_algorithm=
- fi
-
[ -n "$encryption_algorithm" ] && \
crypto="${crypto:+${crypto},}${encryption_algorithm}${hash_algorithm:+-${hash_algorithm}}${prf_algorithm:+-${prf_algorithm}}${dh_group:+-${dh_group}}"
}
@@ -430,6 +424,8 @@ config_remote() {
local auth_method
local keyingtries
local dpddelay
+ local local_sendcert
+ local remote_sendcert
local inactivity
local keyexchange
local fragmentation
@@ -452,6 +448,9 @@ config_remote() {
config_get local_ip "$conf" local_ip "%any"
config_get keyingtries "$conf" keyingtries "3"
config_get dpddelay "$conf" dpddelay "30s"
+ config_get encap "$conf" force_encapsulation "no"
+ config_get send_cert "$conf" local_sendcert "ifasked"
+ config_get send_certreq "$conf" remote_sendcert "yes"
config_get inactivity "$conf" inactivity
config_get keyexchange "$conf" keyexchange "ikev2"
config_get fragmentation "$conf" fragmentation "yes"
@@ -568,6 +567,9 @@ config_remote() {
swanctl_xappend2 "proposals = $ike_proposal"
[ -n "$dpddelay" ] && swanctl_xappend2 "dpd_delay = $dpddelay"
+ [ -n "$encap" ] && swanctl_xappend2 "encap = $encap"
+ [ -n "$send_certreq" ] && swanctl_xappend2 "send_certreq = $send_certreq"
+ [ -n "$send_cert" ] && swanctl_xappend2 "send_cert = $send_cert"
[ "$keyingtries" = "%forever" ] && swanctl_xappend2 "keyingtries = 0" || swanctl_xappend2 "keyingtries = $keyingtries"
swanctl_xappend1 "}"
--
1.8.3.1
...
and finally If you need help configuring any apple-based clients, to create a mobileconfig is not too difficult, again refer to this excellent guide.. though i should mention that swanctl currently lacks support for setting authentication_method
to eap-tls, so you should NOT check the "EAP" checkbox ON (like in that guide), my old high-sierra macbook still connects fine with the older pubkey auth method.. Note: If you need an older version of Apple's Configurator 2 (thanks Apple for removing support older OS.. grumble grumble), you can try your luck with this.. or if you don't trust a random person's copy of an apple-app (i did, but i wouldn't recommend it for security reasons), try your luck the hard way.
Anyway things are working semi-ok (VPN client can reach the internet, that's the hardest bit as it involves layer-2/layer-3 routing/dns/forwarding and firewalls etc.. oh my!), though as i mentioned above i had to patch the /etc/init.d/swanctl
script to support some of the extra options my apple clients supposedly need.. But at least configuring the client side is super easy and requires no extra apps..
One thing i didn't get working is DHCP to work correctly for VPN clients off the XFRM interface, but i don't have enough VPN clients to be bothered that much by just giving them a static IP pool (both IPv4 and IPv6).. plus again the swanctl init script doesn't handle setting a dhcp-based pool correctly (the connection's pool attribute can point to a different pool-based section, or can just be a special keyword dhcp.. the init script will always try to create a separate pool named dhcp instead
Hope this helps other people! The above post was extracted from a longer post i did about my overall goals with the router, if you're interested..