DNS over TLS

From NixOS Wiki
Revision as of 21:10, 12 October 2019 by imported>Vdot0x23 (Only set dns for wlp and enp interface, not virbr, docker and so on)

DNS-over-TLS is a protocol specified in RFC 7858 that encrypts and authenticates DNS requests, that usually otherwise are prone to various attacks.

Using NetworkManager

Enable Stubby

Stubby is a DNS-over-TLS daemon that can resolve DNS requests using DNS-over-TLS.

The following snippet will enable Stubby on port 5453. The reason for it being port 5453 is that dnsmasq will occupy port 53.

    services.stubby = {
      enable = true;
      listenAddresses = 
      [ 
        "127.0.0.1@5453"
        "0::1@5453"
      ];

Configuring NetworkManager and Enabling Dnsmasq

Dnsmasq has many functions, but in this case, it will be a local cache for DNS requests to avoid redundant DNS requests and increase speed of frequent DNS requests.

The following snippet will enable dnsmasq, included in networkmanager and since there is no global setting for which DNS server NetworkManager should use, this snippet also sets up a dispatcher script, which runs on any connection right before NetworkManager "tells" the system that the connection is up.

Additionally, for privacy reasons, this dispatcher script also stops NetworkManager from sending the machines hostname as part of DHCP, though this is not neccesary for DNS-over-TLS to function.

    networking.networkmanager = {
      enable = true;
      dns = "dnsmasq";
      dispatcherScripts = 
      [ {
        source = pkgs.writeText "upHook" ''
          # Only set dns for wlp and enp interface, not virbr, docker and so on
          if [[ $DEVICE_IFACE == *"wlp"* || $DEVICE_IFACE == *"enp"* ]]; then
            /run/current-system/sw/bin/nmcli connection modify uuid $CONNECTION_UUID \
            ipv4.dhcp-send-hostname "false" \
            ipv4.ignore-auto-dns "true" \
            ipv4.dns "127.0.0.1" \
            ipv6.dhcp-send-hostname "false" \
            ipv6.ignore-auto-dns "true" \
            ipv6.dns "::1" # Dnsmasq doesn't actually listen on IPv6, so ipv6 dns requests probably won't work
          else
            echo "Excluding $DEVICE_IFACE from privacy dispatcher script" >> /tmp/dispatcherScripts.log
          fi
        '';
        type = "pre-up";
      } ]; # Use local DNS server and don't send hostname. For all connections
    };

Dnsmasq needs some additional configuration to use Stubby. The snippet below tells dnsmasq to use localhost on port 5453, which is where Stubby is running, for DNS requests that are not cached. It also moderately increases the cache size of dnsmasq from the default.

environment.etc = {
    "NetworkManager/dnsmasq.d/dnsmasq-nm.conf".text = ''
      no-resolv
      server=127.0.0.1#5453
      server=0::1#5453
      cache-size=1500
   '';
      "NetworkManager/dnsmasq-shared.d/dnsmasq-shared-nm.conf".text = ''
      no-resolv
      server=127.0.0.1#5453
      server=0::1#5453
      cache-size=500
    '';
  };

Manual Upstreams for Stubby

Manual upstreams can be defined for stubby, instead of the default, as shown on the example below.

services.stubby = {
  enable = true;
  listenAddresses = 
  [ 
    "127.0.0.1@5453"
    "0::1@5453"
  ];
  upstreamServers = ''
    ## IPv4 ##
    # The Uncensored DNS servers
      - address_data: 89.233.43.71
        tls_auth_name: "unicast.censurfridns.dk"
        tls_pubkey_pinset:
          - digest: "sha256"
            value: wikE3jYAA6jQmXYTr/rbHeEPmC78dQwZbQp6WdrseEs=
    # Foundation for Applied Privacy
      - address_data: 37.252.185.232
        tls_auth_name: "dot1.appliedprivacy.net"
        tls_port: 443 # In case default 853 is blocked
    ## IPv6 ##
    # The Uncensored DNS server
      - address_data: 2a01:3a0:53:53::0
        tls_auth_name: "unicast.censurfridns.dk"
        tls_pubkey_pinset:
          - digest: "sha256"
            value: wikE3jYAA6jQmXYTr/rbHeEPmC78dQwZbQp6WdrseEs=
    # Foundation for Applied Privacy
      - address_data: 2a00:63c1:a:229::3
        tls_port: 443 # In case default 853 is blocked
        tls_auth_name: "dot1.appliedprivacy.net"
  '';
};

If the default upstreams are to be kept, they have to be readded.