# This strongswan-swanctl test is based on: # https://www.strongswan.org/testing/testresults/swanctl/rw-psk-ipv4/index.html # https://github.com/strongswan/strongswan/tree/master/testing/tests/swanctl/rw-psk-ipv4 # # The roadwarrior carol sets up a connection to gateway moon. The authentication # is based on pre-shared keys and IPv4 addresses. Upon the successful # establishment of the IPsec tunnels, the specified updown script automatically # inserts iptables-based firewall rules that let pass the tunneled traffic. In # order to test both tunnel and firewall, carol pings the client alice behind # the gateway moon. # # alice moon carol # eth1------vlan_0------eth1 eth2------vlan_1------eth1 # 192.168.0.1 192.168.0.3 192.168.1.3 192.168.1.2 # # See the NixOS manual for how to run this test: # https://nixos.org/nixos/manual/index.html#sec-running-nixos-tests-interactively import ./make-test.nix ({ pkgs, ...} : let allowESP = "iptables --insert INPUT --protocol ESP --jump ACCEPT"; # Shared VPN settings: vlan0 = "192.168.0.0/24"; carolIp = "192.168.1.2"; moonIp = "192.168.1.3"; version = 2; secret = "0sFpZAZqEN6Ti9sqt4ZP5EWcqx"; esp_proposals = [ "aes128gcm128-x25519" ]; proposals = [ "aes128-sha256-x25519" ]; in { name = "strongswan-swanctl"; meta.maintainers = with pkgs.stdenv.lib.maintainers; [ basvandijk ]; nodes = { alice = { nodes, ... } : { virtualisation.vlans = [ 0 ]; networking = { dhcpcd.enable = false; defaultGateway = "192.168.0.3"; }; }; moon = {pkgs, config, nodes, ...} : let strongswan = config.services.strongswan-swanctl.package; in { virtualisation.vlans = [ 0 1 ]; networking = { dhcpcd.enable = false; firewall = { allowedUDPPorts = [ 4500 500 ]; extraCommands = allowESP; }; nat = { enable = true; internalIPs = [ vlan0 ]; internalInterfaces = [ "eth1" ]; externalIP = moonIp; externalInterface = "eth2"; }; }; environment.systemPackages = [ strongswan ]; services.strongswan-swanctl = { enable = true; swanctl = { connections = { "rw" = { local_addrs = [ moonIp ]; local."main" = { auth = "psk"; }; remote."main" = { auth = "psk"; }; children = { "net" = { local_ts = [ vlan0 ]; updown = "${strongswan}/libexec/ipsec/_updown iptables"; inherit esp_proposals; }; }; inherit version; inherit proposals; }; }; secrets = { ike."carol" = { id."main" = carolIp; inherit secret; }; }; }; }; }; carol = {pkgs, config, nodes, ...} : let strongswan = config.services.strongswan-swanctl.package; in { virtualisation.vlans = [ 1 ]; networking = { dhcpcd.enable = false; firewall.extraCommands = allowESP; }; environment.systemPackages = [ strongswan ]; services.strongswan-swanctl = { enable = true; swanctl = { connections = { "home" = { local_addrs = [ carolIp ]; remote_addrs = [ moonIp ]; local."main" = { auth = "psk"; id = carolIp; }; remote."main" = { auth = "psk"; id = moonIp; }; children = { "home" = { remote_ts = [ vlan0 ]; start_action = "trap"; updown = "${strongswan}/libexec/ipsec/_updown iptables"; inherit esp_proposals; }; }; inherit version; inherit proposals; }; }; secrets = { ike."moon" = { id."main" = moonIp; inherit secret; }; }; }; }; }; }; testScript = '' startAll(); $carol->waitUntilSucceeds("ping -c 1 alice"); ''; })