at master 3.3 kB view raw
1let 2 carolKey = "2d2a338b46f8e4a8c462f0c385b481292a05f678e19a2b82755258cf0f0af7e2"; 3 carolPubKey = "n932l3pjvmhtxxcdrqq2qpw5zc58f01vvjx01h4dtd1bb0nnu2h0.k"; 4 carolPassword = "678287829ce4c67bc8b227e56d94422ee1b85fa11618157b2f591de6c6322b52"; 5 6 basicConfig = 7 { ... }: 8 { 9 services.cjdns.enable = true; 10 11 # Turning off DHCP isn't very realistic but makes 12 # the sequence of address assignment less stochastic. 13 networking.useDHCP = false; 14 15 # CJDNS output is incompatible with the XML log. 16 systemd.services.cjdns.serviceConfig.StandardOutput = "null"; 17 }; 18 19in 20 21{ pkgs, ... }: 22{ 23 name = "cjdns"; 24 25 nodes = { 26 # Alice finds peers over over ETHInterface. 27 alice = 28 { ... }: 29 { 30 imports = [ basicConfig ]; 31 32 services.cjdns.ETHInterface.bind = "eth1"; 33 34 services.httpd.enable = true; 35 services.httpd.adminAddr = "foo@example.org"; 36 networking.firewall.allowedTCPPorts = [ 80 ]; 37 }; 38 39 # Bob explicitly connects to Carol over UDPInterface. 40 bob = 41 { ... }: 42 43 { 44 imports = [ basicConfig ]; 45 46 networking.interfaces.eth1.ipv4.addresses = [ 47 { 48 address = "192.168.0.2"; 49 prefixLength = 24; 50 } 51 ]; 52 53 services.cjdns = { 54 UDPInterface = { 55 bind = "0.0.0.0:1024"; 56 connectTo."192.168.0.1:1024" = { 57 password = carolPassword; 58 publicKey = carolPubKey; 59 }; 60 }; 61 }; 62 }; 63 64 # Carol listens on ETHInterface and UDPInterface, 65 # but knows neither Alice or Bob. 66 carol = 67 { ... }: 68 { 69 imports = [ basicConfig ]; 70 71 environment.etc."cjdns.keys".text = '' 72 CJDNS_PRIVATE_KEY=${carolKey} 73 CJDNS_ADMIN_PASSWORD=FOOBAR 74 ''; 75 76 networking.interfaces.eth1.ipv4.addresses = [ 77 { 78 address = "192.168.0.1"; 79 prefixLength = 24; 80 } 81 ]; 82 83 services.cjdns = { 84 authorizedPasswords = [ carolPassword ]; 85 ETHInterface.bind = "eth1"; 86 UDPInterface.bind = "192.168.0.1:1024"; 87 }; 88 networking.firewall.allowedUDPPorts = [ 1024 ]; 89 }; 90 91 }; 92 93 testScript = '' 94 import re 95 96 start_all() 97 98 alice.wait_for_unit("cjdns.service") 99 bob.wait_for_unit("cjdns.service") 100 carol.wait_for_unit("cjdns.service") 101 102 103 def cjdns_ip(machine): 104 res = machine.succeed("ip -o -6 addr show dev tun0") 105 ip = re.split("\\s+|/", res)[3] 106 machine.log("has ip {}".format(ip)) 107 return ip 108 109 110 alice_ip6 = cjdns_ip(alice) 111 bob_ip6 = cjdns_ip(bob) 112 carol_ip6 = cjdns_ip(carol) 113 114 # ping a few times each to let the routing table establish itself 115 116 alice.wait_until_succeeds("ping -c 4 {}".format(carol_ip6)) 117 bob.wait_until_succeeds("ping -c 4 {}".format(carol_ip6)) 118 119 carol.wait_until_succeeds("ping -c 4 {}".format(alice_ip6)) 120 carol.wait_until_succeeds("ping -c 4 {}".format(bob_ip6)) 121 122 alice.wait_until_succeeds("ping -c 4 {}".format(bob_ip6)) 123 bob.wait_until_succeeds("ping -c 4 {}".format(alice_ip6)) 124 125 alice.wait_for_unit("httpd.service") 126 127 bob.succeed("curl --fail -g http://[{}]".format(alice_ip6)) 128 ''; 129}