Skip to content

feat(dns): add DNS over HTTPS (DoH) support via blocky#200

Open
awlx wants to merge 2 commits intoCachyOS:developfrom
awlx:feat/doh-support
Open

feat(dns): add DNS over HTTPS (DoH) support via blocky#200
awlx wants to merge 2 commits intoCachyOS:developfrom
awlx:feat/doh-support

Conversation

@awlx
Copy link
Contributor

@awlx awlx commented Mar 25, 2026

Adds DNS over HTTPS (DoH) support using blocky as a lightweight local DNS proxy. When DoH is enabled, blocky handles resolution over HTTPS and NetworkManager points to 127.0.0.1.

Built on top of #196 (custom DNS server support).

What changed

DNS over HTTPS (DoH)

  • Added DoH toggle for each server that supports it (Cloudflare, Google, Quad9, AdGuard, FFMUC, etc.)
  • DoH and DoT are mutually exclusive — enabling one disables the other
  • Uses blocky as local DNS proxy on 127.0.0.1:53
  • Bootstrap DNS uses DoT-encrypted queries (tcp-tls:hostname with ips: list) when the server supports DoT, falls back to plaintext IPs otherwise
  • Both IPv4 and IPv6 bootstrap addresses are included (quoted for YAML safety)
  • blocky installed from CachyOS repo via pacman with pkexec GUI password prompt
  • Upstream strategy set to strict for predictable resolution order
  • Reset clears blocky (stops service, disables it) and restores DHCP
  • CLI gets --doh flag on dns set subcommand
  • State preserved across restarts: reads blocky config to detect active DoH server

Custom DNS with DoH

  • Added DoH URL input field to the custom DNS server form
  • Custom servers can use DoH with their own URL, using the configured IPv4/IPv6 addresses and DoT hostname for bootstrap resolution
  • CLI dns set-custom gets --doh and --doh-url flags
  • Empty bootstrap IPs are filtered to prevent blocky config errors

NetworkManager hardening

  • Set ipv4.ignore-auto-dns yes and ipv6.ignore-auto-dns yes when setting DNS (both DoT and DoH) to prevent DHCP-provided DNS servers from leaking alongside the configured encrypted servers
  • Reset restores ignore-auto-dns no for both protocols
  • Blocky restarts after NM (not before) to avoid bootstrap failures during network transition

i18n

  • All new strings added across all 31 locales

Why blocky over dnscrypt-proxy

  • Simple YAML config — easy to generate programmatically, single file
  • Native DoH + DoT upstream support — covers the two most requested protocols
  • Bootstrap DNS with DoTtcp-tls: upstream with ips: for encrypted bootstrap, dnscrypt-proxy only supports plaintext bootstrap
  • Lightweight — single Go binary, ~15 MB, ~20 MB RAM, no databases or temp files
  • DoQ coming soon0xERR0R/blocky#2013 adds DNS over QUIC upstream support; once shipped, adding DoQ here is a one-line config change
  • dnscrypt-proxy is heavier, uses TOML + server stamps (harder to generate), and its primary focus is DNSCrypt protocol which is less widely adopted than DoH

More details on blocky: https://0xerr0r.github.io/blocky/latest/

Testing

Tested on CachyOS with NetworkManager 1.52, systemd-resolved, and blocky 0.29.0:

  • cachyos-hello dns set -c "Starlink" -s cloudflare --doh — sets Cloudflare with DoH enabled
  • cachyos-hello dns set-custom -c "Starlink" --ipv4 "45.90.28.220,45.90.30.220" --doh --doh-url "https://dns.nextdns.io/eb9cb4" --dot-hostname "eb9cb4.dns.nextdns.io" — custom NextDNS DoH with DoT bootstrap
  • cachyos-hello dns set-custom -c "Starlink" --ipv4 "45.90.28.220" --doh --doh-url "https://dns.nextdns.io/eb9cb4" — custom DoH without DoT hostname (plaintext bootstrap)
  • cachyos-hello dns list-servers — shows DoH URLs alongside DoT hostnames
  • cachyos-hello dns reset -c "Starlink" — resets DNS, stops blocky, restores DHCP
  • GUI: select server → check DoH → Apply; verified blocky running, config written, DNS resolving via dig @127.0.0.1
  • Verified DoT bootstrap: tcp-tls:cloudflare-dns.com with IPs when DoT available
  • Verified resolvectl query --cache=no shows encrypted transport: yes for DoT
  • Verified ignore-auto-dns prevents DHCP DNS leaks on both IPv4 and IPv6
  • Verified state persists across app restarts (blocky config read back)
  • Verified switching between DoH ↔ DoT ↔ reset works cleanly

