Unable to connect to VPN with strongswan

Hello, I am trying to connect to my uni’s VPN using strongswan with EAP.

I installed strongswan with:

  networking.networkmanager = {
  	enable = true;
	enableStrongSwan = true;
  };

And configured the vpn settings itself using the nm-applet gui, without a certificate specified.

However when trying to connect I get the error:

nov 25 15:41:28 hostname charon-nm[5648]: 06[CFG] no issuer certificate found for "C=US, ST=New Jersey, L=Jersey City, O=The USERTRUST Network, CN=USERTrust RSA Certification Authority"

In the setup instructions it is written that:

Strongswan does not have any default trusted root certificates on some linux distributions (verified for fedora 36). This causes the VPN connection to fail, as the certificate used by the university will not be trusted. This issue does not affect Ubuntu 18.04.

  1. To check if this is the case, run # journalctl -f -u NetworkManager.service, while trying to connect to the VPN.
  2. Only proceed to the next step if the connection log shows a line such as no issuer certificate found for "C=US, ST=New Jersey, L=Jersey City, O=The USERTRUST Network, CN=USERTrust RSA Certification Authority"
  3. Make a symbolic link from the root certificates trusted by your distribution to the directory where strongswan expects certificates. This directory differs between distributions.
  • On Ubuntu (and most other distributions): # ln -s /etc/ssl/certs /etc/ipsec.d/cacerts/systemCA
  • On Fedora: # ln -s /etc/ssl/certs /etc/strongswan/ipsec.d/cacerts/systemCA
  1. Restart strongswan and NetworkManager: # systemctl restart strongswan NetworkManager

However, this is naturally not possible on NixOS.

In the strongswanNM it is specified that the /etc/ssl/certs should be used as a source of certificates in: nixpkgs/pkgs/tools/networking/strongswan/default.nix at e8c38b73aeb218e27163376a2d617e61a2ad9b59 · NixOS/nixpkgs · GitHub
So it feels like the program should work properly out of the box, however maybe something is misconfigured or missing?

1 Like

Also having the same problem, similarly trying to connect to my Uni’s VPN on Nix, with StrongSwan. Have you made any progress in getting this working?

Have you tried setting security.pki.certificateFiles to [ "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt" ]?

Sorry for the late reply!
I fixed it by manually downloading and putting the certificate in /etc/ssl/certs.

This should also be possible by adding the file through security.pki.certificateFiles, however when trying it through this way it didn’t work for me and I haven’t bothered looking into it since.

While this fixed the certificate issue and I am able to connect to the VPN, my internet just stops working once connected. So I still haven’t gotten it to work :(. Let me know if you run into the same issue!

Same issue here, also wasn’t able to connect with the cert added to security.pki.certificateFiles, but either adding it as the VPN certificate in NetworkManager, or into /etc/ssl/certs allowed me to connect. Still, no Internet, I think it might be something to do with routing.

I’ll try messing around with it some more and make a post here if I figure anything out.

Something similar was also mentioned in this older thread.

1 Like

Right, I wasn’t able to figure it out using NetworkManager, BUT using the strongswan service without going through NM actually managed to work.

Here’s my config:

  services.strongswan = {
    enable = true;
   
    ca = {
      lets_encrypt = {
        auto = "add";
        # This is where I store my Let's encrypt root X1 cert
        cacert = "/etc/nixos/certs/isrgrootx1.pem";
      };
    };

    connections = {
      work = {
        auto = "add";
        
        right = "gate.workdomain.tld";       # VPN server address
        rightid = "gate.workdomain.tld";
        rightsubnet = "0.0.0.0/0";
        rightauth = "pubkey";

        leftauth = "eap";

        # Specific setting that my workplace requires
        leftsourceip = "%config";

        eap_identity = "my_username";          # Maps to user=my_username

        # Specific settings that my workplace requires
        fragmentation = "yes";              # Encapsulation is enabled
        compress = "yes";                   # Maps to ipcomp=yes
      };
    };

    secrets = [
      # Maps to a file that looks something like this:
      # my_username : EAP "my_password"
      "/run/secrets/work_vpn_password"
    ];
  };

And to connect to the VPN, just run:

sudo ipsec up work (replace work with your VPN connection name)

And then it magically works.

You might have to reboot before it will find the connection. Not sure why, didn’t bother to check.

Thanks! I got it to work with your configuration as base, but with slightly different configuration as my VPN uses eap-mschapv2.

Here is my configuration as reference for anyone who’s also trying to set it up:

{ inputs, outputs, ... }: 
let 
	vpn_server_address = "vpn-url";
	identity = "my-identity";
in
{
  services.strongswan = {
    enable = true;
   
    ca = {
      usertrust = {
        auto = "add";
        # This is where I store my USERTrust certificate:
        cacert = "/etc/ssl/certs/USERTrust_RSA_Certification_Authority.crt";
      };
    };

    connections = {
      uni = {
        auto = "add";
	keyexchange = "ikev2";
        
        right = vpn_server_address;
        rightid = vpn_server_address;
        rightsubnet = "0.0.0.0/0";
		rightauth = "pubkey";

                  leftauth = "eap-mschapv2";
                  leftsourceip = "%config";
          	  leftid = "%any";

        eap_identity = identity ;

		encap = "true";
        compress = "no";
		fragmentation = "yes";
      };
};

    secrets = [
      # Maps to a file that looks something like this:
      # my_username : EAP "my_password"
      "/run/secrets/uni_vpn_login"
    ];
  };

}

For anyone: If you want to test it out quickly without rebooting, try out `ipsec rereadsecrets` and `ipsec update` to make sure your new configuration is read by ipsec.
1 Like

Also FYI, if you need the VPN to only affect certain subnets, change the rightsubnet option. For example, 10.0.0.0/8 for 10.0.0.0 - 10.255.255.255.