Skip to content

Commit 78ab0ad

Browse files
committed
nixos/doh-server: init
1 parent 1e90553 commit 78ab0ad

File tree

5 files changed

+226
-0
lines changed

5 files changed

+226
-0
lines changed

nixos/doc/manual/redirects.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -875,6 +875,12 @@
875875
"module-services-networking-dnsmasq-references": [
876876
"index.html#module-services-networking-dnsmasq-references"
877877
],
878+
"module-service-doh-server": [
879+
"index.html#module-service-doh-server"
880+
],
881+
"module-service-doh-server-quick-start": [
882+
"index.html#module-service-doh-server-quick-start"
883+
],
878884
"module-services-samba": [
879885
"index.html#module-services-samba"
880886
],

nixos/doc/manual/release-notes/rl-2505.section.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@
5151

5252
- [networking.modemmanager](options.html#opt-networking.modemmanager) has been split out of [networking.networkmanager](options.html#opt-networking.networkmanager). NetworkManager still enables ModemManager by default, but options exist now to run NetworkManager without ModemManager.
5353

54+
- [doh-server](https://github.com/m13253/dns-over-https), a high performance DNS over HTTPS server. Available as [services.doh-server](options.html#opt-services.doh-server.enable).
55+
5456
- [ncps](https://github.com/kalbasit/ncps), a Nix binary cache proxy service implemented in Go using [go-nix](https://github.com/nix-community/go-nix). Available as [services.ncps](options.html#opt-services.ncps.enable).
5557

5658
- [Conduwuit](https://conduwuit.puppyirl.gay/), a federated chat server implementing the Matrix protocol, forked from Conduit. Available as [services.conduwuit](#opt-services.conduwuit.enable).

nixos/modules/module-list.nix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1055,6 +1055,7 @@
10551055
./services/networking/dnsmasq.nix
10561056
./services/networking/dnsproxy.nix
10571057
./services/networking/doh-proxy-rust.nix
1058+
./services/networking/doh-server.nix
10581059
./services/networking/ejabberd.nix
10591060
./services/networking/envoy.nix
10601061
./services/networking/epmd.nix
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# DNS-over-HTTPS Server {#module-service-doh-server}
2+
3+
[DNS-over-HTTPS](https://github.com/m13253/dns-over-https) is a high performance DNS over HTTPS client & server. This module enables its server part (`doh-server`).
4+
5+
## Quick Start {#module-service-doh-server-quick-start}
6+
7+
`doh-server` can be used as a standalone https web server (with ssl cert and key speicified) or with other reverse proxy services (such as `nginx` or `candy`). The latter approach is recommended as `doh-server` does not do OCSP Stapling.
8+
9+
Setup a standalone instance:
10+
11+
```nix
12+
services.doh-server = {
13+
enable = true;
14+
settings = {
15+
listen = [ ":443" ];
16+
upstream = [ "udp:1.1.1.1:53" ];
17+
cert = "/path/to/cert.crt";
18+
key = "/path/to/key.key";
19+
};
20+
};
21+
```
22+
23+
Setup with Nginx + ACME (recommanded):
24+
25+
```nix
26+
services.doh-server = {
27+
enable = true;
28+
settings = {
29+
listen = [ ":8053" ];
30+
upstream = [ "udp:1.1.1.1:53" ];
31+
};
32+
};
33+
34+
services.nginx = {
35+
enable = true;
36+
virtualHosts."doh.example.com" = {
37+
enableACME = true;
38+
forceSSL = true;
39+
http2 = true;
40+
locations."/".return = 404;
41+
locations."/dns-query".extraConfig = ''
42+
proxy_set_header X-Real-IP $remote_addr;
43+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
44+
proxy_set_header Host $host;
45+
proxy_set_header X-NginX-Proxy true;
46+
proxy_http_version 1.1;
47+
proxy_set_header Upgrade $http_upgrade;
48+
proxy_redirect off;
49+
proxy_set_header X-Forwarded-Proto $scheme;
50+
proxy_read_timeout 86400;
51+
proxy_pass http://127.0.0.1:8053/dns-query;
52+
'';
53+
};
54+
# and other virtual hosts ...
55+
};
56+
57+
security.acme = {
58+
acceptTerms = true;
59+
defaults.email = "you@example.com";
60+
defaults.group = "nginx";
61+
};
62+
```
63+
64+
See a full configuration in https://github.com/m13253/dns-over-https/blob/master/doh-server/doh-server.conf.
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
{
2+
config,
3+
lib,
4+
pkgs,
5+
...
6+
}:
7+
8+
let
9+
cfg = config.services.doh-server;
10+
toml = pkgs.formats.toml { };
11+
configFile = toml.generate "config.toml" cfg.settings;
12+
in
13+
{
14+
options.services.doh-server = {
15+
enable = lib.mkEnableOption "DNS-over-HTTPS server";
16+
17+
package = lib.mkPackageOption pkgs "dns-over-https" { };
18+
19+
settings = lib.mkOption {
20+
type = lib.types.submodule {
21+
freeformType = toml.type;
22+
options = {
23+
24+
listen = lib.mkOption {
25+
type = lib.types.listOf lib.types.str;
26+
default = [
27+
"127.0.0.1:8053"
28+
"[::1]:8053"
29+
];
30+
example = [ ":443" ];
31+
description = "HTTP listen address and port";
32+
};
33+
34+
path = lib.mkOption {
35+
type = lib.types.str;
36+
default = "/dns-query";
37+
example = "/dns-query";
38+
description = "HTTP path for resolve application";
39+
};
40+
41+
upstream = lib.mkOption {
42+
type = lib.types.listOf lib.types.str;
43+
default = [
44+
"udp:1.1.1.1:53"
45+
"udp:1.0.0.1:53"
46+
"udp:8.8.8.8:53"
47+
"udp:8.8.4.4:53"
48+
];
49+
example = [ "udp:127.0.0.1:53" ];
50+
description = ''
51+
Upstream DNS resolver.
52+
If multiple servers are specified, a random one will be chosen each time.
53+
You can use "udp", "tcp" or "tcp-tls" for the type prefix.
54+
For "udp", UDP will first be used, and switch to TCP when the server asks to or the response is too large.
55+
For "tcp", only TCP will be used.
56+
For "tcp-tls", DNS-over-TLS (RFC 7858) will be used to secure the upstream connection.
57+
'';
58+
};
59+
60+
timeout = lib.mkOption {
61+
type = lib.types.int;
62+
default = 10;
63+
example = 15;
64+
description = "Upstream timeout";
65+
};
66+
67+
tries = lib.mkOption {
68+
type = lib.types.int;
69+
default = 3;
70+
example = 5;
71+
description = "Number of tries if upstream DNS fails";
72+
};
73+
74+
verbose = lib.mkOption {
75+
type = lib.types.bool;
76+
default = false;
77+
example = true;
78+
description = "Enable logging";
79+
};
80+
81+
log_guessed_client_ip = lib.mkOption {
82+
type = lib.types.bool;
83+
default = false;
84+
example = true;
85+
description = ''
86+
Enable log IP from HTTPS-reverse proxy header: X-Forwarded-For or X-Real-IP
87+
Note: http uri/useragent log cannot be controlled by this config
88+
'';
89+
};
90+
91+
ecs_allow_non_global_ip = lib.mkOption {
92+
type = lib.types.bool;
93+
default = false;
94+
example = true;
95+
description = ''
96+
By default, non global IP addresses are never forwarded to upstream servers.
97+
This is to prevent two things from happening:
98+
1. the upstream server knowing your private LAN addresses;
99+
2. the upstream server unable to provide geographically near results,
100+
or even fail to provide any result.
101+
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".
102+
'';
103+
};
104+
105+
ecs_use_precise_ip = lib.mkOption {
106+
type = lib.types.bool;
107+
default = false;
108+
example = true;
109+
description = ''
110+
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.
111+
'';
112+
};
113+
};
114+
};
115+
default = { };
116+
example = {
117+
listen = [ ":8153" ];
118+
upstream = [ "udp:127.0.0.1:53" ];
119+
};
120+
description = "Configuration of doh-server in toml. See example in https://github.com/m13253/dns-over-https/blob/master/doh-server/doh-server.conf";
121+
};
122+
123+
configFile = lib.mkOption {
124+
type = lib.types.path;
125+
example = ~/doh-server.conf;
126+
description = ''
127+
The config file for the doh-server.
128+
Setting this option will override any configuration applied by the `settings` option.
129+
'';
130+
};
131+
};
132+
config = lib.mkIf cfg.enable {
133+
services.doh-server.configFile = lib.mkDefault (toml.generate "doh-server.conf" cfg.settings);
134+
systemd.services.doh-server = {
135+
description = "DNS-over-HTTPS Server";
136+
documentation = [ "https://github.com/m13253/dns-over-https" ];
137+
after = [ "network.target" ];
138+
wantedBy = [ "multi-user.target" ];
139+
serviceConfig = {
140+
AmbientCapabilities = "CAP_NET_BIND_SERVICE";
141+
ExecStart = "${cfg.package}/bin/doh-server -conf ${configFile}";
142+
LimitNOFILE = 1048576;
143+
Restart = "always";
144+
RestartSec = 3;
145+
Type = "simple";
146+
DynamicUser = true;
147+
};
148+
};
149+
};
150+
151+
meta.maintainers = with lib.maintainers; [ DictXiong ];
152+
meta.doc = ./doh-server.md;
153+
}

0 commit comments

Comments
 (0)