146 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
		
		
			
		
	
	
			146 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
| 
								 | 
							
								import ../make-test-python.nix ({ lib, ...}:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  name = "initrd-network-openvpn";
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  nodes =
							 | 
						||
| 
								 | 
							
								    let
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      # Inlining of the shared secret for the
							 | 
						||
| 
								 | 
							
								      # OpenVPN server and client
							 | 
						||
| 
								 | 
							
								      secretblock = ''
							 | 
						||
| 
								 | 
							
								        secret [inline]
							 | 
						||
| 
								 | 
							
								        <secret>
							 | 
						||
| 
								 | 
							
								        ${lib.readFile ./shared.key}
							 | 
						||
| 
								 | 
							
								        </secret>
							 | 
						||
| 
								 | 
							
								        '';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    in
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      # Minimal test case to check a successful boot, even with invalid config
							 | 
						||
| 
								 | 
							
								      minimalboot =
							 | 
						||
| 
								 | 
							
								        { ... }:
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								          boot.initrd.network = {
							 | 
						||
| 
								 | 
							
								            enable = true;
							 | 
						||
| 
								 | 
							
								            openvpn = {
							 | 
						||
| 
								 | 
							
								              enable = true;
							 | 
						||
| 
								 | 
							
								              configuration = "/dev/null";
							 | 
						||
| 
								 | 
							
								            };
							 | 
						||
| 
								 | 
							
								          };
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      # initrd VPN client
							 | 
						||
| 
								 | 
							
								      ovpnclient =
							 | 
						||
| 
								 | 
							
								        { ... }:
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								          virtualisation.useBootLoader = true;
							 | 
						||
| 
								 | 
							
								          virtualisation.vlans = [ 1 ];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          boot.initrd = {
							 | 
						||
| 
								 | 
							
								            # This command does not fork to keep the VM in the state where
							 | 
						||
| 
								 | 
							
								            # only the initramfs is loaded
							 | 
						||
| 
								 | 
							
								            preLVMCommands =
							 | 
						||
| 
								 | 
							
								            ''
							 | 
						||
| 
								 | 
							
								              /bin/nc -p 1234 -lke /bin/echo TESTVALUE
							 | 
						||
| 
								 | 
							
								            '';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            network = {
							 | 
						||
| 
								 | 
							
								              enable = true;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								              # Work around udhcpc only getting a lease on eth0
							 | 
						||
| 
								 | 
							
								              postCommands = ''
							 | 
						||
| 
								 | 
							
								                /bin/ip addr add 192.168.1.2/24 dev eth1
							 | 
						||
| 
								 | 
							
								              '';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								              # Example configuration for OpenVPN
							 | 
						||
| 
								 | 
							
								              # This is the main reason for this test
							 | 
						||
| 
								 | 
							
								              openvpn = {
							 | 
						||
| 
								 | 
							
								                enable = true;
							 | 
						||
| 
								 | 
							
								                configuration = "${./initrd.ovpn}";
							 | 
						||
| 
								 | 
							
								              };
							 | 
						||
| 
								 | 
							
								            };
							 | 
						||
| 
								 | 
							
								          };
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      # VPN server and gateway for ovpnclient between vlan 1 and 2
							 | 
						||
| 
								 | 
							
								      ovpnserver =
							 | 
						||
| 
								 | 
							
								        { ... }:
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								          virtualisation.vlans = [ 1 2 ];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          # Enable NAT and forward port 12345 to port 1234
							 | 
						||
| 
								 | 
							
								          networking.nat = {
							 | 
						||
| 
								 | 
							
								            enable = true;
							 | 
						||
| 
								 | 
							
								            internalInterfaces = [ "tun0" ];
							 | 
						||
| 
								 | 
							
								            externalInterface = "eth2";
							 | 
						||
| 
								 | 
							
								            forwardPorts = [ { destination = "10.8.0.2:1234";
							 | 
						||
| 
								 | 
							
								                               sourcePort = 12345; } ];
							 | 
						||
| 
								 | 
							
								          };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          # Trust tun0 and allow the VPN Server to be reached
							 | 
						||
| 
								 | 
							
								          networking.firewall = {
							 | 
						||
| 
								 | 
							
								            trustedInterfaces = [ "tun0" ];
							 | 
						||
| 
								 | 
							
								            allowedUDPPorts = [ 1194 ];
							 | 
						||
| 
								 | 
							
								          };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          # Minimal OpenVPN server configuration
							 | 
						||
| 
								 | 
							
								          services.openvpn.servers.testserver =
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								            config = ''
							 | 
						||
| 
								 | 
							
								              dev tun0
							 | 
						||
| 
								 | 
							
								              ifconfig 10.8.0.1 10.8.0.2
							 | 
						||
| 
								 | 
							
								              ${secretblock}
							 | 
						||
| 
								 | 
							
								            '';
							 | 
						||
| 
								 | 
							
								          };
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      # Client that resides in the "external" VLAN
							 | 
						||
