summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--nixos/modules/services/networking/miniupnpd.nix24
-rw-r--r--nixos/release.nix1
-rw-r--r--nixos/tests/bittorrent.nix101
-rw-r--r--nixos/tests/upnp.nix94
-rw-r--r--pkgs/tools/networking/miniupnpd/default.nix16
5 files changed, 178 insertions, 58 deletions
diff --git a/nixos/modules/services/networking/miniupnpd.nix b/nixos/modules/services/networking/miniupnpd.nix
index 19400edb68f9..ab714a6ac75e 100644
--- a/nixos/modules/services/networking/miniupnpd.nix
+++ b/nixos/modules/services/networking/miniupnpd.nix
@@ -57,32 +57,12 @@ in
};
config = mkIf cfg.enable {
- # from miniupnpd/netfilter/iptables_init.sh
networking.firewall.extraCommands = ''
- iptables -t nat -N MINIUPNPD
- iptables -t nat -A PREROUTING -i ${cfg.externalInterface} -j MINIUPNPD
- iptables -t mangle -N MINIUPNPD
- iptables -t mangle -A PREROUTING -i ${cfg.externalInterface} -j MINIUPNPD
- iptables -t filter -N MINIUPNPD
- iptables -t filter -A FORWARD -i ${cfg.externalInterface} ! -o ${cfg.externalInterface} -j MINIUPNPD
- iptables -t nat -N MINIUPNPD-PCP-PEER
- iptables -t nat -A POSTROUTING -o ${cfg.externalInterface} -j MINIUPNPD-PCP-PEER
+ ${pkgs.bash}/bin/bash -x ${pkgs.miniupnpd}/etc/miniupnpd/iptables_init.sh -i ${cfg.externalInterface}
'';
- # from miniupnpd/netfilter/iptables_removeall.sh
networking.firewall.extraStopCommands = ''
- iptables -t nat -F MINIUPNPD
- iptables -t nat -D PREROUTING -i ${cfg.externalInterface} -j MINIUPNPD
- iptables -t nat -X MINIUPNPD
- iptables -t mangle -F MINIUPNPD
- iptables -t mangle -D PREROUTING -i ${cfg.externalInterface} -j MINIUPNPD
- iptables -t mangle -X MINIUPNPD
- iptables -t filter -F MINIUPNPD
- iptables -t filter -D FORWARD -i ${cfg.externalInterface} ! -o ${cfg.externalInterface} -j MINIUPNPD
- iptables -t filter -X MINIUPNPD
- iptables -t nat -F MINIUPNPD-PCP-PEER
- iptables -t nat -D POSTROUTING -o ${cfg.externalInterface} -j MINIUPNPD-PCP-PEER
- iptables -t nat -X MINIUPNPD-PCP-PEER
+ ${pkgs.bash}/bin/bash -x ${pkgs.miniupnpd}/etc/miniupnpd/iptables_removeall.sh -i ${cfg.externalInterface}
'';
systemd.services.miniupnpd = {
diff --git a/nixos/release.nix b/nixos/release.nix
index 66dbf697c8a0..8016dba09152 100644
--- a/nixos/release.nix
+++ b/nixos/release.nix
@@ -250,6 +250,7 @@ in rec {
tests.acme = callTest tests/acme.nix {};
tests.avahi = callTest tests/avahi.nix {};
tests.beegfs = callTest tests/beegfs.nix {};
+ tests.upnp = callTest tests/upnp.nix {};
tests.bittorrent = callTest tests/bittorrent.nix {};
tests.bind = callTest tests/bind.nix {};
#tests.blivet = callTest tests/blivet.nix {}; # broken since 2017-07024
diff --git a/nixos/tests/bittorrent.nix b/nixos/tests/bittorrent.nix
index 609b1ff7a83a..8977be9b859f 100644
--- a/nixos/tests/bittorrent.nix
+++ b/nixos/tests/bittorrent.nix
@@ -13,57 +13,95 @@ let
# Some random file to serve.
file = pkgs.hello.src;
- miniupnpdConf = nodes: pkgs.writeText "miniupnpd.conf"
- ''
- ext_ifname=eth1
- listening_ip=${(pkgs.lib.head nodes.router.config.networking.interfaces.eth2.ipv4.addresses).address}/24
- allow 1024-65535 192.168.2.0/24 1024-65535
- '';
-
+ internalRouterAddress = "192.168.3.1";
+ internalClient1Address = "192.168.3.2";
+ externalRouterAddress = "80.100.100.1";
+ externalClient2Address = "80.100.100.2";
+ externalTrackerAddress = "80.100.100.3";
in
{
name = "bittorrent";
meta = with pkgs.stdenv.lib.maintainers; {
- maintainers = [ domenkozar eelco chaoflow rob wkennington ];
+ maintainers = [ domenkozar eelco chaoflow rob wkennington bobvanderlinden ];
};
nodes =
{ tracker =
{ pkgs, ... }:
- { environment.systemPackages = [ pkgs.transmission pkgs.opentracker ];
+ { environment.systemPackages = [ pkgs.transmission ];
+
+ virtualisation.vlans = [ 1 ];
+ networking.interfaces.eth1.ipv4.addresses = [
+ { address = externalTrackerAddress; prefixLength = 24; }
+ ];
# We need Apache on the tracker to serve the torrents.
services.httpd.enable = true;
services.httpd.adminAddr = "foo@example.org";
services.httpd.documentRoot = "/tmp";
- networking.firewall.enable = false; # FIXME: figure out what ports we actually need
+ networking.firewall.enable = false;
+
+ services.opentracker.enable = true;
+
+ services.transmission.enable = true;
+ services.transmission.settings.dht-enabled = false;
+ services.transmission.settings.port-forwaring-enabled = false;
};
router =
- { pkgs, ... }:
- { environment.systemPackages = [ pkgs.miniupnpd ];
- virtualisation.vlans = [ 1 2 ];
+ { pkgs, nodes, ... }:
+ { virtualisation.vlans = [ 1 2 ];
networking.nat.enable = true;
networking.nat.internalInterfaces = [ "eth2" ];
networking.nat.externalInterface = "eth1";
- networking.firewall.enable = false;
+ networking.firewall.enable = true;
+ networking.firewall.trustedInterfaces = [ "eth2" ];
+ networking.interfaces.eth0.ipv4.addresses = [];
+ networking.interfaces.eth1.ipv4.addresses = [
+ { address = externalRouterAddress; prefixLength = 24; }
+ ];
+ networking.interfaces.eth2.ipv4.addresses = [
+ { address = internalRouterAddress; prefixLength = 24; }
+ ];
+ services.miniupnpd = {
+ enable = true;
+ externalInterface = "eth1";
+ internalIPs = [ "eth2" ];
+ appendConfig = ''
+ ext_ip=${externalRouterAddress}
+ '';
+ };
};
client1 =
{ pkgs, nodes, ... }:
- { environment.systemPackages = [ pkgs.transmission ];
+ { environment.systemPackages = [ pkgs.transmission pkgs.miniupnpc ];
virtualisation.vlans = [ 2 ];
- networking.defaultGateway =
- (pkgs.lib.head nodes.router.config.networking.interfaces.eth2.ipv4.addresses).address;
+ networking.interfaces.eth0.ipv4.addresses = [];
+ networking.interfaces.eth1.ipv4.addresses = [
+ { address = internalClient1Address; prefixLength = 24; }
+ ];
+ networking.defaultGateway = internalRouterAddress;
networking.firewall.enable = false;
+ services.transmission.enable = true;
+ services.transmission.settings.dht-enabled = false;
+ services.transmission.settings.message-level = 3;
};
client2 =
{ pkgs, ... }:
{ environment.systemPackages = [ pkgs.transmission ];
+ virtualisation.vlans = [ 1 ];
+ networking.interfaces.eth0.ipv4.addresses = [];
+ networking.interfaces.eth1.ipv4.addresses = [
+ { address = externalClient2Address; prefixLength = 24; }
+ ];
networking.firewall.enable = false;
+ services.transmission.enable = true;
+ services.transmission.settings.dht-enabled = false;
+ services.transmission.settings.port-forwaring-enabled = false;
};
};
@@ -72,43 +110,38 @@ in
''
startAll;
- # Enable NAT on the router and start miniupnpd.
- $router->waitForUnit("nat");
- $router->succeed(
- "iptables -w -t nat -N MINIUPNPD",
- "iptables -w -t nat -A PREROUTING -i eth1 -j MINIUPNPD",
- "echo 1 > /proc/sys/net/ipv4/ip_forward",
- "miniupnpd -f ${miniupnpdConf nodes}"
- );
+ # Wait for network and miniupnpd.
+ $router->waitForUnit("network-online.target");
+ $router->waitForUnit("miniupnpd");
# Create the torrent.
$tracker->succeed("mkdir /tmp/data");
$tracker->succeed("cp ${file} /tmp/data/test.tar.bz2");
- $tracker->succeed("transmission-create /tmp/data/test.tar.bz2 -p -t http://${(pkgs.lib.head nodes.tracker.config.networking.interfaces.eth1.ipv4.addresses).address}:6969/announce -o /tmp/test.torrent");
+ $tracker->succeed("transmission-create /tmp/data/test.tar.bz2 --private --tracker http://${externalTrackerAddress}:6969/announce --outfile /tmp/test.torrent");
$tracker->succeed("chmod 644 /tmp/test.torrent");
# Start the tracker. !!! use a less crappy tracker
- $tracker->waitForUnit("network.target");
- $tracker->succeed("opentracker -p 6969 >&2 &");
+ $tracker->waitForUnit("network-online.target");
+ $tracker->waitForUnit("opentracker.service");
$tracker->waitForOpenPort(6969);
# Start the initial seeder.
- my $pid = $tracker->succeed("transmission-cli /tmp/test.torrent -M -w /tmp/data >&2 & echo \$!");
+ $tracker->succeed("transmission-remote --add /tmp/test.torrent --no-portmap --no-dht --download-dir /tmp/data");
# Now we should be able to download from the client behind the NAT.
$tracker->waitForUnit("httpd");
- $client1->waitForUnit("network.target");
- $client1->succeed("transmission-cli http://tracker/test.torrent -w /tmp >&2 &");
+ $client1->waitForUnit("network-online.target");
+ $client1->succeed("transmission-remote --add http://${externalTrackerAddress}/test.torrent --download-dir /tmp >&2 &");
$client1->waitForFile("/tmp/test.tar.bz2");
$client1->succeed("cmp /tmp/test.tar.bz2 ${file}");
# Bring down the initial seeder.
- $tracker->succeed("kill -9 $pid");
+ # $tracker->stopJob("transmission");
# Now download from the second client. This can only succeed if
# the first client created a NAT hole in the router.
- $client2->waitForUnit("network.target");
- $client2->succeed("transmission-cli http://tracker/test.torrent -M -w /tmp >&2 &");
+ $client2->waitForUnit("network-online.target");
+ $client2->succeed("transmission-remote --add http://${externalTrackerAddress}/test.torrent --no-portmap --no-dht --download-dir /tmp >&2 &");
$client2->waitForFile("/tmp/test.tar.bz2");
$client2->succeed("cmp /tmp/test.tar.bz2 ${file}");
'';
diff --git a/nixos/tests/upnp.nix b/nixos/tests/upnp.nix
new file mode 100644
index 000000000000..3f2dd13fb560
--- /dev/null
+++ b/nixos/tests/upnp.nix
@@ -0,0 +1,94 @@
+# This tests whether UPnP port mappings can be created using Miniupnpd
+# and Miniupnpc.
+# It runs a Miniupnpd service on one machine, and verifies
+# a client can indeed create a port mapping using Miniupnpc. If
+# this succeeds an external client will try to connect to the port
+# mapping.
+
+import ./make-test.nix ({ pkgs, ... }:
+
+let
+ internalRouterAddress = "192.168.3.1";
+ internalClient1Address = "192.168.3.2";
+ externalRouterAddress = "80.100.100.1";
+ externalClient2Address = "80.100.100.2";
+in
+{
+ name = "upnp";
+ meta = with pkgs.stdenv.lib.maintainers; {
+ maintainers = [ bobvanderlinden ];
+ };
+
+ nodes =
+ {
+ router =
+ { pkgs, nodes, ... }:
+ { virtualisation.vlans = [ 1 2 ];
+ networking.nat.enable = true;
+ networking.nat.internalInterfaces = [ "eth2" ];
+ networking.nat.externalInterface = "eth1";
+ networking.firewall.enable = true;
+ networking.firewall.trustedInterfaces = [ "eth2" ];
+ networking.interfaces.eth1.ipv4.addresses = [
+ { address = externalRouterAddress; prefixLength = 24; }
+ ];
+ networking.interfaces.eth2.ipv4.addresses = [
+ { address = internalRouterAddress; prefixLength = 24; }
+ ];
+ services.miniupnpd = {
+ enable = true;
+ externalInterface = "eth1";
+ internalIPs = [ "eth2" ];
+ appendConfig = ''
+ ext_ip=${externalRouterAddress}
+ '';
+ };
+ };
+
+ client1 =
+ { pkgs, nodes, ... }:
+ { environment.systemPackages = [ pkgs.miniupnpc pkgs.netcat ];
+ virtualisation.vlans = [ 2 ];
+ networking.defaultGateway = internalRouterAddress;
+ networking.interfaces.eth1.ipv4.addresses = [
+ { address = internalClient1Address; prefixLength = 24; }
+ ];
+ networking.firewall.enable = false;
+
+ services.httpd.enable = true;
+ services.httpd.listen = [{ ip = "*"; port = 9000; }];
+ services.httpd.adminAddr = "foo@example.org";
+ services.httpd.documentRoot = "/tmp";
+ };
+
+ client2 =
+ { pkgs, ... }:
+ { environment.systemPackages = [ pkgs.miniupnpc ];
+ virtualisation.vlans = [ 1 ];
+ networking.interfaces.eth1.ipv4.addresses = [
+ { address = externalClient2Address; prefixLength = 24; }
+ ];
+ networking.firewall.enable = false;
+ };
+ };
+
+ testScript =
+ { nodes, ... }:
+ ''
+ startAll;
+
+ # Wait for network and miniupnpd.
+ $router->waitForUnit("network-online.target");
+ # $router->waitForUnit("nat");
+ $router->waitForUnit("firewall.service");
+ $router->waitForUnit("miniupnpd");
+
+ $client1->waitForUnit("network-online.target");
+
+ $client1->succeed("upnpc -a ${internalClient1Address} 9000 9000 TCP");
+
+ $client1->waitForUnit("httpd");
+ $client2->waitUntilSucceeds("curl http://${externalRouterAddress}:9000/");
+ '';
+
+})
diff --git a/pkgs/tools/networking/miniupnpd/default.nix b/pkgs/tools/networking/miniupnpd/default.nix
index f794a4e27c7a..f3cd9ea6a819 100644
--- a/pkgs/tools/networking/miniupnpd/default.nix
+++ b/pkgs/tools/networking/miniupnpd/default.nix
@@ -1,5 +1,10 @@
-{ stdenv, fetchurl, iptables, libuuid, pkgconfig }:
+{ stdenv, lib, fetchurl, iptables, libuuid, pkgconfig
+, which, iproute, gnused, coreutils, gawk, makeWrapper
+}:
+let
+ scriptBinEnv = lib.makeBinPath [ which iproute iptables gnused coreutils gawk ];
+in
stdenv.mkDerivation rec {
name = "miniupnpd-2.1";
@@ -10,7 +15,7 @@ stdenv.mkDerivation rec {
};
buildInputs = [ iptables libuuid ];
- nativeBuildInputs= [ pkgconfig ];
+ nativeBuildInputs= [ pkgconfig makeWrapper ];
makefile = "Makefile.linux";
@@ -18,6 +23,13 @@ stdenv.mkDerivation rec {
installFlags = [ "PREFIX=$(out)" "INSTALLPREFIX=$(out)" ];
+ postFixup = ''
+ for script in $out/etc/miniupnpd/ip{,6}tables_{init,removeall}.sh
+ do
+ wrapProgram $script --set PATH '${scriptBinEnv}:$PATH'
+ done
+ '';
+
meta = with stdenv.lib; {
homepage = http://miniupnp.free.fr/;
description = "A daemon that implements the UPnP Internet Gateway Device (IGD) specification";