[BUG] Encrypted DNS (DoH) not working on MT6000 Flint 2 - Firmware 4.8.4

Hi everyone,

after updating my GL-MT6000 Flint 2 from 4.8.3 → 4.8.4 (Firmware Type: release, compiled 2026-03-12), Encrypted DNS / DoH stopped working completely.

:warning: Important: this update arrived as a standard stable release — no beta label, no warning, no indication of gray release status. There was no way to know this was experimental.

What happens
Every time I select any DoH preset from Network → DNS → Encrypted DNS (Quad9, Cloudflare, etc.), all clients immediately lose internet. Wi-Fi stays connected but DNS fails completely. Ping to 8.8.8.8 still works — confirming it's a DNS-only issue.

This worked perfectly on 4.8.3.

Steps to reproduce

  1. Go to Network → DNS
  2. Set Mode → Encrypted DNS
  3. Select any preset (e.g. quad9-doh-ip4-port443-filter-pri)
  4. Tap Submit
  5. All clients lose internet immediately.
    Root cause
    The preset list uses hostnames (dns.quad9.net, dns.cloudflare.com etc.). The https-dns-proxy service on port 5453 needs to resolve those hostnames before it can start — but DNS isn't up yet at that point. Bootstrap deadlock. In 4.8.4 the firewall rule lan_drop_leaked_dns is now enabled and blocks any DNS fallback, making the failure total.
    Workaround
    Use DoH with direct IP instead of hostname — these work fine on 4.8.4:
    https://9.9.9.9/dns-query (Quad9, same filtering as filter-pri preset)
    https://1.1.1.1/dns-query (Cloudflare)
    https://8.8.8.8/dns-query (Google)
    Note: the app has no field to type a custom DoH URL — the workaround above requires SSH. Please add a custom input field in the Encrypted DNS UI. Device info
    Model: GL-MT6000 Flint 2
    Firmware: 4.8.4 — Type: release
    Compiled: 2026-03-12 17:56:15
    Previous firmware: 4.8.3 (working)
    AdGuard Home: disabled
    IPv6: disabled
    Update received: automatically via router panel, shown as standard stable release
    Thanks
6 Likes

Is there no pre defined bootstrap dns here in the application?

2 Likes

Good point. In a correct https-dns-proxy setup, a plain DNS bootstrap (e.g. 8.8.8.8) should be configured so the service can resolve the DoH hostname on startup before DNS is fully operational.
Looking at my config (debug_info.log), dnsmasq is configured with:
server=127.0.0.1#5453 (only upstream)
noresolv=1 (no fallback resolv.conf)
This means dnsmasq has zero fallback if the service on port 5453 doesn't respond. There is no visible bootstrap plain DNS configured for https-dns-proxy in 4.8.4.
On 4.8.3 this worked fine, so either:
The bootstrap DNS was present in 4.8.3 and got removed/broken in 4.8.4
The bootstrap mechanism changed behavior between the two versions
The workaround of using https://9.9.9.9/dns-query (direct IP) confirms the issue: with an IP-based URL there is no hostname to resolve at bootstrap, so the service starts correctly.
Could a GL.iNet dev confirm whether the bootstrap DNS config for https-dns-proxy changed between 4.8.3 and 4.8.4?

1 Like

I can confirm a related issue on the same firmware, in a slightly different scenario.

Device: GL-MT6000 (Flint 2)

Firmware: 4.8.4 (updated from 4.8.3, settings kept)

In my setup, DoH works fine with AdGuard Home enabled. The moment I disable AdGuard Home, DNS stops working completely for all clients and for the router itself.

This matches your finding exactly. Via SSH I confirmed that dnsmasq is hardcoded to forward all DNS requests to 127.0.0.1#5453, even when AdGuard Home is disabled and nothing is listening on that port:


/etc/config/dhcp: list server '127.0.0.1#5453'

/etc/config/dhcp: option noresolv '1'

With noresolv=1 and no service on port 5453, there is zero fallback — complete DNS outage.

Workaround: Keep AdGuard Home enabled (DoH works correctly through it). Switching to Plain DNS also restores connectivity, but sacrifices encryption.

So the missing bootstrap DNS you identified affects not just the initial DoH startup, but also any situation where the service on port 5453 is unavailable — including simply disabling AdGuard Home.

1 Like

