Skip to main content

max / alloy

Say why DoT stays opportunistic, now that it is measured rather than feared The setting is unchanged and its stated reason was wrong. This file argued that a global DNSOverTLS=yes would refuse the MagicDNS stub and cost us `ssh astra`. Measured on fw12, a tailnet-joined install, which is what GO alloy f4806a35 was open for: Tailscale sets DoT off on its own link through resolved's per-link API, per-link wins over the global, and under `yes` both astra and fw13 resolved and a TCP connection to astra:22 opened. MagicDNS was never at risk from this file. What `yes` does break is everything else. makenot.work and fedoraproject.org both stopped resolving, because `yes` refuses a server that cannot do DoT and port 853 was closed on both the LAN router and the ISP resolver behind it. A router that does not speak DoT is the normal case, so `yes` as a default is a machine that cannot resolve anything off the tailnet. Also recorded because the setting reads stronger than it is: with 853 closed, opportunistic buys nothing on that network and every lookup is plaintext, while resolvectl still reports DNSOverTLS=opportunistic. That line is the setting, not evidence of encryption. The Containerfile guard keeps refusing `yes` and now says why in the terms that actually hold.
Co-Authored-By
Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session
https://claude.ai/code/session_01WFBzMprSmNCfvdj2cGZyka
Author: Max Johnson <me@maxj.phd> · 2026-09-08 18:00 UTC
Signed with PGP, not checked
Commit: 3fc56289686dd58d25213ad39b5340a7da9c2212
Parent: 3ff1300
2 files changed, +42 insertions, -23 deletions
M Containerfile +1 -1
@@ -3852,7 +3852,7 @@
3852 3852 || { echo "systemd-tmpfiles rejects $tmpf" >&2; exit 1; }; \
3853 3853 dns=/etc/systemd/resolved.conf.d/10-alloy-dns.conf; \
3854 3854 grep -q '^DNSOverTLS=opportunistic' "$dns" \
3855 - || { echo "$dns does not set DNSOverTLS, or sets 'yes' before anyone measured it against MagicDNS" >&2; exit 1; }; \
3855 + || { echo "$dns does not set DNSOverTLS, or sets 'yes', which breaks every name off the tailnet on an uplink with no DoT (measured, see the file)" >&2; exit 1; }; \
3856 3856 echo "hardening drop-ins: sysctl, modprobe, kargs, sway, flatpak, resolved — all present and non-inert"
3857 3857
3858 3858 # =====================================================================
@@ -1,31 +1,50 @@
1 - # Alloy DNS posture: encrypted where it can be, and never at the cost of
2 - # MagicDNS.
1 + # Alloy DNS posture: encrypted where the network offers it, and never at the
2 + # cost of MagicDNS.
3 3 #
4 4 # The Containerfile has a note beside systemd-resolved saying Alloy leaves it
5 - # alone. This is the first opinion Alloy has about it, and the second half of
6 - # the setting matters more than the first.
5 + # alone. This is the first opinion Alloy has about it.
7 6 #
8 - # DNSOverTLS=opportunistic RATHER THAN yes. Every machine in this tree is
9 - # addressed by tailnet name (memory `feedback_no_direct_ips`), and Tailscale
10 - # configures resolved itself: MagicDNS answers come from the 100.100.100.100
11 - # stub, and split-DNS routes for the tailnet domain are pushed into resolved
12 - # per-link. A global `yes` refuses any server that cannot do DoT, and that
13 - # stub cannot. `ssh astra` failing to resolve is a worse outcome than a
14 - # plaintext lookup on a coffee-shop network.
7 + # MEASURED 2026-09-08 on fw12, a tailnet-joined Alloy install, which is what
8 + # GoingsOn alloy `f4806a35` was open for. The measurement moved the reason for
9 + # this setting without moving the setting, so what follows is what was seen
10 + # rather than what was expected.
15 11 #
16 - # `opportunistic` uses DoT when the server offers it and falls back when it
17 - # does not, which is downgradeable by an active attacker and is honest about
18 - # being a best-effort setting rather than a guarantee.
12 + # MAGICDNS IS NOT THE CONSTRAINT, and an earlier version of this comment said
13 + # it was. Tailscale does not rely on the global default: it sets DNS over TLS
14 + # off on its own link through resolved's per-link API, and `resolvectl status`
15 + # shows `-DNSOverTLS` on tailscale0 while the global reads whatever is set
16 + # here. Per-link wins, so a global `DNSOverTLS=yes` leaves the 100.100.100.100
17 + # stub alone. Under `yes`, `astra` and `fw13` both resolved and a TCP
18 + # connection to astra:22 opened. Nothing here needs to protect MagicDNS from
19 + # this file.
19 20 #
20 - # UPGRADING THIS IS A MEASUREMENT, NOT A PREFERENCE. `yes` becomes correct
21 - # the day someone verifies on a tailnet-joined Alloy machine that MagicDNS
22 - # still resolves under it, or configures a DoT-capable resolver for the
23 - # non-tailnet routes explicitly. GoingsOn alloy `f4806a35` holds that.
21 + # THE CONSTRAINT IS THE UPLINK. Under `DNSOverTLS=yes` every ordinary name
22 + # failed: `makenot.work` and `fedoraproject.org` both stopped resolving,
23 + # because `yes` refuses a server that cannot do DoT and neither uplink can.
24 + # Port 853 was closed on the LAN router and on the ISP resolver behind it,
25 + # while 53 answered. A home router that does not speak DoT is the normal case,
26 + # not this network being unusual, so `yes` shipped as a default is a machine
27 + # that cannot resolve anything off the tailnet.
24 28 #
25 - # DNSSEC=allow-downgrade for the same shape of reason: full `yes` breaks on
26 - # networks whose resolver mangles or strips DNSSEC records, which includes a
27 - # lot of hotel and airport DNS, and the failure mode is total rather than
28 - # degraded.
29 + # WHAT `opportunistic` IS WORTH, stated plainly because the setting reads
30 + # stronger than it is. It uses DoT when the server offers it and falls back
31 + # when it does not, which an active attacker can downgrade. On the network
32 + # measured above it buys nothing at all: with 853 closed, every lookup is
33 + # plaintext, and `resolvectl status` still reports `DNSOverTLS=opportunistic`,
34 + # because that line is the setting and not evidence of encryption. Read it as
35 + # a statement of intent that pays off on a network whose resolver offers DoT,
36 + # and not as a guarantee about any particular one.
37 + #
38 + # UPGRADING THIS IS NO LONGER A MEASUREMENT. It now needs a DoT-capable
39 + # resolver named explicitly for the non-tailnet routes, which is choosing a
40 + # DNS provider on every user's behalf. That is a policy question of the same
41 + # shape as the flatpak remote, which Alloy answered by configuring none
42 + # (GoingsOn alloy `e10e0e40`), so it wants the same kind of ruling rather than
43 + # a default picked here.
44 + #
45 + # DNSSEC=allow-downgrade for a related reason: full `yes` breaks on networks
46 + # whose resolver mangles or strips DNSSEC records, which includes a lot of
47 + # hotel and airport DNS, and the failure mode is total rather than degraded.
29 48 [Resolve]
30 49 DNSOverTLS=opportunistic
31 50 DNSSEC=allow-downgrade