summary refs log tree commit diff
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2011-03-10 12:08:39 +0000
committerEelco Dolstra <eelco.dolstra@logicblox.com>2011-03-10 12:08:39 +0000
commit9bf4ac079ec08f68d825982cc15ab2b8f4ab664e (patch)
treee7086c567fbf3be5859967128953f738b617945a
parente2e7b689b47c70580af87f64a5b1e9cd5a5cc835 (diff)
downloadnixpkgs-9bf4ac079ec08f68d825982cc15ab2b8f4ab664e.tar
nixpkgs-9bf4ac079ec08f68d825982cc15ab2b8f4ab664e.tar.gz
nixpkgs-9bf4ac079ec08f68d825982cc15ab2b8f4ab664e.tar.bz2
nixpkgs-9bf4ac079ec08f68d825982cc15ab2b8f4ab664e.tar.lz
nixpkgs-9bf4ac079ec08f68d825982cc15ab2b8f4ab664e.tar.xz
nixpkgs-9bf4ac079ec08f68d825982cc15ab2b8f4ab664e.tar.zst
nixpkgs-9bf4ac079ec08f68d825982cc15ab2b8f4ab664e.zip
* Add a module for doing Network Address Translation.
svn path=/nixos/trunk/; revision=26246
-rw-r--r--modules/module-list.nix1
-rw-r--r--modules/services/networking/nat.nix95
-rw-r--r--tests/nat.nix39
3 files changed, 118 insertions, 17 deletions
diff --git a/modules/module-list.nix b/modules/module-list.nix
index 5c1f3deab4c..453d09653fb 100644
--- a/modules/module-list.nix
+++ b/modules/module-list.nix
@@ -99,6 +99,7 @@
   ./services/networking/gw6c.nix
   ./services/networking/ifplugd.nix
   ./services/networking/ircd-hybrid.nix
+  ./services/networking/nat.nix
   ./services/networking/ntpd.nix
   ./services/networking/openfire.nix
   ./services/networking/openvpn.nix
diff --git a/modules/services/networking/nat.nix b/modules/services/networking/nat.nix
new file mode 100644
index 00000000000..2f9715e9fab
--- /dev/null
+++ b/modules/services/networking/nat.nix
@@ -0,0 +1,95 @@
+# This module enables Network Address Translation (NAT).
+
+{ config, pkgs, ... }:
+
+with pkgs.lib;
+
+let
+
+  cfg = config.networking.nat;
+
+in
+
+{
+
+  ###### interface
+
+  options = {
+  
+    networking.nat.enable = mkOption {
+      default = false;
+      description =
+        ''
+          Whether to enable Network Address Translation (NAT).
+        '';
+    };
+  
+    networking.nat.internalIPs = mkOption {
+      example = "192.168.1.0/24";
+      description =
+        ''
+          The IP address range for which to perform NAT.  Packets
+          coming from these addresses and destined for the external
+          interface will be rewritten.
+        '';
+    };
+  
+    networking.nat.externalInterface = mkOption {
+      example = "eth1";
+      description =
+        ''
+          The name of the external network interface.
+        '';
+    };
+  
+    networking.nat.externalIP = mkOption {
+      default = "";
+      example = "203.0.113.123";
+      description =
+        ''
+          The public IP address to which packets from the local
+          network are to be rewritten.  If this is left empty, the
+          IP address associated with the external interface will be
+          used.
+        '';
+    };
+  
+  };
+
+
+  ###### implementation
+
+  config = mkIf config.networking.nat.enable {
+
+    environment.systemPackages = [ pkgs.iptables ];
+
+    jobs.nat =
+      { description = "Network Address Translation";
+
+        startOn = "started network-interfaces";
+
+        path = [ pkgs.iptables ];
+
+        preStart =
+          ''
+            iptables -t nat -F
+            iptables -t nat -X
+
+            iptables -t nat -A POSTROUTING \
+              -s ${cfg.internalIPs} -o ${cfg.externalInterface} \
+              ${if cfg.externalIP == ""
+                then "-j MASQUERADE"
+                else "-j SNAT --to-source ${cfg.externalIP}"}
+
+            echo 1 > /proc/sys/net/ipv4/ip_forward
+          '';
+
+        postStop =
+          ''
+            iptables -t nat -F
+          '';
+      };
+
+  };
+
+}
diff --git a/tests/nat.nix b/tests/nat.nix
index 88aa609774f..6b0c7306bd9 100644
--- a/tests/nat.nix
+++ b/tests/nat.nix
@@ -19,7 +19,9 @@
       router = 
         { config, pkgs, ... }:
         { virtualisation.vlans = [ 2 1 ];
-          environment.systemPackages = [ pkgs.iptables ];
+          networking.nat.enable = true;
+          networking.nat.internalIPs = "192.168.1.0/24";
+          networking.nat.externalInterface = "eth1";
         };
 
       server = 
@@ -37,22 +39,25 @@
 
       # The router should have access to the server.
       $server->waitForJob("httpd");
-      $router->mustSucceed("curl --fail http://server/ >&2");
-
-      # But the client shouldn't be able to reach the server.
-      $client->mustFail("curl --fail --connect-timeout 5 http://server/ >&2");
-
-      # Enable NAT on the router.
-      $router->mustSucceed(
-          "iptables -t nat -F",
-          "iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -d 192.168.1.0/24 -j ACCEPT",
-          "iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -j SNAT "
-          . "--to-source ${nodes.router.config.networking.ifaces.eth1.ipAddress}",
-          "echo 1 > /proc/sys/net/ipv4/ip_forward"
-      );
-
-      # Now the client should be able to connect.
-      $client->mustSucceed("curl --fail http://server/ >&2");
+      $router->succeed("curl --fail http://server/ >&2");
+
+      # The client should be also able to connect via the NAT router.
+      $router->waitForJob("nat");
+      $client->succeed("curl --fail http://server/ >&2");
+      $client->succeed("ping -c 1 server >&2");
+      
+      # If we turn off NAT, the client shouldn't be able to reach the server.
+      $router->succeed("stop nat");
+      $client->fail("curl --fail --connect-timeout 5 http://server/ >&2");
+      $client->fail("ping -c 1 server >&2");
+
+      # And make sure that restarting the NAT job works.
+      $router->succeed("start nat");
+      $client->succeed("curl --fail http://server/ >&2");
+      $client->succeed("ping -c 1 server >&2");
+
+      $client->succeed("ping -c 1 router >&2");
+      $router->succeed("ping -c 1 client >&2");
     '';
 
 }