Support for per-CPU SAs (RFC 9611)
Support for per-CPU SAs (RFC 9611) has been added. This allows to negotiate separate Child SAs with the same traffic selectors for each local CPU, in order to improve the performance by avoiding to have to synchronize state (sequence numbers, counters etc.) between CPU cores, which is necessary if a single SA is shared between them. The Linux kernel supports this extension since 6.13.
The new per_cpu_sas
setting, which requires start_action=trap
to work, enables the installation of special trap policies that instruct the kernel to consider the CPU from which an outbound packet originates. Individual acquires are triggered and per-CPU SAs are then negotiated with the peer. An initially created fallback SA, which has no CPU assigned, handles outbound traffic while CPU-specific SAs are negotiated.
Note that just enabling per-CPU SAs is not enough. It will require careful configuration of the system for best performance. Such as Receive Side Scaling (RSS) for inbound traffic, to distribute the packets between NIC queues and CPU cores, and possibly process pinning for outbound traffic. Please refer to the documentation for details.
Support for IP-TFS's AGGFRAG Mode (RFC 9347)
Basic support for the new AGGFRAG mode has been added. This mode was defined as part of IP-TFS (RFC 9347), which aims to provide Traffic Flow Confidentiality (TFC) by obscuring the size and frequency of IP traffic through fixed-size ESP packets sent at a constant rate. The Linux kernel supports the new mode since 6.14. However, IP-TFS is not yet supported.
The mode itself is similar to tunnel mode, but allows aggregating small IP packets into single ESP packets and fragmenting large IP packets into multiple ESP packets. It's enabled via mode = iptfs
. Several global settings under charon.iptfs
allow fine-tuning of the kernel's behavior. Please refer to the documentation for details.
Matching Identities Against Regular Expressions
In addition to the already available basic wildcards, such as *.strongswan.org
, POSIX regular expressions are now supported to match remote identities (e.g. configured in remote.id
or as identities of shared secrets). Such identities must start with an explicit type prefix, followed by a caret character (^
), and end with a dollar sign ($
) to indicate an anchored pattern. Regular expressions are always matched case insensitive against the string representation of other identities. However, the type must match as well.
Examples:
email:^(moon|sun)@strongswan\.org$
matchesmoon@strongswan.org
orsun@strongswan.org
fqdn:^vpn[0-9]+\.strongswan\.org$
matches e.g.vpn1.strongswan.org
orvpn42.strongswan.org
but notvpn.strongswan.org
"asn1dn:^.*CN=.+\\.strongswan\\.org$"
(note that\
has to be escaped because the identity is defined in double quotes)
The last identity above matches any DN that ends with CN=
followed by anything that ends with.strongswan.org
, so e.g. "C=CH, O=strongSwan Project, CN=moon.strongswan.org"
. But because .+
literally matches any non-empty string, it also matches a DN such as "C=CH, O=strongSwan Project, CN=sun, E=sun@internal.strongswan.org"
.
So make sure to be as specific as possible when writing your regular expressions and be sure to test them.
Switch Configurations Based on EAP-Identities
Previously, an EAP-Identity exchange was only initiated if remote.eap_id=%any
was configured. Any other value was just statically configured and used locally during the EAP method. Matching configurations against EAP-Identities required a workaround via a dummy config that triggered the exchange but had an unused group assigned to force a late switch to other configs (see e.g. this discussion). This was not ideal and didn't allow to e.g. select a different EAP method based on the identity.
With this release, any value configured in remote.eap_id
will trigger an EAP-Identity exchange. If the received identity doesn't match the configuration, an alternative with a matching identity is searched (wildcards and regular expressions are supported for that match, so the behavior for %any
doesn't change as that matches any identity). Note that there is currently no "best" match. The configs are evaluated based on the order returned from the initial config lookup. So configs with more specific identities should be defined before any potential fallback config.
An example can be seen in the ikev2/rw-eap-id-switch test scenario. Depending on the EAP-Identity, moon authenticates the clients either with EAP-TLS or EAP-MD5.
Support for Narrowing With Trap Policies
On Linux, the sequence number from an acquire is now used when installing the corresponding Child SA. This allows handling narrowing properly by changing the reqid based on the narrowed traffic selectors and still removing the temporary state in the kernel so further acquires can get triggered.
An example of this can be seen in the ikev2/net2net-route-narrow test scenario. Based on the traffic selector from the triggering packet, moon selects a different child config and narrows the traffic selectors accordingly.
Also necessary were changes that cause the negotiated traffic selectors to get reused during rekeying/recreation/reauthentication, so narrowed selectors won't revert to the wider configured ones because there won't be any information from a triggering packet anymore to perform the narrowing again. The test scenario illustrates this as well by initiating a Child SA rekeying and a reauthentication.
Default IPsec Proposals With Optional PFS
Similar to the default IKE proposal, all supported key exchange methods are now added to the default ESP/AH proposals. However, they are made optional by also including none
. This enables PFS with peers that use the same or have KE methods non-optional in their proposals, while still allows accepting peers that use the previous non-KE default proposals.
Please note that some peers might have problems with such proposals. For instance, Windows clients that are not configured for PFS. In that case, configuring proposals without KE methods might be necessary.
Other Notable Features and Fixes
- ML-KEM is now supported via OpenSSL 3.5+.
- The
wolfssl
plugin is now compatible with wolfSSL's FIPS module. - GRO for ESP is enabled for the NAT-T UDP sockets, which can improve performance when the
esp4|6_offload
modules are loaded on Linux 6.7+. Please refer to the docs for details. Note that there was a kernel bug if the option is enabled but the modules are not loaded, causing UDP-encapsulated ESP packets to get dropped silently. Two fixes (e3fd057776, 3ac9e29211) have been submitted/applied that should get backported to supported kernels. - The VPN connection in NetworkManager is now marked as persistent, so NetworkManager won't terminate the
charon-nm
daemon if the network connectivity changes (e.g. interfaces go down/up), which obviously prevented the daemon from updating the connection or reconnecting automatically. - The
libsoup
plugin has been migrated to libsoup 3, libsoup 2 is not supported anymore. - The long defunct and limited
uci
plugin for OpenWrt has been removed. - The usage output for the
swanctl
andpki
commands has been streamlined (less indentation, print description for individual commands, print errors at the end of the output etc.). - The log messages by
watcher_t
are now logged in a separate new log group (wch
) instead of thejob
group.