Related issues

Future: DNS over QUIC (DoQ)

DoQ support can be added with minimal changes once blocky ships 0xERR0R/blocky#2013. The implementation would be a new doq:// upstream URL in the blocky config — no architectural changes needed.

Add a 'Custom' option to the DNS server dropdown allowing users to
specify their own DNS server addresses and DoT hostname, addressing
use cases like NextDNS or other custom resolvers.

Changes:
- Add 'Custom' entry to DNS server combo box with IPv4, IPv6, and
  DoT hostname input fields
- Use NetworkManager's native 'address#hostname' notation to persist
  DoT hostnames across restarts
- Read back DoT state and hostname from NM on startup
- Add SNI hostname validation (RFC-compliant DNS labels)
- Add 'set-custom' CLI subcommand for custom DNS from command line
- Fix preset servers to include DoT hostname in addr#hostname format
- Add i18n strings for custom DNS to all 31 locales

Closes: CachyOS#144
Copy link
Member

@vnepogodin vnepogodin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good overall, besides AUR package

@awlx
Copy link
Contributor Author

awlx commented Mar 25, 2026

Found a bug after applying the DoH config and restarting Hello it picks it up as custom servers. Fixing that at the moment :).

@awlx awlx force-pushed the feat/doh-support branch from 77b3aea to b8cc490 Compare March 25, 2026 14:38
@awlx
Copy link
Contributor Author

awlx commented Mar 25, 2026

Ok, it's now fixed and tested all kinds of scenarios:

  • Switching between DoH and DoT and no encryption for pre-configured servers
  • Tested Plaintext DNS and DoH and DoT for custom servers, tested DoH without DoT bootstrap for custom servers
  • Tested restarting of Hello and it correctly sees all the configured things reading from blocky or NetworkManager

@awlx awlx force-pushed the feat/doh-support branch 2 times, most recently from 51b7e89 to 2bfe65b Compare March 25, 2026 15:02
@awlx awlx requested review from ptr1337 and vnepogodin March 25, 2026 17:24
@ptr1337 ptr1337 requested a review from Copilot March 25, 2026 17:51
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds DNS-over-HTTPS (DoH) support by introducing a local blocky DNS proxy (127.0.0.1:53) and wiring it into both the GUI DNS page and the CLI, alongside existing DoT/custom DNS functionality.

Changes:

  • Add DoH toggle/support for preset providers and custom servers (GUI + CLI), using blocky as a local proxy.
  • Generate/read blocky YAML config to persist and detect active DoH server across restarts.
  • Adjust NetworkManager DNS application/reset logic and extend i18n keys for new UI/CLI strings.

Reviewed changes