| 
								 | 
							
								      testclient =
							 | 
						||
| 
								 | 
							
								        { ... }:
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								          virtualisation.vlans = [ 2 ];
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  testScript =
							 | 
						||
| 
								 | 
							
								    ''
							 | 
						||
| 
								 | 
							
								      # Minimal test case, checks whether enabling (with invalid config) harms
							 | 
						||
| 
								 | 
							
								      # the boot process
							 | 
						||
| 
								 | 
							
								      with subtest("Check for successful boot with broken openvpn config"):
							 | 
						||
| 
								 | 
							
								          minimalboot.start()
							 | 
						||
| 
								 | 
							
								          # If we get to multi-user.target, we booted successfully
							 | 
						||
| 
								 | 
							
								          minimalboot.wait_for_unit("multi-user.target")
							 | 
						||
| 
								 | 
							
								          minimalboot.shutdown()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      # Elaborated test case where the ovpnclient (where this module is used)
							 | 
						||
| 
								 | 
							
								      # can be reached by testclient only over ovpnserver.
							 | 
						||
| 
								 | 
							
								      # This is an indirect test for success.
							 | 
						||
| 
								 | 
							
								      with subtest("Check for connection from initrd VPN client, config as file"):
							 | 
						||
| 
								 | 
							
								          ovpnserver.start()
							 | 
						||
| 
								 | 
							
								          testclient.start()
							 | 
						||
| 
								 | 
							
								          ovpnclient.start()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          # Wait until the OpenVPN Server is available
							 | 
						||
| 
								 | 
							
								          ovpnserver.wait_for_unit("openvpn-testserver.service")
							 | 
						||
| 
								 | 
							
								          ovpnserver.succeed("ping -c 1 10.8.0.1")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          # Wait for the client to connect
							 | 
						||
| 
								 | 
							
								          ovpnserver.wait_until_succeeds("ping -c 1 10.8.0.2")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          # Wait until the testclient has network
							 | 
						||
| 
								 | 
							
								          testclient.wait_for_unit("network.target")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          # Check that ovpnclient is reachable over vlan 1
							 | 
						||
| 
								 | 
							
								          ovpnserver.succeed("nc -w 2 192.168.1.2 1234 | grep -q TESTVALUE")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          # Check that ovpnclient is reachable over tun0
							 | 
						||
| 
								 | 
							
								          ovpnserver.succeed("nc -w 2 10.8.0.2 1234 | grep -q TESTVALUE")
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          # Check that ovpnclient is reachable from testclient over the gateway
							 | 
						||
| 
								 | 
							
								          testclient.succeed("nc -w 2 192.168.2.3 12345 | grep -q TESTVALUE")
							 | 
						||
| 
								 | 
							
								    '';
							 | 
						||
| 
								 | 
							
								})
							 |