at 23.05-pre 4.5 kB view raw
1# This is a simple distributed test involving a topology with two 2# separate virtual networks - the "inside" and the "outside" - with a 3# client on the inside network, a server on the outside network, and a 4# router connected to both that performs Network Address Translation 5# for the client. 6import ./make-test-python.nix ({ pkgs, lib, withFirewall, withConntrackHelpers ? false, ... }: 7 let 8 unit = if withFirewall then "firewall" else "nat"; 9 10 routerBase = 11 lib.mkMerge [ 12 { virtualisation.vlans = [ 2 1 ]; 13 networking.firewall.enable = withFirewall; 14 networking.nat.internalIPs = [ "192.168.1.0/24" ]; 15 networking.nat.externalInterface = "eth1"; 16 } 17 (lib.optionalAttrs withConntrackHelpers { 18 networking.firewall.connectionTrackingModules = [ "ftp" ]; 19 networking.firewall.autoLoadConntrackHelpers = true; 20 }) 21 ]; 22 in 23 { 24 name = "nat" + (if withFirewall then "WithFirewall" else "Standalone") 25 + (lib.optionalString withConntrackHelpers "withConntrackHelpers"); 26 meta = with pkgs.lib.maintainers; { 27 maintainers = [ eelco rob ]; 28 }; 29 30 nodes = 31 { client = 32 { pkgs, nodes, ... }: 33 lib.mkMerge [ 34 { virtualisation.vlans = [ 1 ]; 35 networking.defaultGateway = 36 (pkgs.lib.head nodes.router.config.networking.interfaces.eth2.ipv4.addresses).address; 37 } 38 (lib.optionalAttrs withConntrackHelpers { 39 networking.firewall.connectionTrackingModules = [ "ftp" ]; 40 networking.firewall.autoLoadConntrackHelpers = true; 41 }) 42 ]; 43 44 router = 45 { ... }: lib.mkMerge [ 46 routerBase 47 { networking.nat.enable = true; } 48 ]; 49 50 routerDummyNoNat = 51 { ... }: lib.mkMerge [ 52 routerBase 53 { networking.nat.enable = false; } 54 ]; 55 56 server = 57 { ... }: 58 { virtualisation.vlans = [ 2 ]; 59 networking.firewall.enable = false; 60 services.httpd.enable = true; 61 services.httpd.adminAddr = "foo@example.org"; 62 services.vsftpd.enable = true; 63 services.vsftpd.anonymousUser = true; 64 }; 65 }; 66 67 testScript = 68 { nodes, ... }: let 69 routerDummyNoNatClosure = nodes.routerDummyNoNat.config.system.build.toplevel; 70 routerClosure = nodes.router.config.system.build.toplevel; 71 in '' 72 client.start() 73 router.start() 74 server.start() 75 76 # The router should have access to the server. 77 server.wait_for_unit("network.target") 78 server.wait_for_unit("httpd") 79 router.wait_for_unit("network.target") 80 router.succeed("curl --fail http://server/ >&2") 81 82 # The client should be also able to connect via the NAT router. 83 router.wait_for_unit("${unit}") 84 client.wait_for_unit("network.target") 85 client.succeed("curl --fail http://server/ >&2") 86 client.succeed("ping -c 1 server >&2") 87 88 # Test whether passive FTP works. 89 server.wait_for_unit("vsftpd") 90 server.succeed("echo Hello World > /home/ftp/foo.txt") 91 client.succeed("curl -v ftp://server/foo.txt >&2") 92 93 # Test whether active FTP works. 94 client.${if withConntrackHelpers then "succeed" else "fail"}("curl -v -P - ftp://server/foo.txt >&2") 95 96 # Test ICMP. 97 client.succeed("ping -c 1 router >&2") 98 router.succeed("ping -c 1 client >&2") 99 100 # If we turn off NAT, the client shouldn't be able to reach the server. 101 router.succeed( 102 "${routerDummyNoNatClosure}/bin/switch-to-configuration test 2>&1" 103 ) 104 client.fail("curl --fail --connect-timeout 5 http://server/ >&2") 105 client.fail("ping -c 1 server >&2") 106 107 # And make sure that reloading the NAT job works. 108 router.succeed( 109 "${routerClosure}/bin/switch-to-configuration test 2>&1" 110 ) 111 # FIXME: this should not be necessary, but nat.service is not started because 112 # network.target is not triggered 113 # (https://github.com/NixOS/nixpkgs/issues/16230#issuecomment-226408359) 114 ${lib.optionalString (!withFirewall) '' 115 router.succeed("systemctl start nat.service") 116 ''} 117 client.succeed("curl --fail http://server/ >&2") 118 client.succeed("ping -c 1 server >&2") 119 ''; 120 })