From 089155582bf68493be8d9964e72abb8a0a327ec4 Mon Sep 17 00:00:00 2001 From: Dict Xiong Date: Sun, 5 Jan 2025 15:22:33 +0800 Subject: [PATCH] nixos: services.doh-server --- nixos/modules/module-list.nix | 1 + .../services/networking/doh-server.nix | 156 ++++++++++++++++++ 2 files changed, 157 insertions(+) create mode 100644 nixos/modules/services/networking/doh-server.nix diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 7a1d087d92cb62..a91590333d4941 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -1055,6 +1055,7 @@ ./services/networking/dnsmasq.nix ./services/networking/dnsproxy.nix ./services/networking/doh-proxy-rust.nix + ./services/networking/doh-server.nix ./services/networking/ejabberd.nix ./services/networking/envoy.nix ./services/networking/epmd.nix diff --git a/nixos/modules/services/networking/doh-server.nix b/nixos/modules/services/networking/doh-server.nix new file mode 100644 index 00000000000000..f67b09f5e586a1 --- /dev/null +++ b/nixos/modules/services/networking/doh-server.nix @@ -0,0 +1,156 @@ +{ + config, + lib, + pkgs, + ... +}: + +let + cfg = config.services.doh-server; + toml = pkgs.formats.toml { }; + configFile = toml.generate "config.toml" cfg.settings; +in +{ + options.services.doh-server = { + enable = lib.mkEnableOption "DNS-over-HTTPS server"; + + package = lib.mkPackageOption pkgs "dns-over-https" { }; + + settings = lib.mkOption { + type = lib.types.submodule { + freeformType = toml.type; + options = { + + listen = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = [ + "127.0.0.1:8053" + "[::1]:8053" + ]; + description = "HTTP listen port"; + }; + + localAddr = lib.mkOption { + type = lib.types.str; + default = ""; + description = '' + Local address and port for upstream DNS. + If left empty, a local address is automatically chosen. + ''; + }; + + cert = lib.mkOption { + type = lib.types.str; + default = ""; + description = '' + TLS certification file. + If left empty, plain-text HTTP will be used. + You are recommended to leave empty and to use a server load balancer (e.g. Caddy, Nginx) and set up TLS there, because this program does not do OCSP Stapling, which is necessary for client bootstrapping in a network environment with completely no traditional DNS service. + ''; + }; + + key = lib.mkOption { + type = lib.types.str; + default = ""; + description = "TLS private key file"; + }; + + path = lib.mkOption { + type = lib.types.str; + default = "/dns-query"; + description = "HTTP path for resolve application"; + }; + + upstream = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = [ + "udp:1.1.1.1:53" + "udp:1.0.0.1:53" + "udp:8.8.8.8:53" + "udp:8.8.4.4:53" + ]; + description = '' + Upstream DNS resolver. + If multiple servers are specified, a random one will be chosen each time. + You can use "udp", "tcp" or "tcp-tls" for the type prefix. + For "udp", UDP will first be used, and switch to TCP when the server asks to or the response is too large. + For "tcp", only TCP will be used. + For "tcp-tls", DNS-over-TLS (RFC 7858) will be used to secure the upstream connection. + ''; + }; + + timeout = lib.mkOption { + type = lib.types.int; + default = 10; + description = "Upstream timeout"; + }; + + tries = lib.mkOption { + type = lib.types.int; + default = 3; + description = "Number of tries if upstream DNS fails"; + }; + + verbose = lib.mkOption { + type = lib.types.bool; + default = false; + description = "Enable logging"; + }; + + log_guessed_client_ip = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + Enable log IP from HTTPS-reverse proxy header: X-Forwarded-For or X-Real-IP + Note: http uri/useragent log cannot be controlled by this config + ''; + }; + + ecs_allow_non_global_ip = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + By default, non global IP addresses are never forwarded to upstream servers. + This is to prevent two things from happening: + 1. the upstream server knowing your private LAN addresses; + 2. the upstream server unable to provide geographically near results, + or even fail to provide any result. + However, if you are deploying a split tunnel corporation network environment, or for any other reason you want to inhibit this behavior and allow local (eg RFC1918) address to be forwarded, change the following option to "true". + ''; + }; + + ecs_use_precise_ip = lib.mkOption { + type = lib.types.bool; + default = false; + description = '' + If ECS is added to the request, let the full IP address or cap it to 24 or 128 mask. This option is to be used only on private networks where knowledge of the terminal endpoint may be required for security purposes (eg. DNS Firewalling). Not a good option on the internet where IP address may be used to identify the user and not only the approximate location. + ''; + }; + }; + }; + default = { }; + description = "Configuration of doh-server in toml"; + }; + + }; + + config = lib.mkIf cfg.enable { + systemd.services.doh-server = { + description = "DNS-over-HTTPS Server"; + documentation = [ "https://github.com/m13253/dns-over-https" ]; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + AmbientCapabilities = "CAP_NET_BIND_SERVICE"; + ExecStart = "${cfg.package}/bin/doh-server -conf ${configFile}"; + LimitNOFILE = 1048576; + Restart = "always"; + RestartSec = 3; + Type = "simple"; + DynamicUser = true; + }; + }; + }; + + meta.maintainers = with lib.maintainers; [ DictXiong ]; +}