diff options
Diffstat (limited to 'nixos')
-rw-r--r-- | nixos/modules/services/networking/cjdns.nix | 48 | ||||
-rw-r--r-- | nixos/release.nix | 1 | ||||
-rw-r--r-- | nixos/tests/cjdns.nix | 123 |
3 files changed, 148 insertions, 24 deletions
diff --git a/nixos/modules/services/networking/cjdns.nix b/nixos/modules/services/networking/cjdns.nix index 9888419309c1..be0acb27324a 100644 --- a/nixos/modules/services/networking/cjdns.nix +++ b/nixos/modules/services/networking/cjdns.nix @@ -204,8 +204,29 @@ in systemd.services.cjdns = { description = "encrypted networking for everybody"; - wantedBy = [ "multi-user.target" ]; - after = [ "network-interfaces.target" ]; + wantedBy = [ "network.target" ]; + after = [ "networkSetup.service" "network-interfaces.target" ]; + + preStart = if cfg.confFile != "" then "" else '' + [ -e /etc/cjdns.keys ] && source /etc/cjdns.keys + + if [ -z "$CJDNS_PRIVATE_KEY" ]; then + shopt -s lastpipe + ${pkg}/bin/makekeys | { read private ipv6 public; } + + umask 0077 + echo "CJDNS_PRIVATE_KEY=$private" >> /etc/cjdns.keys + echo -e "CJDNS_IPV6=$ipv6\nCJDNS_PUBLIC_KEY=$public" > /etc/cjdns.public + + chmod 600 /etc/cjdns.keys + chmod 444 /etc/cjdns.public + fi + + if [ -z "$CJDNS_ADMIN_PASSWORD" ]; then + echo "CJDNS_ADMIN_PASSWORD=$(${pkgs.coreutils}/bin/head -c 96 /dev/urandom | ${pkgs.coreutils}/bin/tr -dc A-Za-z0-9)" \ + >> /etc/cjdns.keys + fi + ''; script = ( if cfg.confFile != "" then "${pkg}/bin/cjdroute < ${cfg.confFile}" else @@ -224,27 +245,6 @@ in }; }; - system.activationScripts.cjdns = if (cfg.confFile == "") then "" else '' - cjdnsWriteKeys() { - private=$1 - ipv6=$2 - public=$3 - - echo "CJDNS_PRIVATE_KEY=$1" >> /etc/cjdns.keys - echo -e "CJDNS_IPV6=$2\nCJDNS_PUBLIC_KEY=$3" > /etc/cjdns.public - - chmod 600 /etc/cjdns.keys - chmod 444 /etc/cjdns.public - } - - grep -q "CJDNS_PRIVATE_KEY=" /etc/cjdns.keys || \ - cjdnsWriteKeys $(${pkg}/bin/makekeys) - - grep -q "CJDNS_ADMIN_PASSWORD=" /etc/cjdns.keys || \ - echo "CJDNS_ADMIN_PASSWORD=$(${pkgs.coreutils}/bin/head -c 96 /dev/urandom | ${pkgs.coreutils}/bin/tr -dc A-Za-z0-9)" \ - >> /etc/cjdns.keys - ''; - networking.extraHosts = "${cjdnsHosts}"; assertions = [ @@ -258,4 +258,4 @@ in }; -}
\ No newline at end of file +} diff --git a/nixos/release.nix b/nixos/release.nix index cb79dd3a226b..5a89b38acc77 100644 --- a/nixos/release.nix +++ b/nixos/release.nix @@ -235,6 +235,7 @@ in rec { tests.avahi = callTest tests/avahi.nix {}; tests.bittorrent = callTest tests/bittorrent.nix {}; tests.blivet = callTest tests/blivet.nix {}; + tests.cjdns = callTest tests/cjdns.nix {}; tests.containers = callTest tests/containers.nix {}; tests.firefox = callTest tests/firefox.nix {}; tests.firewall = callTest tests/firewall.nix {}; diff --git a/nixos/tests/cjdns.nix b/nixos/tests/cjdns.nix new file mode 100644 index 000000000000..7bb3863c683f --- /dev/null +++ b/nixos/tests/cjdns.nix @@ -0,0 +1,123 @@ +let + carolKey = "2d2a338b46f8e4a8c462f0c385b481292a05f678e19a2b82755258cf0f0af7e2"; + carolPubKey = "n932l3pjvmhtxxcdrqq2qpw5zc58f01vvjx01h4dtd1bb0nnu2h0.k"; + carolPassword = "678287829ce4c67bc8b227e56d94422ee1b85fa11618157b2f591de6c6322b52"; + carolIp4 = "192.168.0.9"; + + basicConfig = + { config, pkgs, ... }: + { services.cjdns.enable = true; + + # Turning off DHCP isn't very realistic but makes + # the sequence of address assignment less stochastic. + networking.useDHCP = false; + + networking.interfaces.eth1.prefixLength = 24; + # CJDNS output is incompatible with the XML log. + systemd.services.cjdns.serviceConfig.StandardOutput = "null"; + #networking.firewall.enable = true; + networking.firewall.allowPing = true; + #networking.firewall.rejectPackets = true; + }; + +in + +import ./make-test.nix { + name = "cjdns"; + + nodes = rec + { # Alice finds peers over over ETHInterface. + alice = + { config, ... }: + { imports = [ basicConfig ]; + + services.cjdns.ETHInterface.bind = "eth1"; + + services.httpd.enable = true; + services.httpd.adminAddr = "foo@example.org"; + networking.firewall.allowedTCPPorts = [ 80 ]; + }; + + # Bob explicitly connects to Carol over UDPInterface. + bob = + { config, lib, nodes, ... }: + + let carolIp4 = lib.mkForce nodes.carol.config.networking.interfaces.eth1; in + + { imports = [ basicConfig ]; + + networking.interfaces.eth1.ipAddress = "192.168.0.2"; + + services.cjdns = + { UDPInterface = + { bind = "0.0.0.0:1024"; + connectTo."192.168.0.1:1024}" = + { hostname = "carol.hype"; + password = carolPassword; + publicKey = carolPubKey; + }; + }; + }; + }; + + # Carol listens on ETHInterface and UDPInterface, + # but knows neither Alice or Bob. + carol = + { config, lib, nodes, ... }: + let + carolIp4 = (lib.mkForce nodes.carol.config.networking.interfaces.eth1); + in + { imports = [ basicConfig ]; + + environment.etc."cjdns.keys".text = '' + CJDNS_PRIVATE_KEY=${carolKey} + CJDNS_ADMIN_PASSWORD=FOOBAR + ''; + + networking.interfaces.eth1.ipAddress = "192.168.0.1"; + + services.cjdns = + { authorizedPasswords = [ carolPassword ]; + ETHInterface.bind = "eth1"; + UDPInterface.bind = "192.168.0.1:1024"; + }; + networking.firewall.allowedUDPPorts = [ 1024 ]; + }; + + }; + + testScript = + '' + startAll; + + $alice->waitForUnit("cjdns.service"); + $bob->waitForUnit("cjdns.service"); + $carol->waitForUnit("cjdns.service"); + + sub cjdnsIp { + my ($machine) = @_; + my $ip = (split /[ \/]+/, $machine->succeed("ip -o -6 addr show dev tun0"))[3]; + $machine->log("has ip $ip"); + return $ip; + } + + my $aliceIp6 = cjdnsIp $alice; + my $bobIp6 = cjdnsIp $bob; + my $carolIp6 = cjdnsIp $carol; + + # ping a few times each to let the routing table establish itself + + $alice->succeed("ping6 -c 4 $carolIp6"); + $bob->succeed("ping6 -c 4 carol.hype"); + + $carol->succeed("ping6 -c 4 $aliceIp6"); + $carol->succeed("ping6 -c 4 $bobIp6"); + + $alice->succeed("ping6 -c 4 $bobIp6"); + $bob->succeed("ping6 -c 4 $aliceIp6"); + + $alice->waitForUnit("httpd.service"); + + $bob->succeed("curl --fail -g http://[$aliceIp6]"); + ''; +} |