Thank you, this is very valuable — you've just confirmed the bug is actually much broader than DoH specifically.
The root issue is clear now: in 4.8.4, dnsmasq is hardcoded to forward everything to 127.0.0.1#5453 with noresolv=1, but there is no guarantee anything is listening on that port.
This means the bug affects multiple scenarios:
DoH enabled with hostname-based preset → port 5453 service fails to bootstrap → DNS outage
AdGuard Home disabled → nothing on port 5453 → DNS outage
Any future case where the port 5453 service crashes or fails to start
In 4.8.3 this was handled correctly. Something changed in 4.8.4 that removed the safety net.
The actual fix GL.iNet needs to implement:
dnsmasq should always have at least one plain DNS fallback (e.g. the WAN-provided DNS from resolv.conf) for cases when port 5453 is unavailable. The noresolv=1 + single upstream approach with no fallback is the real architectural problem introduced in 4.8.4.
This is not just a DoH bug — it's a DNS architecture regression that can cause a complete outage in multiple common scenarios.

1 Like

You are using DOH in glui or Adguard settings? Cause adguard has its own bootstrap servers.

I'm using DoH configured via the GL.iNet UI (Network → DNS → Encrypted DNS), not AdGuard Home. AdGuard Home is completely disabled on my setup.

That's exactly the point — AdGuard Home has its own bootstrap DNS mechanism which handles this correctly (as the previous reply confirmed: DoH works fine when AGH is enabled). The problem is that the GL.iNet native DoH implementation (https-dns-proxy on port 5453) has no working bootstrap in 4.8.4.

So to summarize the two confirmed scenarios:

AGH enabled → DoH works :white_check_mark: (AGH handles bootstrap internally)

AGH disabled, GL.iNet native DoH → DNS outage :cross_mark: (no bootstrap, noresolv=1, nothing on port 5453)

This means the native GL.iNet DoH implementation is effectively broken in 4.8.4 for anyone not using AdGuard Home.

1 Like

DoH is configured in both places:

GL.iNet GUI: Network → DNS → Encrypted DNS (DoH)

AdGuard Home: Custom upstream DoH servers with bootstrap DNS configured

AGH bootstrap servers:

  • 9.9.9.9

  • 149.112.112.112

AGH upstream (DoH):

AGH fallback:

Note that AGH uses IP-based DoH URLs for the primary upstreams — which avoids the bootstrap deadlock entirely (no hostname to resolve at startup). The Mullvad fallback uses a hostname, but that’s covered by the bootstrap servers.

This is exactly why DNS works fine with AGH enabled: AGH has a proper bootstrap configuration. The problem only appears when AGH is disabled, because then dnsmasq falls back to 127.0.0.1#5453 with noresolv=1 and nothing listening on that port — no bootstrap, no fallback, complete outage.

1 Like

Mine on 4.8.3 doesnt use https-dns-proxy at all, it is using dnscrypt-proxy. Has this changed between versions?

This is a crucial finding — it could explain everything.
According to the GL.iNet docs, the Encrypted DNS section supports multiple backends: DNSCrypt-Proxy, DNS over HTTPS, DNS over TLS, and Oblivious DoH . If 4.8.3 used dnscrypt-proxy as the backend for DoH presets and 4.8.4 switched to https-dns-proxy, that would explain exactly why 4.8.3 worked and 4.8.4 doesn't.
The key difference: dnscrypt-proxy has a built-in bootstrap resolver mechanism by design. https-dns-proxy in its default OpenWrt configuration requires bootstrap_dns to be explicitly set (e.g. option bootstrap_dns '1.1.1.1,8.8.8.8'). If GL.iNet migrated to https-dns-proxy in 4.8.4 but forgot to configure the bootstrap DNS field, the service will always deadlock on hostname-based resolvers .
Can you check on your 4.8.3 device which process is running for DoH?
ps | grep -E 'dnscrypt|https-dns'
And on 4.8.4 (my device) I can confirm only https-dns-proxy is running — with no bootstrap DNS configured.
If this backend switch is confirmed, the fix for GL.iNet is straightforward: add bootstrap_dns '8.8.8.8' to the https-dns-proxy config in 4.8.4.

grep -E 'dnscrypt|https-dns'
2563 root 1210m S /usr/sbin/dnscrypt-proxy -config /etc/dnscrypt-proxy2/dnscrypt-proxy.toml
13694 root 1340 S grep -E dnscrypt|https-dns

Update: I ran the check on my 4.8.4 device and it's also using dnscrypt-proxy, not https-dns-proxy:

2563 root 1210m S /usr/sbin/dnscrypt-proxy -config /etc/dnscrypt-proxy2/dnscrypt-proxy.toml

So the backend did not change between 4.8.3 and 4.8.4 — both use dnscrypt-proxy.
This makes the bug even more interesting: dnscrypt-proxy IS running, which means the service itself starts fine. The failure must happen at a different stage — most likely when the GL.iNet UI writes a new server stamp to dnscrypt-proxy.toml and restarts the service. During that restart, the new server can't be reached, dnscrypt-proxy crashes or goes into error state, and since dnsmasq has noresolv=1 pointing exclusively to port 5453, there is zero fallback.
The next diagnostic step would be to compare the content of /etc/dnscrypt-proxy2/dnscrypt-proxy.toml in two states:
Before selecting a DoH preset (working state)
After selecting a preset (broken state)

