8 networking.nameservers = [ "::1" ];
11 extraOptions = "empty-zones-enable no;";
12 zones = lib.singleton {
15 file = pkgs.writeText "root.zone" ''
17 . IN SOA ns.example.org. admin.example.org. ( 1 3h 1h 1w 1d )
18 . IN NS ns.example.org.
20 ns.example.org. IN A 192.168.0.1
21 ns.example.org. IN AAAA abcd::1
23 1.0.168.192.in-addr.arpa IN PTR ns.example.org.
31 newServer({address="127.0.0.1:53", name="local-bind"})
41 name = "dnsdist-base";
42 meta.maintainers = with lib.maintainers; [ jojosch ];
44 nodes.machine = baseConfig;
47 machine.wait_for_unit("bind.service")
48 machine.wait_for_open_port(53)
49 machine.succeed("host -p 53 192.168.0.1 | grep -qF ns.example.org")
51 machine.wait_for_unit("dnsdist.service")
52 machine.wait_for_open_port(5353)
53 machine.succeed("host -p 5353 192.168.0.1 | grep -qF ns.example.org")
58 name = "dnsdist-dnscrypt";
59 meta.maintainers = with lib.maintainers; [ rnhmjoj ];
61 nodes.server = lib.mkMerge [
64 networking.firewall.allowedTCPPorts = [ 443 ];
65 networking.firewall.allowedUDPPorts = [ 443 ];
66 services.dnsdist.dnscrypt.enable = true;
67 services.dnsdist.dnscrypt.providerKey = pkgs.runCommand "dnscrypt-secret.key" {} ''
68 echo 'R70+xqm7AaDsPtDgpSjSG7KHvEqVf6u6PZ+E3cGPbOwUQdg6/
69 RIIpK6pHkINhrv7nxwIG5c7b/m5NJVT3A1AXQ==' | base64 -id > "$out"
75 services.dnscrypt-proxy2.enable = true;
76 services.dnscrypt-proxy2.upstreamDefaults = false;
77 services.dnscrypt-proxy2.settings =
78 { server_names = [ "server" ];
79 listen_addresses = [ "[::1]:53" ];
81 # Computed using https://dnscrypt.info/stamps/
83 "sdns://AQAAAAAAAAAADzE5Mi4xNjguMS4yOjQ0MyAUQdg6_RIIpK6pHkINhrv7nxwIG5c7b_m5NJVT3A1AXRYyLmRuc2NyeXB0LWNlcnQuc2VydmVy";
85 networking.nameservers = [ "::1" ];
89 with subtest("The DNSCrypt server is accepting connections"):
90 server.wait_for_unit("bind.service")
91 server.wait_for_unit("dnsdist.service")
92 server.wait_for_open_port(443)
93 almost_expiration = server.succeed("date --date '14min'").strip()
95 with subtest("The DNSCrypt client can connect to the server"):
96 client.wait_until_succeeds("journalctl -u dnscrypt-proxy2 --grep '\[server\] OK'")
98 with subtest("DNS queries over UDP are working"):
99 client.wait_for_open_port(53)
100 client.succeed("host -U 192.168.0.1 | grep -qF ns.example.org")
102 with subtest("DNS queries over TCP are working"):
103 client.wait_for_open_port(53)
104 client.succeed("host -T 192.168.0.1 | grep -qF ns.example.org")
106 with subtest("The server rotates the ephemeral keys"):
107 server.succeed(f"date -s '{almost_expiration}'")
108 client.succeed(f"date -s '{almost_expiration}'")
109 server.wait_until_succeeds("journalctl -u dnsdist --grep 'rotated certificate'")
111 with subtest("The client can still connect to the server"):
112 client.wait_until_succeeds("host -T 192.168.0.1")
113 client.wait_until_succeeds("host -U 192.168.0.1")