Confusion Regarding Setting Up IKEv2 VPN Service with StrongSwan Using IPsec and Swanctl

Confusion Regarding Setting Up IKEv2 VPN Service with StrongSwan Using IPsec and Swanctl

I hope you're all doing well. I'm not very confident in my English skills, so I used GPT for translation. Please forgive me if there are any grammar mistakes.

I'm quite new to OpenWRT, and I'm trying to set up a simple IKEv2 VPN service by following the official documentation and some other resources I've found. My goal is to be able to access my home network from anywhere.
I'm having some problems. When I set up the VPN service using IPsec, everything seems to be working fine, I can access other computers on my home network through the VPN. However, when I attempt to set it up using swanctl, I can access the internet but I can't seem to reach the other computers on my home network.
Although I've achieved my goal by configuring it through IPsec, I still want to know what's missing in the configuration with swanctl.
Thank you, everyone.

The current version being used and the configuration information are as follows:
version: openwrt 22.03.5 , strongswan 5.9.5-13
package: strongswan-full strongswan-mod-kernel-libipsec kmod-tun

shared configuration

/etc/strongswan.conf

charon {
        dns1 = 192.168.5.1
        load_modular = yes
        plugins {
                include strongswan.d/charon/*.conf
        }
}

/etc/config/network

config interface 'loopback'
        option device 'lo'
        option proto 'static'
        option ipaddr '127.0.0.1'
        option netmask '255.0.0.0'

config device
        option name 'br-lan'
        option type 'bridge'
        list ports 'eth0'
        list ports 'eth1'
        option ipv6 '0'

config interface 'lan'                
        option device 'br-lan'
        option proto 'static'
        option ipaddr '192.168.5.1'
        option netmask '255.255.255.0'
        option ip6assign '60'
        list dns '223.5.5.5'
        list dns '119.29.29.29'

config interface 'wan'
        option proto 'pppoe'
        option device 'iptv.1'
        option username 'xxx'
        option password 'xxx'
        option ipv6 'auto'
        option peerdns '0'
        list dns '223.5.5.5'
        list dns '119.29.29.29'

config device
        option type 'bridge'
        option name 'iptv'
        list ports 'eth2'
        list ports 'eth3'

config bridge-vlan
        option device 'iptv'
        option vlan '1'
        list ports 'eth3'

config bridge-vlan
        option device 'iptv'
        option vlan '45'
        option local '0'
        list ports 'eth2'
        list ports 'eth3:t'

/etc/config/firewall

config defaults
        option input 'ACCEPT'
        option output 'ACCEPT'
        option forward 'REJECT'
        option synflood_protect '1'

config zone
        option name 'lan'
        option input 'ACCEPT'
        option output 'ACCEPT'
        option forward 'ACCEPT'
        list network 'lan'

config zone
        option name 'wan'
        option input 'REJECT'
        option output 'ACCEPT'
        option forward 'REJECT'
        option masq '1'
        option mtu_fix '1'
        list network 'wan'

config forwarding
        option src 'lan'
        option dest 'wan'

config rule                                     
        option name 'Allow-IPSec-ESP'           
        option src 'wan'                        
        option proto 'esp'                      
        option target 'ACCEPT'                  
                                                
config rule                                     
        option name 'Allow-ISAKMP'              
        option src 'wan'                        
        option dest_port '500'                  
        option proto 'udp'                      
        option target 'ACCEPT'                  
                                                
config rule                                     
        option name 'Allow-IPSec-NAT-T'         
        option src 'wan'                        
        option dest_port '4500'                 
        option proto 'udp'                      
        option target 'ACCEPT'                  
                                                
config rule                                     
        option name 'Allow-IPSec-Auth-Header'   
        option src 'wan'                        
        option proto 'ah'                       
        option target 'ACCEPT'

ipsec

/etc/config/network

config interface 'ipsec'                       
        option device 'ipsec0'
        option proto 'none'
        option defaultroute '0'
        option peerdns '0'  
        option ipv6 '0'

/etc/config/firewall

config zone                                     
        option name 'vpn'                       
        list network 'ipsec'                    
        option input 'ACCEPT'                   
        option output 'ACCEPT'                  
        option forward 'ACCEPT'                 
        option masq '1'                         
        option mtu_fix '1'                      
                                                
config forwarding                               
        option src 'vpn'                        
        option dest 'lan'                       
                                                
config forwarding                               
        option src 'lan'                        
        option dest 'vpn'                       
                                                
config forwarding                               
        option src 'vpn'                        
        option dest 'wan'

/etc/ipsec.conf

config setup

conn %default
        keyexchange=ikev2
        ike=aes256-aes128-sha1-sha256-modp2048-modp3072
        esp=aes128-aes256-sha256-modp3072-modp2048,aes128-aes256-sha256
        left=%any
        leftauth=pubkey
        leftid=ddns.adi291.com
        leftsubnet=0.0.0.0/0;::/0
        leftcert=serverCert_ddns.adi291.com.pem
        leftsendcert=always
        right=%any
        rightsourceip=192.168.5.160/29
        rightdns=192.168.5.1
        eap_identity=%identity
        auto=add

conn rwPUBKEY
        rightauth=pubkey
        rightcert=clientCert_Adi.pem

/etc/ipsec.secrets

: RSA serverKey_ddns.adi291.com.pem

swanctl

/etc/swanctl/common.conf

local_addrs  = 0.0.0.0/0,::/0
remote_addrs = 0.0.0.0/0,::/0
local {
        auth = pubkey
        certs = serverCert_ddns.adi291.com.pem
        id = ddns.adi291.com
}
children {
        ikev2clients {
                local_ts  = 0.0.0.0/0;::/0
                esp_proposals = default
        }
}
pools = strongswanippool
unique = never
version = 2
proposals = default

/etc/swanctl/swanctl.conf

connections {
        rw-pubkey {
                include ./common.conf
                remote-pubkey {
                        auth = pubkey
                        certs = clientCert_Adi.pem
                }
                send_certreq = no
        }
}

secrets {
        rsa- {
                filename="serverKey_ddns.adi291.com.pem"
        }
}

pools {
        strongswanippool {
                addrs = 192.168.5.160-192.168.5.166
                #dns = 192.168.5.1
        }
}

include conf.d/*.conf

include /var/swanctl/swanctl.conf

/etc/config/firewall

config rule                    
        option name 'AllowIPsec2WAN'
        list proto 'all'       
        option src 'wan'             
        option dest 'wan'  
        option target 'ACCEPT'   
        option enabled '0'

Do you have a particular reason to prefer IKEv2 over (e.g.) wireguard? While there's nothing wrong about strongswan and IKEv2, wireguard tends to to be easier to set up and operate - so if you don't need to integrate into an existing VPN or have other reasons to use it, wireguard might be easier (if so, start fresh, reset and configure wireguard).

--
CA and certificate handling for IPsec or OpenVPN is not trivial, wireguard's public-/ private key handling is a lot easier for reasonably small deployments.

Because I'd prefer not to use extra client software. maybe in the future I'll try using WireGuard, could you recommend some links with guides on how to use it? Thank you so much.

Drop it, use libreswan. It is much easier to set up. Use official documentation from https://libreswan.org/wiki/Configuration_examples

StrongSWAN documentation from OpenWRT is a bit confusing. It should be devided into two StrongSWAN before 22.03 and StrongSWAN 22.03+ just for the sake of convenience.

Use PSK+XAUTH, it is the same level of complexity as Wireguard. The only thing which WG provides in extra is QR code... which doesn't work (in OpenWRT) as intended to be.

The official article mentions that libreswan is no longer supported and cannot be installed after 19.07.9.
libreswan vpn

Documentation is old...

opkg list | grep libreswan

Thanks! Well, I suppose I placed too much trust in the accuracy of the official documentation...

However, at the moment, I've successfully set up the VPN service using StrongSwan's IPsec, and everything is functioning well. The issue arises when I try to configure it using swanctl. I'm still eager to find out the underlying reasons for this inconsistency.

1 Like

@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..

1 Like

Thank you for your response. In the days following my post, I believe I've successfully configured and am able to connect and use it normally. However, due to finding the management a bit cumbersome, I eventually switched to WireGuard.

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.