cat /etc/dnscrypt-proxy2/dnscrypt-proxy.toml

This would tell us exactly what GL.iNet UI writes into the config when a preset is applied, and whether the stamp or listen_addresses port changes.

bootstrap_resolvers = ['9.9.9.11:53', '8.8.8.8:53']

ignore_system_dns = true

Found this in 4.8.3

I have the same issue. I was using Cloudflare DoH.

3 Likes

Same issue here, had to revert to basic Quad9. If this is any help, I’ve removed the package gl-sdk4-ddns and installed via LuCI the packages acme, acme-dnsapi and luci-app-acme. This shouldn’t modify the behavior for DoH.

If there’s any test I can run, just let me know.

Thanks for confirming — this is now at least 3 users on 4.8.4 with the same issue, which makes it clearly a regression and not an isolated config problem.

The packages you installed (acme, luci-app-acme) don't touch the DNS stack so they shouldn't be relevant — good to rule that out.

If you're willing to run some tests, these would help narrow down the exact failure point:

1 — Check dnscrypt-proxy status after applying a DoH preset:

ps | grep dnscrypt

logread | grep dnscrypt | tail -20

2 — Check what's actually listening on port 5453:

netstat -tlnup | grep 5453

3 — Check the dnscrypt-proxy config after selecting a preset:

cat /etc/dnscrypt-proxy2/dnscrypt-proxy.toml | grep -E 'listen|server_names|urls|stamp'

4 — Most important: run step 3 in working state (before selecting a preset or after reverting to plain DNS), then select a DoH preset, wait 10 seconds, and run it again. Compare the two outputs.

This would tell us exactly what the GL.iNet UI writes to the config when a preset is applied and whether dnscrypt-proxy actually restarts cleanly after that change.

I have the same issue - updating to 4.8.4 has resulted in no internet connection. I had to disable Cloudflare DoH.

Poor testing…

2 Likes

Did the test, so here’s the output.

  1. Check dnscrypt-proxy status after applying a DoH preset:
root@GL-MT6000:~# ps | grep dnscrypt
15022 root      1244 S    grep dnscrypt
root@GL-MT6000:~# logread | grep dnscrypt | tail -20
root@GL-MT6000:~#
-> no logs
  1. Check what's actually listening on port 5453:
root@GL-MT6000:~# netstat -tlnup | grep 5453
root@GL-MT6000:~#
-> once again, no output
  1. Check the dnscrypt-proxy config after selecting a preset:

Regular DNS, tested working :

root@GL-MT6000:~# cat /etc/dnscrypt-proxy2/dnscrypt-proxy.toml | grep -E 'listen|server_names|urls|stamp'
server_names = ["dns4eu","dns4eu-ipv6"]
## List of local addresses and ports to listen to. Can be IPv4 and/or IPv6.
## listen_addresses = ['127.0.0.1:53', '[::1]:53']
## To listen to all IPv4 addresses, use `listen_addresses = ['0.0.0.0:53']`
## To listen to all IPv4+IPv6 addresses, use `listen_addresses = ['[::]:53']`
listen_addresses = ['127.0.0.1:5453']
## Switch to a different system user after listening sockets have been created.
disabled_server_names = []
# cert_ignore_timestamp = false
## They will never be used if lists have already been cached, and if the stamps
## `listen_addrs` must not be empty.
## Addresses that the local DoH server should listen to
# listen_addresses = ['127.0.0.1:3000']
## For each `listen_address` the complete URL to access the server will be:
## `https://<listen_address><path>` (ex: `https://127.0.0.1/dns-query`)
## different servers. In that case, names listed in `server_names`
## If the `urls` property is missing, cache files and valid signatures
    urls = ['https://raw.githubusercontent.com/DNSCrypt/dnscrypt-resolvers/master/v3/public-resolvers.md', 'https://download.dnscrypt.info/resolvers-list/v3/public-resolvers.md']
    urls = ['https://raw.githubusercontent.com/DNSCrypt/dnscrypt-resolvers/master/v3/relays.md', 'https://download.dnscrypt.info/resolvers-list/v3/relays.md']
