Share via

Azure P2S IKEv2 VPN (Basic SKU) with certificate authentication won't connect on Fedora 44 with SELinux enforcing (NetworkManager-strongswan)

Sepehr Soltanieh 45 Reputation points
2026-05-22T07:04:37.71+00:00

I'm trying to set up a client using StrongSwan + GNOME Settings (NetworkManager / nmcli) for my Azure Point-to-Site Basic SKU IKEv2 VPN on a fresh Fedora 44 install, without disabling SELinux. I'd like the method to stay as close as possible to the official Microsoft guide:

https://learn.microsoft.com/en-us/azure/vpn-gateway/point-to-site-vpn-client-certificate-ike-linux

Also found this older Fedora discussion that looks related but doesn't quite match my symptoms:

https://discussion.fedoraproject.org/t/after-upgrade-to-fedora-32-strongswan-vpn-issue/70501

The same VPN connects fine from Windows, macOS, and from my previous Ubuntu install on the same hardware.

My environment

  • Fedora 44 Workstation, Linux kernel 7.0.9-202.fc44, SELinux Enforcing
  • NetworkManager 1.56.0-1.fc44, NetworkManager-strongswan 1.6.0-12.fc44, strongswan 6.0.4-2.fc44
  • update-crypto-policies --showDEFAULT
  • VPN: Azure VPN Gateway, Basic SKU, IKEv2 only, certificate auth (self-signed root CA uploaded to Azure; X.509 client cert + 2048-bit RSA PKCS#8 key, unencrypted)

To anyone who might want to mention that the Azure Basic SKU VPN Gateway won't support the IKEv2 protocol, please have a look here; unfortunately there are many contradictory documentation on Microsoft's resources.

Also, if you're curious and want to set it up for yourself and are following this guide but can't see the IKEv2 protocol option on Azure Portal, use this workaround.

What I did

sudo dnf install strongswan tpm2-abrmd strongswan-charon-nm NetworkManager-strongswan-gnome

install -m 0755 -Z -d ~/.cert
install -m 0755 -Z -d ~/.cert/myvpn
install -m 0644 -Z "/path/to/downloaded/azure/vpnclientconfiguration/Generic/VpnServerRoot.cer_0" ~/.cert/myvpn/VpnServerRoot.cer
install -m 0644 -Z "/path/to/generated/azure/vpn/client/Cert.pem" ~/.cert/myvpn/client-cert.pem
install -m 0600 -Z "/path/to/generated/azure/vpn/client/Key.pem" ~/.cert/myvpn/client-key.pem
sudo restorecon -RvF ~/.cert

Result:

$ ls -laZR ~/.cert
.cert:
drwxr-xr-x.  3 myuser myuser unconfined_u:object_r:home_cert_t:s0     4096 .
drwx------. 35 myuser myuser unconfined_u:object_r:user_home_dir_t:s0 4096 ..
drwxr-xr-x.  2 myuser myuser unconfined_u:object_r:home_cert_t:s0     4096 myvpn

.cert/myvpn:
-rw-r--r--.  1 myuser myuser unconfined_u:object_r:home_cert_t:s0 1200 client-cert.pem
-rw-------.  1 myuser myuser unconfined_u:object_r:home_cert_t:s0 1704 client-key.pem
-rw-r--r--.  1 myuser myuser unconfined_u:object_r:home_cert_t:s0  914 VpnServerRoot.cer

Then following the GUI Steps of the Microsoft guide, opened GNOME Settings → Network → Add VPN → IPsec/IKEv2 (strongswan) and added the following:

enter image description here

The server and client certificate files were imported from the ~/.cert/myvpn/ directory. Everything else (the Algorithms section and all the other tabs) were left unchanged and in most cases empty.

The issue I ran into

When I tried to connect to it using GUI toggle, it wouldn't turn on and immediately switches off; and when I tried to turn it on with nmcli, I got the following logs in the console:

$ sudo nmcli general logging level debug

$ nmcli general logging
LEVEL  DOMAINS
DEBUG  PLATFORM,RFKILL,ETHER,WIFI,BT,MB,DHCP4,DHCP6,PPP,IP4,IP6,AUTOIP4,DNS,VPN,SHARING,SUPPLICANT,AGENTS,SETTINGS,SUSPEND,CORE,DEVICE,OLPC,INFINIBAND,FIREWALL,ADSL,BOND,VLAN,BRIDGE,TEAM,CONCHECK,DCB,DISPATCH,AUDIT,SYSTEMD,PROXY

$ nmcli connection up myvpn
Error: Connection activation failed: No valid secrets
Hint: use 'journalctl -xe NM_CONNECTION=c8259051-72b6-443f-a718-35479d4744b8 + NM_DEVICE=enp70s0' to get more details.

$ journalctl -xe NM_CONNECTION=c8259051-72b6-443f-a718-35479d4744b8 + NM_DEVICE=enp70s0
May 21 22:59:37 MyComputerHostname NetworkManager[1612]: <info>  [1779429577.6508] vpn[0x55ba894865e0,c8259051-72b6-443f-a718-35479d4744b8,"myvpn"]: starting strongswan
May 21 22:59:37 MyComputerHostname NetworkManager[1612]: <warn>  [1779429577.6564] vpn[0x55ba894865e0,c8259051-72b6-443f-a718-35479d4744b8,"myvpn"]: plugin NeedSecrets request #1 failed: GDBus.Error:org.freedesktop.NetworkManager.Settings.Connection.InvalidProperty: Failure creating the temporary file
May 21 23:50:38 MyComputerHostname NetworkManager[1612]: <debug> [1779432638.2233] ndisc-lndp[0x7f735c00cab0,"enp70s0"]: processing libndp events
May 21 23:50:38 MyComputerHostname NetworkManager[1612]: <debug> [1779432638.3204] ndisc-lndp[0x7f735c00cab0,"enp70s0"]: processing libndp events
May 21 23:50:42 MyComputerHostname NetworkManager[1612]: <debug> [1779432642.9932] device[30c479a3a8c2afdd] (enp70s0): add_pending_action (1): 'activation-16'
May 21 23:50:42 MyComputerHostname NetworkManager[1612]: <debug> [1779432642.9933] active-connection[cefeeab6d1ead33d]: constructed (NMVpnConnection, version-id 16, type managed)
May 21 23:50:43 MyComputerHostname NetworkManager[1612]: <info>  [1779432643.0060] vpn[0x55ba894865e0,c8259051-72b6-443f-a718-35479d4744b8,"myvpn"]: starting strongswan
May 21 23:50:43 MyComputerHostname NetworkManager[1612]: <debug> [1779432643.0060] vpn[0x55ba894865e0,c8259051-72b6-443f-a718-35479d4744b8,"myvpn"]: starting: watch D-Bus service org.freedesktop.NetworkManager.strongswan
May 21 23:50:43 MyComputerHostname NetworkManager[1612]: <debug> [1779432643.0060] vpn[0x55ba894865e0,c8259051-72b6-443f-a718-35479d4744b8,"myvpn"]: set state: prepare (was waiting)
May 21 23:50:43 MyComputerHostname NetworkManager[1612]: <debug> [1779432643.0060] active-connection[cefeeab6d1ead33d]: set state activating (was unknown)
May 21 23:50:43 MyComputerHostname NetworkManager[1612]: <debug> [1779432643.0061] active-connection[cefeeab6d1ead33d]: check-controller-ready: not signalling (state activating, no controller)
May 21 23:50:43 MyComputerHostname NetworkManager[1612]: <debug> [1779432643.0085] vpn[0x55ba894865e0,c8259051-72b6-443f-a718-35479d4744b8,"myvpn"]: starting: VPN service has PID 234994
May 21 23:50:43 MyComputerHostname NetworkManager[1612]: <debug> [1779432643.0306] platform: (enp70s0) signal: address 4 changed: 192.168.1.15/24 brd 192.168.1.255 lft 50364sec pref 50364sec lifetime 91998-55962[86400,86400] dev 2 flags noprefixroute src kernel
May 21 23:50:43 MyComputerHostname NetworkManager[1612]: <debug> [1779432643.0310] platform: (enp70s0) signal: address 6 changed: 2601:646:a000:8d0e:fb85:a6a8:932:8d5b/64 lft 252933sec pref 252933sec lifetime 91998-91960[252971,252971] dev 2 flags noprefixroute src kernel
May 21 23:50:43 MyComputerHostname NetworkManager[1612]: <debug> [1779432643.0452] vpn[0x55ba894865e0,c8259051-72b6-443f-a718-35479d4744b8,"myvpn"]: set state: need-auth (was prepare)
May 21 23:50:43 MyComputerHostname NetworkManager[1612]: <debug> [1779432643.0453] vpn[0x55ba894865e0,c8259051-72b6-443f-a718-35479d4744b8,"myvpn"]: secrets: requesting VPN secrets pass #1
May 21 23:50:43 MyComputerHostname NetworkManager[1612]: <debug> [1779432643.0454] settings-connection[880c56810e638783,c8259051-72b6-443f-a718-35479d4744b8]: (vpn:0x55ba894daa90) secrets requested flags 0x80000004 hints '(none)'
May 21 23:50:43 MyComputerHostname NetworkManager[1612]: <debug> [1779432643.0456] settings-connection[880c56810e638783,c8259051-72b6-443f-a718-35479d4744b8]: (vpn:0x55ba8956a900) existing secrets returned
May 21 23:50:43 MyComputerHostname NetworkManager[1612]: <debug> [1779432643.0456] settings-connection[880c56810e638783,c8259051-72b6-443f-a718-35479d4744b8]: (vpn:0x55ba8956a900) secrets request completed
May 21 23:50:43 MyComputerHostname NetworkManager[1612]: <debug> [1779432643.0457] settings-connection[880c56810e638783,c8259051-72b6-443f-a718-35479d4744b8]: (vpn:0x55ba8956a900) new agent secrets processed
May 21 23:50:43 MyComputerHostname NetworkManager[1612]: <debug> [1779432643.0461] vpn[0x55ba894865e0,c8259051-72b6-443f-a718-35479d4744b8,"myvpn"]: secrets: asking service if additional secrets are required
May 21 23:50:43 MyComputerHostname NetworkManager[1612]: <warn>  [1779432643.0510] vpn[0x55ba894865e0,c8259051-72b6-443f-a718-35479d4744b8,"myvpn"]: plugin NeedSecrets request #1 failed: GDBus.Error:org.freedesktop.NetworkManager.Settings.Connection.InvalidProperty: Failure creating the temporary file
May 21 23:50:43 MyComputerHostname NetworkManager[1612]: <debug> [1779432643.0510] vpn[0x55ba894865e0,c8259051-72b6-443f-a718-35479d4744b8,"myvpn"]: set state: failed (was need-auth)
May 21 23:50:43 MyComputerHostname NetworkManager[1612]: <debug> [1779432643.0510] active-connection[cefeeab6d1ead33d]: set state deactivated (was activating)
May 21 23:50:43 MyComputerHostname NetworkManager[1612]: <debug> [1779432643.0511] active-connection[cefeeab6d1ead33d]: check-controller-ready: not signalling (state deactivated, no controller)
May 21 23:50:43 MyComputerHostname NetworkManager[1612]: <debug> [1779432643.0511] device[30c479a3a8c2afdd] (enp70s0): remove_pending_action (0): 'activation-16'
May 21 23:50:43 MyComputerHostname NetworkManager[1612]: <debug> [1779432643.0514] active-connection[cefeeab6d1ead33d]: disposing
May 21 23:50:43 MyComputerHostname NetworkManager[1612]: <debug> [1779432643.3300] ndisc-lndp[0x7f735c00cab0,"enp70s0"]: processing libndp events
May 21 23:50:49 MyComputerHostname NetworkManager[1612]: <debug> [1779432649.0737] ndisc-lndp[0x7f735c00cab0,"enp70s0"]: processing libndp events

How do I fix this and get connected to my VPN?

Azure VPN Gateway
Azure VPN Gateway

An Azure service that enables the connection of on-premises networks to Azure through site-to-site virtual private networks.

0 comments No comments

3 answers

Sort by: Most helpful
  1. Sepehr Soltanieh 45 Reputation points
    2026-05-28T06:22:28.4+00:00

    My solution

    Thanks Vallepu, your pointers got me looking in the right direction. SELinux was indeed part of the problem, but it turned out there were actually two independent blockers stacked on top of each other, and the system-wide cert placement suggestion did not work on current Fedora. I finally got it connecting reliably with SELinux left in enforcing mode, so I wanted to write up the full solution in case it helps the next person.

    Where to put the certificates (this part matters)

    The official guide tells you to drop the certs into system directories like /etc/ipsec.d/{certs,private,cacerts}. On Fedora that path belongs to libreswan, and strongswan uses /etc/strongswan/ipsec.d/ instead. I tried the strongswan system path and it failed:

    plugin NeedSecrets request #1 failed: GDBus.Error:...: Failed to read file
    '/etc/strongswan/ipsec.d/private/client-key.pem' as user 'sepehr':
    error opening the file: 13 (Permission denied)
    

    The reason is that NetworkManager 1.56 reads the certificate and key as the user activating the connection, not as root. System directories under /etc/strongswan/ipsec.d/ are mode 700 and owned by root, so a normal user cannot read them, and the connection fails before it even starts. Running sudo nmcli con up does not help either, because NetworkManager still resolves the requesting user from the D-Bus session.

    The fix that works is to keep the certificates somewhere your own user can read, and the conventional spot is ~/.cert/. It already carries the right SELinux type (home_cert_t), so it is purpose-built for exactly this.

    install -m 0755 -Z -d ~/.cert/myvpn
    install -m 0644 -Z "/path/to/downloaded/azure/vpnclientconfiguration/Generic/VpnServerRoot.cer_0" ~/.cert/myvpn/VpnServerRoot.cer
    install -m 0644 -Z "/path/to/generated/azure/vpn/client/Cert.pem" ~/.cert/myvpn/client-cert.pem
    install -m 0600 -Z "/path/to/generated/azure/vpn/client/Key.pem" ~/.cert/myvpn/client-key.pem
    restorecon -RvF ~/.cert        # confirm the SELinux context; check with: ls -Z ~/.cert/myvpn
    

    Then create the connection through GNOME Settings → Network → VPN → IPsec/IKEv2 (strongswan), pointing the CA certificate, the user certificate, and the private key at the three files above, and enabling "Request an inner IP address".

    Blocker 1: SHA-1 crypto policy

    Azure's VPN gateway certificate is signed with SHA-1 by Microsoft's CA. Fedora's default crypto policy disables SHA-1 signature verification, and charon-nm validates that gateway certificate through OpenSSL, which consults the system-wide crypto policy. Until SHA-1 is re-enabled, authentication against the gateway fails.

    sudo update-crypto-policies --set DEFAULT:SHA1     # check with: update-crypto-policies --show
    

    Note that only Azure's server side uses SHA-1. Your own client certificate can be SHA-256.

    Blocker 2: the temporary cert file (SELinux plus directory permissions)

    With the certs readable and SHA-1 allowed, the connection still failed:

    Error: Connection activation failed: No valid secrets
    

    and in the journal:

    plugin NeedSecrets request #1 failed: GDBus.Error:...InvalidProperty:
    Failure creating the temporary file
    

    Here is what is happening. NetworkManager 1.56 reads your ~/.cert/ files as your user, then writes short-lived copies into /run/NetworkManager/cert/ and hands those temporary paths to charon-nm (strongswan's NetworkManager backend), which reads them and brings up the IPsec tunnel. The temporary files are removed when the VPN disconnects. This copy-as-user behavior appears to be the hardening added for CVE-2025-9615, which is named in both the NetworkManager and strongswan package changelogs on Fedora.

    Two things break that copy step, and they are on different layers:

    1. Directory permissions (DAC). The /run/NetworkManager/cert/ directory gets created with mode 0600, which has no execute bit. NetworkManager itself can still use it because it runs with full capabilities, but charon-nm drops its Linux capabilities at startup (you can see dropped capabilities, running as uid 0, gid 0 in its log). Without CAP_DAC_OVERRIDE, even uid 0 cannot enter a directory that lacks the execute bit, so creating the temp file fails.

    2. SELinux (MAC). charon-nm runs in the ipsec_t domain, and the cert directory is typed NetworkManager_var_run_t. The shipped policy does not allow that combination, so even after the permission issue is solved, SELinux blocks it. With dontaudit rules disabled, the denial shows up clearly:

    avc: denied { write } for comm="charon-nm" name="cert" dev="tmpfs"
    scontext=system_u:system_r:ipsec_t:s0
    tcontext=system_u:object_r:NetworkManager_var_run_t:s0
    tclass=dir permissive=0
    

    Both layers have to be satisfied. Fixing only one still fails.

    Fix for blocker 2

    First, generate a small SELinux policy module from the real denials. Going permissive briefly and disabling dontaudit lets you capture the complete set in one pass:

    sudo setenforce 0
    sudo semodule -DB
    sudo mkdir -p /run/NetworkManager/cert && sudo chmod 700 /run/NetworkManager/cert
    nmcli con up myvpn
    nmcli con down myvpn
    sudo ausearch -m avc -ts recent --raw | grep 'ipsec_t' | audit2allow -M allow-strongswan-charon-nm-vpn-certs
    

    Review what it will allow before installing:

    cat allow-strongswan-charon-nm-vpn-certs.te
    

    On my system it came out tightly scoped to just this interaction:

    allow NetworkManager_t ipsec_t:process { noatsecure rlimitinh siginh };
    allow ipsec_t NetworkManager_var_run_t:dir { add_name remove_name write };
    allow ipsec_t NetworkManager_var_run_t:file { create getattr open read rename unlink write };
    

    Install it, re-enable dontaudit, and go back to enforcing:

    sudo semodule -i allow-strongswan-charon-nm-vpn-certs.pp
    sudo semodule -B
    sudo setenforce 1
    

    Finally, make the directory permission fix survive reboots. /run is tmpfs, so it is recreated on every boot. A tmpfiles.d entry creates the directory with the right mode early, before the VPN backend needs it:

    echo 'd /run/NetworkManager/cert 0700 root root -' | sudo tee /etc/tmpfiles.d/nm-cert-dir.conf
    

    Result

    After both blockers are addressed, the VPN connects with SELinux enforcing:

    nmcli con up myvpn
    

    A caveat on blocker 2, and a request

    I want to be upfront that I am not fully certain this is the correct root-cause fix for the second blocker, only that it is consistent with what I observed and that it gets me connected reliably. The reasoning (the copy-as-user step, the mode 0600 directory, charon-nm dropping capabilities, and the SELinux type mismatch) is pieced together from the package changelogs, the daemon logs, and the AVC denials, not from reading the source.

    One thing worth being precise about: the two layers are not interchangeable, and fixing only the permissions does not remove the need for the SELinux rule. SELinux type enforcement is independent of Linux capabilities and of file mode. CAP_DAC_OVERRIDE only bypasses the kernel's owner/group/mode check; the SELinux decision is made separately, purely on the process domain and the target type. So a process in ipsec_t writing to NetworkManager_var_run_t is denied even with full capabilities and even if the directory were 0700 or 0777. In other words, simply having charon-nm create the directory before it drops capabilities, or having NetworkManager create it as 0700, would still leave the SELinux denial in place. As long as charon-nm (ipsec_t) is the process creating the file inside NetworkManager's runtime directory, a policy rule is required.

    That points at what the real root cause probably is. There is one change that would make both workarounds unnecessary at once: having NetworkManager itself (the NetworkManager_t daemon) create the temporary file, rather than charon-nm doing it. NetworkManager runs with full capabilities, so mode 0600 would not block it, and it is already allowed to write to its own NetworkManager_var_run_t directory, so SELinux would not block it either. The fact that charon-nm calls this copy step in its own deprivileged ipsec_t process suggests the hardening from CVE-2025-9615 was meant to run inside the NetworkManager daemon, and the strongswan plugin is invoking it from the wrong context. I have not confirmed this against the source, so treat it as a hypothesis.

    If anyone closer to the NetworkManager or strongswan internals can confirm where this should properly be fixed (in strongswan's charon-nm, in NetworkManager, or as a new rule in Fedora's selinux-policy), or knows a cleaner approach that avoids a local policy module, I would genuinely appreciate the correction.

    Was this answer helpful?

    0 comments No comments

  2. Vallepu Venkateswarlu 9,830 Reputation points Microsoft External Staff Moderator
    2026-05-25T19:01:43.9633333+00:00

    Hi Sepehr Soltanieh,

    Welcome to Microsoft Q&A Platform.

    It looks like NetworkManager’s strongSwan plugin on Fedora 44 (with SELinux Enforcing) is choking on creating its “secret” temp file hence the “NeedSecrets request #1 failed: … Failure creating the temporary file” and “No valid secrets” errors. In most cases this points to SELinux denying the write. Here are a few ways to get you back online without disabling SELinux:

    Quick SELinux check

    • sudo setenforce 0
    • nmcli connection up myvpn
    • If the VPN suddenly connects, SELinux is indeed the blocker.

    Add a targeted SELinux policy for NetworkManager-strongSwan

    sudo ausearch -c NetworkManager --raw | audit2allow -M nm-strongswan sudo semodule -i nm-strongswan.pp This lets the plugin create its temp files while keeping the rest of SELinux enforced.

    System-wide cert/key placement (no temp-file hacks) Move your client certificate and private key into the system directories so NM-strongSwan can use them in place, avoiding per-user temp files altogether:

    sudo install -o root -g root -m 0644 ~/.cert/myvpn/client-cert.pem    /etc/ipsec.d/certs/ 
    sudo install -o root -g root -m 0600 ~/.cert/myvpn/client-key.pem     /etc/ipsec.d/private/ 
    sudo install -o root -g root -m 0644 ~/.cert/myvpn/VpnServerRoot.cer   /etc/ipsec.d/cacerts/
    
    

    Then in GNOME Settings → Network → + VPN → IPsec/IKEv2 (strongswan): • CA certificate → /etc/ipsec.d/cacerts/VpnServerRoot.cer • Certificate file → /etc/ipsec.d/certs/client-cert.pem • Private key → /etc/ipsec.d/private/client-key.pem

    If you’re comfortable with text files, you can bypass NetworkManager and drop a /etc/ipsec.conf + /etc/strongswan.conf in place. Microsoft’s guide has a sample at the bottom of the Linux GUI doc.

    Give the policy trick or system-path workaround a try. If you still see failures, grab the AVC denials right after a failed connect and paste them here:

    sudo ausearch -m avc -ts today
    

    Refer:

    Configure P2S IKEv2 cert-auth on Linux

    Basic SKU IKEv2 support details:

    Please210246-screenshot-2021-12-10-121802.pngand “up-vote” wherever the information provided helps you, **this can be beneficial to other community members.

    Was this answer helpful?

    0 comments No comments

  3. AI answer

    2026-05-22T07:04:48.83+00:00

    Azure P2S IKEv2 certificate-based VPN clients on Linux must be configured from the Generic profile in the Azure-generated VPN client package. For IKEv2 certificate authentication, Azure requires:

    1. A VPN gateway SKU that supports IKEv2 for P2S.
    2. IKEv2 selected as a tunnel type when generating the VPN client profile.
    3. The client configured using the values from the Generic folder in the profile package.

    In this scenario, the Basic SKU VPN gateway is used. The Basic SKU does not support IKEv2 for P2S, so Azure does not generate the required Generic configuration and the IKEv2 client cannot be configured correctly. This leads to connection failures on Linux clients such as Fedora with strongSwan/NetworkManager.

    To fix the issue and connect successfully from Fedora using strongSwan/NetworkManager:

    1. Change the VPN gateway to a SKU that supports IKEv2 for P2S (for example, a non-Basic SKU listed as supporting IKEv2 in Azure VPN Gateway documentation).
    2. In the VPN gateway configuration, ensure IKEv2 is selected as a tunnel type for the P2S configuration.
    3. Regenerate the VPN client profile configuration package after changing the SKU and tunnel type.
    4. Unzip the new package and use the files in the Generic folder:
      • VpnSettings.xml for server address and tunnel type.
      • VpnServerRoot.cer as the root certificate to validate the Azure VPN gateway.
    5. Reconfigure the Fedora strongSwan/NetworkManager connection using these values and certificates.

    If the Generic folder is missing after regeneration, verify again that:

    • IKEv2 is selected as the tunnel type.
    • The VPN gateway SKU is not Basic.

    Only after these conditions are met will Azure provide the correct IKEv2 configuration needed for a working Linux client.


    References:

    AI-generated content may be incorrect. Read our transparency notes for more information.

    Was this answer helpful?

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.