diff options
Diffstat (limited to 'nixpkgs/nixos/tests/dnscrypt-wrapper/default.nix')
-rw-r--r-- | nixpkgs/nixos/tests/dnscrypt-wrapper/default.nix | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/nixpkgs/nixos/tests/dnscrypt-wrapper/default.nix b/nixpkgs/nixos/tests/dnscrypt-wrapper/default.nix new file mode 100644 index 000000000000..1a794931dc50 --- /dev/null +++ b/nixpkgs/nixos/tests/dnscrypt-wrapper/default.nix @@ -0,0 +1,148 @@ + +{ lib, pkgs, ... }: + +let + snakeoil = import ../common/acme/server/snakeoil-certs.nix; + + hosts = lib.mkForce + { "fd::a" = [ "server" snakeoil.domain ]; + "fd::b" = [ "client" ]; + }; +in + +{ + name = "dnscrypt-wrapper"; + meta = with pkgs.lib.maintainers; { + maintainers = [ rnhmjoj ]; + }; + + nodes = { + server = { + networking.hosts = hosts; + networking.interfaces.eth1.ipv6.addresses = lib.singleton + { address = "fd::a"; prefixLength = 64; }; + + services.dnscrypt-wrapper = + { enable = true; + address = "[::]"; + port = 5353; + keys.expiration = 5; # days + keys.checkInterval = 2; # min + # The keypair was generated by the command: + # dnscrypt-wrapper --gen-provider-keypair \ + # --provider-name=2.dnscrypt-cert.server \ + providerKey.public = "${./public.key}"; + providerKey.secret = "${./secret.key}"; + }; + + # nameserver + services.bind.enable = true; + services.bind.zones = lib.singleton + { name = "."; + master = true; + file = pkgs.writeText "root.zone" '' + $TTL 3600 + . IN SOA example.org. admin.example.org. ( 1 3h 1h 1w 1d ) + . IN NS example.org. + example.org. IN AAAA 2001:db8::1 + ''; + }; + + # webserver + services.nginx.enable = true; + services.nginx.virtualHosts.${snakeoil.domain} = + { onlySSL = true; + listenAddresses = [ "localhost" ]; + sslCertificate = snakeoil.${snakeoil.domain}.cert; + sslCertificateKey = snakeoil.${snakeoil.domain}.key; + locations."/ip".extraConfig = '' + default_type text/plain; + return 200 "Ciao $remote_addr!\n"; + ''; + }; + + # demultiplex HTTP and DNS from port 443 + services.sslh = + { enable = true; + method = "ev"; + settings.transparent = true; + settings.listen = lib.mkForce + [ { host = "server"; port = "443"; is_udp = false; } + { host = "server"; port = "443"; is_udp = true; } + ]; + settings.protocols = + [ # Send TLS to webserver (TCP) + { name = "tls"; host= "localhost"; port= "443"; } + # Send DNSCrypt to dnscrypt-wrapper (TCP or UDP) + { name = "anyprot"; host = "localhost"; port = "5353"; } + { name = "anyprot"; host = "localhost"; port = "5353"; is_udp = true;} + ]; + }; + + networking.firewall.allowedTCPPorts = [ 443 ]; + networking.firewall.allowedUDPPorts = [ 443 ]; + }; + + client = { + networking.hosts = hosts; + networking.interfaces.eth1.ipv6.addresses = lib.singleton + { address = "fd::b"; prefixLength = 64; }; + + services.dnscrypt-proxy2.enable = true; + services.dnscrypt-proxy2.upstreamDefaults = false; + services.dnscrypt-proxy2.settings = + { server_names = [ "server" ]; + listen_addresses = [ "[::1]:53" ]; + cache = false; + # Computed using https://dnscrypt.info/stamps/ + static.server.stamp = + "sdns://AQAAAAAAAAAADzE5Mi4xNjguMS4yOjQ0MyAUQdg6" + +"_RIIpK6pHkINhrv7nxwIG5c7b_m5NJVT3A1AXRYyLmRuc2NyeXB0LWNlcnQuc2VydmVy"; + }; + networking.nameservers = [ "::1" ]; + security.pki.certificateFiles = [ snakeoil.ca.cert ]; + }; + + }; + + testScript = '' + with subtest("The server can generate the ephemeral keypair"): + server.wait_for_unit("dnscrypt-wrapper") + server.wait_for_file("/var/lib/dnscrypt-wrapper/2.dnscrypt-cert.server.key") + server.wait_for_file("/var/lib/dnscrypt-wrapper/2.dnscrypt-cert.server.crt") + almost_expiration = server.succeed("date --date '4days 23 hours 56min'").strip() + + with subtest("The DNSCrypt client can connect to the server"): + server.wait_for_unit("sslh") + client.wait_until_succeeds("journalctl -u dnscrypt-proxy2 --grep '\[server\] OK'") + + with subtest("HTTP client can connect to the server"): + server.wait_for_unit("nginx") + client.succeed("curl -s --fail https://${snakeoil.domain}/ip | grep -q fd::b") + + with subtest("DNS queries over UDP are working"): + server.wait_for_unit("bind") + client.wait_for_open_port(53) + assert "2001:db8::1" in client.wait_until_succeeds( + "host -U example.org" + ), "The IP address of 'example.org' does not match 2001:db8::1" + + with subtest("DNS queries over TCP are working"): + server.wait_for_unit("bind") + client.wait_for_open_port(53) + assert "2001:db8::1" in client.wait_until_succeeds( + "host -T example.org" + ), "The IP address of 'example.org' does not match 2001:db8::1" + + with subtest("The server rotates the ephemeral keys"): + # advance time by a little less than 5 days + server.succeed(f"date -s '{almost_expiration}'") + client.succeed(f"date -s '{almost_expiration}'") + server.wait_for_file("/var/lib/dnscrypt-wrapper/oldkeys") + + with subtest("The client can still connect to the server"): + client.systemctl("restart dnscrypt-proxy2") + client.wait_until_succeeds("host -T example.org") + client.wait_until_succeeds("host -U example.org") + ''; +} |