1{ 2 system ? builtins.currentSystem, 3 config ? { }, 4 pkgs ? import ../.. { inherit system config; }, 5 systemdStage1 ? false, 6}: 7 8import ../make-test-python.nix ( 9 { lib, ... }: 10 11 { 12 name = "initrd-network-openvpn"; 13 14 nodes = 15 let 16 17 # Inlining of the shared secret for the 18 # OpenVPN server and client 19 secretblock = '' 20 secret [inline] 21 <secret> 22 ${lib.readFile ./shared.key} 23 </secret> 24 ''; 25 26 in 27 { 28 29 # Minimal test case to check a successful boot, even with invalid config 30 minimalboot = 31 { ... }: 32 { 33 boot.initrd.systemd.enable = systemdStage1; 34 boot.initrd.network = { 35 enable = true; 36 openvpn = { 37 enable = true; 38 configuration = builtins.toFile "initrd.ovpn" ""; 39 }; 40 }; 41 }; 42 43 # initrd VPN client 44 ovpnclient = 45 { ... }: 46 { 47 virtualisation.useBootLoader = true; 48 virtualisation.vlans = [ 1 ]; 49 50 boot.initrd = { 51 systemd.enable = systemdStage1; 52 systemd.extraBin.nc = "${pkgs.busybox}/bin/nc"; 53 systemd.services.nc = { 54 requiredBy = [ "initrd.target" ]; 55 after = [ "network.target" ]; 56 serviceConfig = { 57 ExecStart = "/bin/nc -p 1234 -lke /bin/echo TESTVALUE"; 58 Type = "oneshot"; 59 }; 60 }; 61 62 # This command does not fork to keep the VM in the state where 63 # only the initramfs is loaded 64 preLVMCommands = lib.mkIf (!systemdStage1) '' 65 /bin/nc -p 1234 -lke /bin/echo TESTVALUE 66 ''; 67 68 network = { 69 enable = true; 70 71 # Work around udhcpc only getting a lease on eth0 72 postCommands = lib.mkIf (!systemdStage1) '' 73 /bin/ip addr add 192.168.1.2/24 dev eth1 74 ''; 75 76 # Example configuration for OpenVPN 77 # This is the main reason for this test 78 openvpn = { 79 enable = true; 80 configuration = "${./initrd.ovpn}"; 81 }; 82 }; 83 }; 84 }; 85 86 # VPN server and gateway for ovpnclient between vlan 1 and 2 87 ovpnserver = 88 { ... }: 89 { 90 virtualisation.vlans = [ 91 1 92 2 93 ]; 94 95 # Enable NAT and forward port 12345 to port 1234 96 networking.nat = { 97 enable = true; 98 internalInterfaces = [ "tun0" ]; 99 externalInterface = "eth2"; 100 forwardPorts = [ 101 { 102 destination = "10.8.0.2:1234"; 103 sourcePort = 12345; 104 } 105 ]; 106 }; 107 108 # Trust tun0 and allow the VPN Server to be reached 109 networking.firewall = { 110 trustedInterfaces = [ "tun0" ]; 111 allowedUDPPorts = [ 1194 ]; 112 }; 113 114 # Minimal OpenVPN server configuration 115 services.openvpn.servers.testserver = { 116 config = '' 117 dev tun0 118 ifconfig 10.8.0.1 10.8.0.2 119 cipher AES-256-CBC 120 ${secretblock} 121 ''; 122 }; 123 }; 124 125 # Client that resides in the "external" VLAN 126 testclient = 127 { ... }: 128 { 129 virtualisation.vlans = [ 2 ]; 130 }; 131 }; 132 133 testScript = '' 134 # Minimal test case, checks whether enabling (with invalid config) harms 135 # the boot process 136 with subtest("Check for successful boot with broken openvpn config"): 137 minimalboot.start() 138 # If we get to multi-user.target, we booted successfully 139 minimalboot.wait_for_unit("multi-user.target") 140 minimalboot.shutdown() 141 142 # Elaborated test case where the ovpnclient (where this module is used) 143 # can be reached by testclient only over ovpnserver. 144 # This is an indirect test for success. 145 with subtest("Check for connection from initrd VPN client, config as file"): 146 ovpnserver.start() 147 testclient.start() 148 ovpnclient.start() 149 150 # Wait until the OpenVPN Server is available 151 ovpnserver.wait_for_unit("openvpn-testserver.service") 152 ovpnserver.succeed("ping -c 1 10.8.0.1") 153 154 # Wait for the client to connect 155 ovpnserver.wait_until_succeeds("ping -c 1 10.8.0.2") 156 157 # Wait until the testclient has network 158 testclient.wait_for_unit("network.target") 159 160 # Check that ovpnclient is reachable over vlan 1 161 ovpnserver.succeed("nc -w 2 192.168.1.2 1234 | grep -q TESTVALUE") 162 163 # Check that ovpnclient is reachable over tun0 164 ovpnserver.succeed("nc -w 2 10.8.0.2 1234 | grep -q TESTVALUE") 165 166 # Check that ovpnclient is reachable from testclient over the gateway 167 testclient.succeed("nc -w 2 192.168.2.3 12345 | grep -q TESTVALUE") 168 ''; 169 } 170)