0

I use strongswan-swanctl on a VPN server running NixOS.

Basically it is working and I can connect to the VPN server from clients.

  services.strongswan-swanctl = {                                            
    enable = true;                                                           
    swanctl = {                                                              
      authorities = {                                                        
        "vpnca" = {                                                          
          cacert = "ca-cert.pem";                                            
        };                                                                   
      };                                                                     
      connections = {                                                        
        "ikev2-eap" = {                                                      
          version = 2;                                                       
          proposals = [ "aes192gcm16-aes128gcm16-prfsha256-ecp256-ecp521"    
                        "aes192-sha256-modp3072"                             
                        "default" ];                                         
          rekey_time = "0s";                                                 
          pools = [ "primary-pool-ipv4" "primary-pool-ipv6" ];               
          fragmentation = "yes";                                             
          dpd_delay = "30s";                                                 
          local."1" = {                                                      
            certs = [ "vpn_example_com.pem" ];                              
            id = "@vpn.example.com";                                        
          };                                                                 
          remote."1" = {                                                     
            auth = "eap-mschapv2";                                           
            eap_id = "%any";                                                 
          };                                                                 
          children = {                                                       
            "ikev2-eap" = {                                                  
              local_ts = [ "0.0.0.0/0" "::/0" ];                             
              rekey_time = "0s";                                             
              dpd_action = "clear";                                          
              esp_proposals = [ "aes192gcm16-aes128gcm16-prfsha256-ecp256-modp3072"
                                "aes192-sha256-ecp256-modp3072"              
                                "default" ];                                 
              updown = "/etc/swanctl/proxyndp.updown";                       
            };                                                               
          };                                                                 
          local_addrs = [ "192.0.2.1" "2001:db8::2"];         
        };                                                                   
      };

The problem I have is inside the /etc/swanctl/proxyndp.updown script:

#! /bin/sh

case $PLUTO_VERB in
     up-client-v6)
         sysctl -w net.ipv6.conf.all.forwarding=1
         sysctl -w net.ipv6.conf.all.proxy_ndp=1
         ip -6 neigh add proxy ${PLUTO_PEER_CLIENT%????} dev ens3
     ;;
     down-client-v6)
         ip -6 neigh delete proxy ${PLUTO_PEER_CLIENT%????} dev ens3
     ;;
esac

The program sysctl isn't found by the system when executing this script. On a normal user shell I see the tool in /run/current-system/sw/bin/sysctl but for this script I get the following log messages in the system journal:

Feb 12 16:04:01 vpn.example.com charon-systemd[9249]: updown: /etc/swanctl/proxyndp.updown: line 5: sysctl: command not found
Feb 12 16:04:01 vpn.example.com charon-systemd[9249]: updown: /etc/swanctl/proxyndp.updown: line 6: sysctl: command not found

Note: ip is in the same folder and can be run by the script.

Any idea what's going wrong there?

1 Answers1

1

Behaviour definition outside Nix expressions

It looks to me like you put the proxy.updown file by yourself in /etc. That is something you shouldn't do on NixOS, as your system behaviour then wouldn't only depend on your Nix expressions. Everything should be managed in your configuration.nix (or files imported by configuration.nix). Instead of setting the path in services.strongswan-swanctl.swanctl.connections."ikev2-eap".children."ikev2-eap".updown, you can directly supply the content of the file:

updown = ''
  sysctl -w net.ipv6.conf.all.forwarding=1
  ...
'';

sysctl: command not found

The sysctl binary is not found, because it is not part of the systemd service PATH, as you can see here in the sources. One easy fix for that is to directly reference the Nix store path of sysctl in the updown script with "${pkgs.procps}/bin/sysctl ...".

updown = ''
  ${pkgs.procps}/bin/sysctl -w net.ipv6.conf.all.forwarding=1
  ...
'';

On build time, that expression is transformed to something like "/nix/store/8f9cypv6vw5hwkh49l1j6b1rkxi4dbsq-procps-3.3.15/bin/sysctl ...".

Alternative to using sysctl command

If you could live with the sysctl option being defined all the time and not just when your interface is up, you could use the boot.kernel.sysctl option.

{ config, pkgs, lib, ...}:{
  boot.kernel.sysctl = {
    "net.ipv6.conf.all.forwarding" = "1";
    "net.ipv6.conf.all.proxy_ndp" = "1";
  };

  services.strongswan-swanctl = {
  ...
}

Resources

I've never used strongswan but I think a valuable resource for learning NixOS best practices are the NixOS tests. The strongswan one defines three virtual machines, boots them and tests, wether the first machine can ping the third one through the VPN.

erictapen
  • 146