diff options
Diffstat (limited to 'nixos/modules/services')
-rw-r--r-- | nixos/modules/services/networking/cjdns-hosts.sh | 11 | ||||
-rw-r--r-- | nixos/modules/services/networking/cjdns.nix | 194 |
2 files changed, 126 insertions, 79 deletions
diff --git a/nixos/modules/services/networking/cjdns-hosts.sh b/nixos/modules/services/networking/cjdns-hosts.sh new file mode 100644 index 000000000000..8a2b47e52143 --- /dev/null +++ b/nixos/modules/services/networking/cjdns-hosts.sh @@ -0,0 +1,11 @@ +pubs=($pubs) +hosts=($hosts) + +lines="''\n" +for ((i = 0; i < ${#pubs[*]}; i++)); do + addr=$($cjdns/bin/publictoip6 ${pubs[i]}) + lines="${lines}$addr ${hosts[i]}\n" +done +lines="${lines}''" + +echo -ne $lines > $out diff --git a/nixos/modules/services/networking/cjdns.nix b/nixos/modules/services/networking/cjdns.nix index 7192b8b7a0e0..9888419309c1 100644 --- a/nixos/modules/services/networking/cjdns.nix +++ b/nixos/modules/services/networking/cjdns.nix @@ -4,8 +4,46 @@ with lib; let + pkg = pkgs.cjdns; + cfg = config.services.cjdns; + connectToSubmodule = + { options, ... }: + { options = + { password = mkOption { + type = types.str; + description = "Authorized password to the opposite end of the tunnel."; + }; + publicKey = mkOption { + type = types.str; + description = "Public key at the opposite end of the tunnel."; + }; + hostname = mkOption { + default = ""; + example = "foobar.hype"; + type = types.str; + description = "Optional hostname to add to /etc/hosts; prevents reverse lookup failures."; + }; + }; + }; + + peers = mapAttrsToList (n: v: v) (cfg.ETHInterface.connectTo // cfg.UDPInterface.connectTo); + + pubs = toString (map (p: if p.hostname == "" then "" else p.publicKey) peers); + hosts = toString (map (p: if p.hostname == "" then "" else p.hostname) peers); + + cjdnsHosts = + if hosts != "" then + import (pkgs.stdenv.mkDerivation { + name = "cjdns-hosts"; + builder = ./cjdns-hosts.sh; + + inherit (pkgs) cjdns; + inherit pubs hosts; + }) + else ""; + # would be nice to merge 'cfg' with a //, # but the json nesting is wacky. cjdrouteConf = builtins.toJSON ( { @@ -44,7 +82,7 @@ in enable = mkOption { type = types.bool; - default = false; + default = false; description = '' Whether to enable the cjdns network encryption and routing engine. A file at /etc/cjdns.keys will @@ -53,84 +91,80 @@ in ''; }; + confFile = mkOption { + type = types.str; + default = ""; + example = "/etc/cjdroute.conf"; + description = '' + Ignore all other cjdns options and load configuration from this file. + ''; + }; + authorizedPasswords = mkOption { type = types.listOf types.str; - default = [ ]; - example = [ + default = [ ]; + example = [ "snyrfgkqsc98qh1y4s5hbu0j57xw5s0" - "z9md3t4p45mfrjzdjurxn4wuj0d8swv" - "49275fut6tmzu354pq70sr5b95qq0vj" + "z9md3t4p45mfrjzdjurxn4wuj0d8swv" + "49275fut6tmzu354pq70sr5b95qq0vj" ]; - description = '' - Any remote cjdns nodes that offer these passwords on - connection will be allowed to route through this node. + description = '' + Any remote cjdns nodes that offer these passwords on + connection will be allowed to route through this node. ''; }; admin = { bind = mkOption { type = types.string; - default = "127.0.0.1:11234"; - description = '' + default = "127.0.0.1:11234"; + description = '' Bind the administration port to this address and port. - ''; + ''; }; }; UDPInterface = { bind = mkOption { type = types.string; - default = ""; + default = ""; example = "192.168.1.32:43211"; description = '' - Address and port to bind UDP tunnels to. - ''; - }; + Address and port to bind UDP tunnels to. + ''; + }; connectTo = mkOption { - type = types.attrsOf ( types.submodule ( - { options, ... }: - { options = { - # TODO make host an option, and add it to networking.extraHosts - password = mkOption { - type = types.str; - description = "Authorized password to the opposite end of the tunnel."; - }; - publicKey = mkOption { - type = types.str; - description = "Public key at the opposite end of the tunnel."; - }; - }; - } - )); - default = { }; + type = types.attrsOf ( types.submodule ( connectToSubmodule ) ); + default = { }; example = { "192.168.1.1:27313" = { - password = "5kG15EfpdcKNX3f2GSQ0H1HC7yIfxoCoImnO5FHM"; + hostname = "homer.hype"; + password = "5kG15EfpdcKNX3f2GSQ0H1HC7yIfxoCoImnO5FHM"; publicKey = "371zpkgs8ss387tmr81q04mp0hg1skb51hw34vk1cq644mjqhup0.k"; }; }; description = '' - Credentials for making UDP tunnels. - ''; - }; + Credentials for making UDP tunnels. + ''; + }; }; ETHInterface = { bind = mkOption { - default = ""; - example = "eth0"; - description = '' - Bind to this device for native ethernet operation. - ''; - }; + default = ""; + example = "eth0"; + description = '' + Bind to this device for native ethernet operation. + ''; + }; beacon = mkOption { - type = types.int; + type = types.int; default = 2; description = '' Auto-connect to other cjdns nodes on the same network. Options: - 0: Disabled. + 0: Disabled. 1: Accept beacons, this will cause cjdns to accept incoming beacon messages and try connecting to the sender. 2: Accept and send beacons, this will cause cjdns to broadcast @@ -142,32 +176,20 @@ in }; connectTo = mkOption { - type = types.attrsOf ( types.submodule ( - { options, ... }: - { options = { - password = mkOption { - type = types.str; - description = "Authorized password to the opposite end of the tunnel."; - }; - publicKey = mkOption { - type = types.str; - description = "Public key at the opposite end of the tunnel."; - }; - }; - } - )); - default = { }; + type = types.attrsOf ( types.submodule ( connectToSubmodule ) ); + default = { }; example = { "01:02:03:04:05:06" = { - password = "5kG15EfpdcKNX3f2GSQ0H1HC7yIfxoCoImnO5FHM"; + hostname = "homer.hype"; + password = "5kG15EfpdcKNX3f2GSQ0H1HC7yIfxoCoImnO5FHM"; publicKey = "371zpkgs8ss387tmr81q04mp0hg1skb51hw34vk1cq644mjqhup0.k"; }; }; - description = '' - Credentials for connecting look similar to UDP credientials + description = '' + Credentials for connecting look similar to UDP credientials except they begin with the mac address. - ''; - }; + ''; + }; }; }; @@ -185,34 +207,48 @@ in wantedBy = [ "multi-user.target" ]; after = [ "network-interfaces.target" ]; - script = '' - source /etc/cjdns.keys - echo '${cjdrouteConf}' | sed \ - -e "s/@CJDNS_ADMIN_PASSWORD@/$CJDNS_ADMIN_PASSWORD/g" \ - -e "s/@CJDNS_PRIVATE_KEY@/$CJDNS_PRIVATE_KEY/g" \ - | ${pkgs.cjdns}/bin/cjdroute - ''; + script = ( + if cfg.confFile != "" then "${pkg}/bin/cjdroute < ${cfg.confFile}" else + '' + source /etc/cjdns.keys + echo '${cjdrouteConf}' | sed \ + -e "s/@CJDNS_ADMIN_PASSWORD@/$CJDNS_ADMIN_PASSWORD/g" \ + -e "s/@CJDNS_PRIVATE_KEY@/$CJDNS_PRIVATE_KEY/g" \ + | ${pkg}/bin/cjdroute + '' + ); serviceConfig = { Type = "forking"; - Restart = "on-failure"; + Restart = "on-failure"; }; }; - system.activationScripts.cjdns = '' + 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 || \ - echo "CJDNS_PRIVATE_KEY=$(${pkgs.cjdns}/bin/makekey)" \ - >> /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 - - chmod 600 /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 = [ - { assertion = ( cfg.ETHInterface.bind != "" || cfg.UDPInterface.bind != "" ); + { assertion = ( cfg.ETHInterface.bind != "" || cfg.UDPInterface.bind != "" || cfg.confFile == "" ); message = "Neither cjdns.ETHInterface.bind nor cjdns.UDPInterface.bind defined."; } { assertion = config.networking.enableIPv6; |