#     urls = ['https://raw.githubusercontent.com/DNSCrypt/dnscrypt-resolvers/master/v3/odoh-servers.md', 'https://download.dnscrypt.info/resolvers-list/v3/odoh-servers.md']
#     urls = ['https://raw.githubusercontent.com/DNSCrypt/dnscrypt-resolvers/master/v3/odoh-relays.md', 'https://download.dnscrypt.info/resolvers-list/v3/odoh-relays.md']
  #   urls = ['https://www.quad9.net/quad9-resolvers.md']
    urls = ["https://quad9.net/dnscrypt/quad9-resolvers.md", "https://raw.githubusercontent.com/Quad9DNS/dnscrypt-settings/main/dnscrypt/quad9-resolvers.md"]
  #   urls = ['https://raw.githubusercontent.com/DNSCrypt/dnscrypt-resolvers/master/v3/parental-control.md', 'https://download.dnscrypt.info/resolvers-list/v3/parental-control.md']
## A relay can be specified as a DNS Stamp (either a relay stamp, or a
## DNSCrypt stamp) or a server name.
## and "example-server-2" via the relay whose relay DNS stamp is
  #   stamp = 'sdns://AQcAAAAAAAAAAAAQMi5kbnNjcnlwdC1jZXJ0Lg'
urls = ['https://raw.githubusercontent.com/DNSCrypt/dnscrypt-resolvers/master/v3/odoh-servers.md', 'https://download.dnscrypt.info/resolvers-list/v3/odoh-servers.md']

DoH activated, tested not working :

oot@GL-MT6000:~# cat /etc/dnscrypt-proxy2/dnscrypt-proxy.toml | grep -E 'listen|server_names|urls|stamp'
server_names = ["dns4eu","dns4eu-ipv6"]
## List of local addresses and ports to listen to. Can be IPv4 and/or IPv6.
## listen_addresses = ['127.0.0.1:53', '[::1]:53']
## To listen to all IPv4 addresses, use `listen_addresses = ['0.0.0.0:53']`
## To listen to all IPv4+IPv6 addresses, use `listen_addresses = ['[::]:53']`
listen_addresses = ['127.0.0.1:5453']
## Switch to a different system user after listening sockets have been created.
disabled_server_names = []
# cert_ignore_timestamp = false
## They will never be used if lists have already been cached, and if the stamps
## `listen_addrs` must not be empty.
## Addresses that the local DoH server should listen to
# listen_addresses = ['127.0.0.1:3000']
## For each `listen_address` the complete URL to access the server will be:
## `https://<listen_address><path>` (ex: `https://127.0.0.1/dns-query`)
## different servers. In that case, names listed in `server_names`
## If the `urls` property is missing, cache files and valid signatures
    urls = ['https://raw.githubusercontent.com/DNSCrypt/dnscrypt-resolvers/master/v3/public-resolvers.md', 'https://download.dnscrypt.info/resolvers-list/v3/public-resolvers.md']
    urls = ['https://raw.githubusercontent.com/DNSCrypt/dnscrypt-resolvers/master/v3/relays.md', 'https://download.dnscrypt.info/resolvers-list/v3/relays.md']
#     urls = ['https://raw.githubusercontent.com/DNSCrypt/dnscrypt-resolvers/master/v3/odoh-servers.md', 'https://download.dnscrypt.info/resolvers-list/v3/odoh-servers.md']
#     urls = ['https://raw.githubusercontent.com/DNSCrypt/dnscrypt-resolvers/master/v3/odoh-relays.md', 'https://download.dnscrypt.info/resolvers-list/v3/odoh-relays.md']
  #   urls = ['https://www.quad9.net/quad9-resolvers.md']
    urls = ["https://quad9.net/dnscrypt/quad9-resolvers.md", "https://raw.githubusercontent.com/Quad9DNS/dnscrypt-settings/main/dnscrypt/quad9-resolvers.md"]
  #   urls = ['https://raw.githubusercontent.com/DNSCrypt/dnscrypt-resolvers/master/v3/parental-control.md', 'https://download.dnscrypt.info/resolvers-list/v3/parental-control.md']
## A relay can be specified as a DNS Stamp (either a relay stamp, or a
## DNSCrypt stamp) or a server name.
## and "example-server-2" via the relay whose relay DNS stamp is
  #   stamp = 'sdns://AQcAAAAAAAAAAAAQMi5kbnNjcnlwdC1jZXJ0Lg'
urls = ['https://raw.githubusercontent.com/DNSCrypt/dnscrypt-resolvers/master/v3/odoh-servers.md', 'https://download.dnscrypt.info/resolvers-list/v3/odoh-servers.md']

Soo … basically the same output. I’m a loss.

1 Like

Exact the same for me after the upgrade to 4.8.4.

Ping to 8.8.8.8 was possible, but no internet connection with DoH (Quad9).

On top of that this update decreased my 5GHz performance.
Had to downgrade to 4.8.3

Edit:

  • i’m not able to choose Quad9 inside the DoH-app. There’s no more quad9 server available.