vuls: init at 0.27.0
[NixPkgs.git] / nixos / tests / bittorrent.nix
blob83d9168a6fa59148fcc9b8f60eea92e634dcddf8
1 # This test runs a Bittorrent tracker on one machine, and verifies
2 # that two client machines can download the torrent using
3 # `transmission'.  The first client (behind a NAT router) downloads
4 # from the initial seeder running on the tracker.  Then we kill the
5 # initial seeder.  The second client downloads from the first client,
6 # which only works if the first client successfully uses the UPnP-IGD
7 # protocol to poke a hole in the NAT.
9 import ./make-test-python.nix (
10   { pkgs, ... }:
12   let
14     # Some random file to serve.
15     file = pkgs.hello.src;
17     internalRouterAddress = "192.168.3.1";
18     internalClient1Address = "192.168.3.2";
19     externalRouterAddress = "80.100.100.1";
20     externalClient2Address = "80.100.100.2";
21     externalTrackerAddress = "80.100.100.3";
23     download-dir = "/var/lib/transmission/Downloads";
24     transmissionConfig =
25       { pkgs, ... }:
26       {
27         environment.systemPackages = [ pkgs.transmission_3 ];
28         services.transmission = {
29           enable = true;
30           settings = {
31             dht-enabled = false;
32             message-level = 2;
33             inherit download-dir;
34           };
35         };
36       };
37   in
39   {
40     name = "bittorrent";
41     meta = with pkgs.lib.maintainers; {
42       maintainers = [
43         domenkozar
44         rob
45         bobvanderlinden
46       ];
47     };
49     nodes = {
50       tracker =
51         { pkgs, ... }:
52         {
53           imports = [ transmissionConfig ];
55           virtualisation.vlans = [ 1 ];
56           networking.firewall.enable = false;
57           networking.interfaces.eth1.ipv4.addresses = [
58             {
59               address = externalTrackerAddress;
60               prefixLength = 24;
61             }
62           ];
64           # We need Apache on the tracker to serve the torrents.
65           services.httpd = {
66             enable = true;
67             virtualHosts = {
68               "torrentserver.org" = {
69                 adminAddr = "foo@example.org";
70                 documentRoot = "/tmp";
71               };
72             };
73           };
74           services.opentracker.enable = true;
75         };
77       router =
78         { pkgs, nodes, ... }:
79         {
80           virtualisation.vlans = [
81             1
82             2
83           ];
84           networking.nat.enable = true;
85           networking.nat.internalInterfaces = [ "eth2" ];
86           networking.nat.externalInterface = "eth1";
87           networking.firewall.enable = true;
88           networking.firewall.trustedInterfaces = [ "eth2" ];
89           networking.interfaces.eth0.ipv4.addresses = [ ];
90           networking.interfaces.eth1.ipv4.addresses = [
91             {
92               address = externalRouterAddress;
93               prefixLength = 24;
94             }
95           ];
96           networking.interfaces.eth2.ipv4.addresses = [
97             {
98               address = internalRouterAddress;
99               prefixLength = 24;
100             }
101           ];
102           services.miniupnpd = {
103             enable = true;
104             externalInterface = "eth1";
105             internalIPs = [ "eth2" ];
106             appendConfig = ''
107               ext_ip=${externalRouterAddress}
108             '';
109           };
110         };
112       client1 =
113         { pkgs, nodes, ... }:
114         {
115           imports = [ transmissionConfig ];
116           environment.systemPackages = [ pkgs.miniupnpc ];
118           virtualisation.vlans = [ 2 ];
119           networking.interfaces.eth0.ipv4.addresses = [ ];
120           networking.interfaces.eth1.ipv4.addresses = [
121             {
122               address = internalClient1Address;
123               prefixLength = 24;
124             }
125           ];
126           networking.defaultGateway = internalRouterAddress;
127           networking.firewall.enable = false;
128         };
130       client2 =
131         { pkgs, ... }:
132         {
133           imports = [ transmissionConfig ];
135           virtualisation.vlans = [ 1 ];
136           networking.interfaces.eth0.ipv4.addresses = [ ];
137           networking.interfaces.eth1.ipv4.addresses = [
138             {
139               address = externalClient2Address;
140               prefixLength = 24;
141             }
142           ];
143           networking.firewall.enable = false;
144         };
145     };
147     testScript =
148       { nodes, ... }:
149       ''
150         start_all()
152         # Wait for network and miniupnpd.
153         router.systemctl("start network-online.target")
154         router.wait_for_unit("network-online.target")
155         router.wait_for_unit("miniupnpd")
157         # Create the torrent.
158         tracker.succeed("mkdir ${download-dir}/data")
159         tracker.succeed(
160             "cp ${file} ${download-dir}/data/test.tar.bz2"
161         )
162         tracker.succeed(
163             "transmission-create ${download-dir}/data/test.tar.bz2 --private --tracker http://${externalTrackerAddress}:6969/announce --outfile /tmp/test.torrent"
164         )
165         tracker.succeed("chmod 644 /tmp/test.torrent")
167         # Start the tracker.  !!! use a less crappy tracker
168         tracker.systemctl("start network-online.target")
169         tracker.wait_for_unit("network-online.target")
170         tracker.wait_for_unit("opentracker.service")
171         tracker.wait_for_open_port(6969)
173         # Start the initial seeder.
174         tracker.succeed(
175             "transmission-remote --add /tmp/test.torrent --no-portmap --no-dht --download-dir ${download-dir}/data"
176         )
178         # Now we should be able to download from the client behind the NAT.
179         tracker.wait_for_unit("httpd")
180         client1.systemctl("start network-online.target")
181         client1.wait_for_unit("network-online.target")
182         client1.succeed("transmission-remote --add http://${externalTrackerAddress}/test.torrent >&2 &")
183         client1.wait_for_file("${download-dir}/test.tar.bz2")
184         client1.succeed(
185             "cmp ${download-dir}/test.tar.bz2 ${file}"
186         )
188         # Bring down the initial seeder.
189         tracker.stop_job("transmission")
191         # Now download from the second client.  This can only succeed if
192         # the first client created a NAT hole in the router.
193         client2.systemctl("start network-online.target")
194         client2.wait_for_unit("network-online.target")
195         client2.succeed(
196             "transmission-remote --add http://${externalTrackerAddress}/test.torrent --no-portmap --no-dht >&2 &"
197         )
198         client2.wait_for_file("${download-dir}/test.tar.bz2")
199         client2.succeed(
200             "cmp ${download-dir}/test.tar.bz2 ${file}"
201         )
202       '';
203   }