Copilot reviewed 35 out of 35 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
src/pages/dns.rs GUI: add DoH toggle, custom DNS fields (including DoH URL), and apply logic for DoH via blocky
src/dns.rs Add DoH URL map, blocky config generation + parsing helpers, and CLI arg extensions
src/cli_handler.rs CLI: add --doh/custom DoH handling and show DoH URLs in list-servers
src/actions.rs Implement blocky install/config/start flow, DoH NM wiring, and new DNS parsing helpers
i18n/*/cachyos_hello.ftl Add new strings for DoH + custom DNS UI/CLI messages

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +33 to +35
enable-doh = Enable DNS over HTTPS (DoH)
doh-tooltip = Encrypt DNS queries using HTTPS via blocky local proxy (requires server support, installs blocky)
doh-blocky-install-failed = Failed to install blocky for DoH support!
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New zh-CN locale entries for DoH/custom DNS are still in English (e.g. enable-doh, doh-tooltip, custom-dns-*). This is inconsistent with the rest of the zh-CN file and will show English UI text for Chinese users. Please provide Chinese translations (or, if the project convention is to keep untranslated strings elsewhere, consider documenting that and/or using a consistent fallback strategy).

Copilot uses AI. Check for mistakes.
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 35 out of 35 changed files in this pull request and generated 6 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 35 out of 35 changed files in this pull request and generated 5 comments.

Comments suppressed due to low confidence (2)

src/actions.rs:175

  • conn_name.replace('\'', "'\\'") does not correctly escape single quotes for use inside a single-quoted shell string (and can break the nmcli command / enable injection). Use the standard bash single-quote escape sequence ('\'') or a shared shell-escape helper, consistent with the escaping used for escaped_config above.
    src/actions.rs:265
  • conn_name.replace('\'', "'\\'") is also used here and has the same incorrect single-quote escaping issue, which can break the command string passed to bash -c. Please switch to the correct bash-safe escaping ('\'') or a shared escape helper.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@awlx awlx force-pushed the feat/doh-support branch from 207aa52 to d627cc8 Compare March 25, 2026 18:52
Add DoH support to the DNS settings page using blocky as a local DNS proxy.
When DoH is enabled, blocky is installed (blocky-bin from AUR), configured
with the selected server's DoH URL, and started as a systemd service.
NetworkManager is pointed to 127.0.0.1 for resolution.

Changes:
- Add DoH URL map for 14 DNS servers that support DNS over HTTPS
- Add blocky config generation with DoT-encrypted bootstrap DNS when the
  server supports it, falling back to plaintext IPs otherwise
- Add DoH checkbox to DNS settings GUI (mutually exclusive with DoT)
- Add --doh flag to 'dns set' CLI subcommand (conflicts_with dot)
- Add --doh and --doh-url flags to 'dns set-custom' for custom DoH
  servers, using the custom IPv4/IPv6 addresses and DoT hostname for
  bootstrap resolution
- Add DoH URL input field to the custom DNS server form
- Auto-install blocky-bin via paru with pkexec for GUI password prompt
- Stop and disable blocky on DNS reset or when switching to DoT/plain
- Show DoH support in 'dns list-servers' output
- Add i18n strings for DoH to all 31 locales

Built on top of CachyOS#196 (custom DNS server support).

Note: DNS over QUIC (DoQ) can be added once blocky ships with
0xERR0R/blocky#2013 (DoQ upstream support)

Addresses: CachyOS#156, CachyOS#144
@awlx awlx force-pushed the feat/doh-support branch from d627cc8 to 8682824 Compare March 25, 2026 18:53
@awlx
Copy link
Contributor Author

awlx commented Mar 26, 2026

@ptr1337 @vnepogodin all the relevant Copilot suggestions should now be addressed. I tested all the combinations again and it works for me :).

As a follow-up (don't want to over do this PR), I wonder if when pressing "reset" the selection should jump to "DHCP (automatic)" so people clearly see that none of the DNS servers is used. Same for the defaults on first start.

I can add a separate PR for that if it's something you are interested in, otherwise this now works :).

@vnepogodin
Copy link
Member

Will review in the coming days.

Yeah "reset" should reset to the previous state without CachyOS Hello modifications

@awlx
Copy link
Contributor Author

awlx commented Mar 26, 2026

Yep, it does that already. I just thought of also making that visually more clear. But as said, it's probably something for a follow-up PR for now the behavior is the same as before :).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature Request] Add DoH/DoT disable option and custom server support in DNS Changer DNS selection improvements

4 participants