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