summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--nixos/modules/services/networking/cjdns.nix48
-rw-r--r--nixos/release.nix1
-rw-r--r--nixos/tests/cjdns.nix123
-rw-r--r--pkgs/tools/networking/cjdns/default.nix3
-rw-r--r--pkgs/tools/networking/cjdns/makekeys-sigpipe.patch29
5 files changed, 180 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]");
+ '';
+}
diff --git a/pkgs/tools/networking/cjdns/default.nix b/pkgs/tools/networking/cjdns/default.nix
index c32bc224bdde..cbaca948b2b2 100644
--- a/pkgs/tools/networking/cjdns/default.nix
+++ b/pkgs/tools/networking/cjdns/default.nix
@@ -14,6 +14,9 @@ stdenv.mkDerivation {
sha256 = "11z8dk7byxh9pfv7mhfvnk465qln1g7z8c8f822623d59lwjpbs1";
};
+ # Make the NixOS service work a little better.
+ patches = [ ./makekeys-sigpipe.patch ];
+
buildInputs = [ which python27 nodejs ] ++
# for flock
stdenv.lib.optional stdenv.isLinux [ utillinux ];
diff --git a/pkgs/tools/networking/cjdns/makekeys-sigpipe.patch b/pkgs/tools/networking/cjdns/makekeys-sigpipe.patch
new file mode 100644
index 000000000000..2b21f56709d0
--- /dev/null
+++ b/pkgs/tools/networking/cjdns/makekeys-sigpipe.patch
@@ -0,0 +1,29 @@
+diff --git a/contrib/c/makekeys.c b/contrib/c/makekeys.c
+index 29582f1..555cf85 100644
+--- a/contrib/c/makekeys.c
++++ b/contrib/c/makekeys.c
+@@ -21,6 +21,7 @@
+
+ #include "crypto_scalarmult_curve25519.h"
+
++#include <signal.h>
+ #include <stdio.h>
+
+ int main(int argc, char** argv)
+@@ -35,6 +36,8 @@ int main(int argc, char** argv)
+ uint8_t hexPrivateKey[65];
+ uint8_t printedIp[40];
+
++ signal(SIGPIPE,SIG_DFL);
++
+ for (;;) {
+ Random_bytes(rand, privateKey, 32);
+ crypto_scalarmult_curve25519_base(publicKey, privateKey);
+@@ -43,6 +46,7 @@ int main(int argc, char** argv)
+ Base32_encode(publicKeyBase32, 53, publicKey, 32);
+ AddrTools_printShortIp(printedIp, ip);
+ printf("%s %s %s.k\n", hexPrivateKey, printedIp, publicKeyBase32);
++ fflush(stdout);
+ }
+ }
+ return 0;