-
Notifications
You must be signed in to change notification settings - Fork 318
feat: add systemd service #488
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,133 @@ | ||
| # /etc/systemd/system/dnsproxy.service | ||
| # | ||
| # Hardened systemd unit for adguardteam/dnsproxy | ||
| # | ||
| # All upstreams use encrypted protocols (DoH, DoT). | ||
| # IP-based upstream URLs avoid bootstrap DNS entirely — no plaintext | ||
| # DNS query ever leaves this machine. | ||
| # | ||
| # Upstream strategy: | ||
| # Primary (fastest_addr): Cloudflare, Google via DoH (IP-based) | ||
| # HTTP/3: Enabled globally for DoH (benefits CF & Google) | ||
| # Fallback: DoT endpoints for all providers | ||
| # | ||
| # Prerequisites: | ||
| # 1. Download the dnsproxy binary to /usr/local/bin/dnsproxy | ||
| # 2. chmod 755 /usr/local/bin/dnsproxy | ||
| # 3. systemctl daemon-reload | ||
| # 4. systemctl enable --now dnsproxy.service | ||
| # | ||
| # Verify no plaintext DNS leaks: | ||
| # sudo ss -ulnp sport = 53 # should show only 127.0.0.1 | ||
| # sudo tcpdump -i any port 53 # should show zero outbound traffic on port 53 | ||
|
|
||
| [Unit] | ||
| Description=dnsproxy — encrypted DNS forwarder (DoH/DoT/DoQ) | ||
| Documentation=https://github.com/AdguardTeam/dnsproxy | ||
| After=network-online.target nss-lookup.target | ||
| Wants=network-online.target | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since this service binds to port 53, consider adding |
||
| Conflicts=systemd-resolved.service dnsmasq.service named.service | ||
|
|
||
| [Service] | ||
| Type=simple | ||
|
|
||
| # Primary upstreams: DoH via IP addresses (zero bootstrap DNS needed) | ||
| # Cloudflare — https://1.1.1.1 / 1.0.0.1 | ||
| # Google — https://8.8.8.8 / 8.8.4.4 | ||
| # Fallback (DoT): all providers, used only if DoH is down | ||
| # --http3 enables HTTP/3 (QUIC transport) for DoH connections | ||
| ExecStart=/usr/local/bin/dnsproxy \ | ||
| --listen=127.0.0.1 \ | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The service is configured to listen only on localhost (127.0.0.1). If users want to use this as a DNS server for other devices on their network, they would need to modify the
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it's not rocket science to update the listen address :) |
||
| --port=53 \ | ||
| --http3 \ | ||
| --upstream=https://1.1.1.1/dns-query \ | ||
| --upstream=https://1.0.0.1/dns-query \ | ||
| --upstream=https://8.8.8.8/dns-query \ | ||
| --upstream=https://8.8.4.4/dns-query \ | ||
| --fallback=tls://1.1.1.1:853 \ | ||
| --fallback=tls://1.0.0.1:853 \ | ||
| --fallback=tls://8.8.8.8:853 \ | ||
| --fallback=tls://8.8.4.4:853 \ | ||
| --cache \ | ||
| --cache-optimistic \ | ||
| --cache-size=4194304 \ | ||
| --cache-min-ttl=60 \ | ||
| --cache-max-ttl=86400 \ | ||
| --upstream-mode=fastest_addr \ | ||
| --pending-requests-enabled \ | ||
| --refuse-any \ | ||
| --timeout=10s \ | ||
| --max-go-routines=1000 | ||
|
|
||
| # ── Identity ────────────────────────────────────────────────────────── | ||
| # DynamicUser creates a transient uid/gid with no login shell, no | ||
| # home directory, and no persistence beyond the service lifetime. | ||
| DynamicUser=yes | ||
|
|
||
| # ── Capabilities ────────────────────────────────────────────────────── | ||
| # Port 53 requires CAP_NET_BIND_SERVICE. Grant only that, nothing else. | ||
| # PrivateUsers=yes is intentionally omitted — it creates a user | ||
| # namespace that strips real capabilities, breaking port 53 binding. | ||
| AmbientCapabilities=CAP_NET_BIND_SERVICE | ||
| CapabilityBoundingSet=CAP_NET_BIND_SERVICE | ||
| NoNewPrivileges=yes | ||
|
|
||
| # ── Filesystem isolation ────────────────────────────────────────────── | ||
| ProtectSystem=strict | ||
| ProtectHome=yes | ||
| PrivateTmp=yes | ||
| PrivateDevices=yes | ||
| ReadWritePaths= | ||
|
|
||
| # StateDirectory creates /var/lib/private/dnsproxy owned by the | ||
| # dynamic user. Currently unused but ready for --output if needed. | ||
| StateDirectory=dnsproxy | ||
| LogsDirectory=dnsproxy | ||
|
Comment on lines
+84
to
+85
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The service creates StateDirectory and LogsDirectory but doesn't specify directory permissions. Consider adding There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The service creates log directories (
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. there is a doc comment right above it |
||
| StateDirectoryMode=0750 | ||
| LogsDirectoryMode=0750 | ||
|
|
||
| # ── Kernel isolation ───────────────────────────────────────────────── | ||
| ProtectKernelTunables=yes | ||
| ProtectKernelModules=yes | ||
| ProtectKernelLogs=yes | ||
| ProtectControlGroups=yes | ||
| ProtectHostname=yes | ||
| ProtectClock=yes | ||
| ProtectProc=invisible | ||
| ProcSubset=pid | ||
|
|
||
| # ── Network isolation ──────────────────────────────────────────────── | ||
| # AF_INET/AF_INET6 — DNS listening + encrypted upstream connections | ||
| # AF_UNIX — journald logging socket | ||
| # AF_NETLINK — Go runtime enumerates network interfaces at start | ||
| RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX AF_NETLINK | ||
|
|
||
| # IPAddressDeny/Allow are intentionally omitted. They use BPF cgroup | ||
| # filters that would block dnsproxy's own outbound connections to | ||
| # upstream resolvers (1.1.1.1, 8.8.8.8, 9.9.9.9, etc). | ||
|
|
||
| # ── Syscall filtering ─────────────────────────────────────────────── | ||
| SystemCallArchitectures=native | ||
| SystemCallFilter=@system-service | ||
| SystemCallFilter=~@privileged @resources | ||
|
|
||
| # ── Misc hardening ────────────────────────────────────────────────── | ||
| RestrictNamespaces=yes | ||
| RestrictRealtime=yes | ||
| RestrictSUIDSGID=yes | ||
| LockPersonality=yes | ||
| MemoryDenyWriteExecute=yes | ||
| UMask=0077 | ||
|
|
||
| # ── Resource limits ────────────────────────────────────────────────── | ||
| LimitNOFILE=65535 | ||
| LimitNPROC=512 | ||
|
|
||
| # ── Restart policy ─────────────────────────────────────────────────── | ||
| # "No disruption": restart immediately on failure, with burst protection. | ||
| Restart=always | ||
| RestartSec=2 | ||
| StartLimitBurst=5 | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The service file defines StartLimitBurst=5 but is missing the required StartLimitIntervalSec parameter. Without specifying the time interval, the burst protection may not work as expected. Consider adding something like
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. systemd in my host complained that |
||
|
|
||
| [Install] | ||
| WantedBy=multi-user.target | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider adding installation instructions for package managers (apt, yum, etc.) in addition to the manual binary download method. This would make the service more accessible to users on different distributions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not applicable