mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-06 10:59:59 +00:00
fix(svc-net-tor): stop imposing a bind policy on a foreign dnsmasq
bind-dynamic sat outside the {% if TOR_DNSMASQ_OWNS_LISTENER %} guard that
gates the listen-address lines, and router.yml:72 forces that flag false in
swarm. So on a stack host the drop-in declared it does not own the listener
and then dictated its bind mode anyway -- naming no address at all.
That converts a wildcard-bound instance's sockets into enumeration-derived
ones. When an IPv6 netlink dump aborts, dnsmasq skips the AF_INET pass and
its GC closes every IPv4 listener, silently: the message is LOG_DEBUG and
bind-dynamic bind failures are non-fatal. The node was left with 10 IPv6
listeners and zero IPv4 while four IPv4 addresses existed, and router.yml
had already pointed /etc/resolv.conf at 127.0.0.1 -- so dockerd got ICMP
port-unreachable and could not resolve ghcr.io. 33 failures in 11 groups,
none before the drop-in landed. The two worker nodes, which never received
it, kept 0.0.0.0:53 bound throughout.
Ownership is the right axis, not deployment mode. Where the role owns the
listener, bind-dynamic is load-bearing: a listen-address naming docker0 can
disappear across a docker restart, and without OPT_CLEVERBIND that bind is
fatal. Where it does not own the instance, the directive is pure collateral
-- and next to a base config carrying bind-interfaces it aborts startup
outright.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
4b10d6b937
commit
4739b2de99
2 files changed
+8
-1
No files matched your search
@@ -3,8 +3,8 @@ listen-address=127.0.0.1
|
||||
{% if TOR_CONTAINER_DNS_HOST | length > 0 %}
|
||||
listen-address={{ TOR_CONTAINER_DNS_HOST }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
bind-dynamic
|
||||
{% endif %}
|
||||
no-hosts
|
||||
no-resolv
|
||||
filter-AAAA
|
||||
|
||||
@@ -38,6 +38,13 @@ class TestDnsmasqListeners(unittest.TestCase):
|
||||
self.assertIn("listen-address=127.0.0.1", rendered)
|
||||
self.assertNotIn("listen-address=172.17", rendered)
|
||||
|
||||
def test_no_bind_policy_when_the_listener_is_not_ours(self):
|
||||
rendered = _render_dnsmasq(
|
||||
TOR_DNSMASQ_OWNS_LISTENER=False, TOR_CONTAINER_DNS_HOST=""
|
||||
)
|
||||
self.assertNotIn("bind-dynamic", rendered)
|
||||
self.assertNotIn("listen-address", rendered)
|
||||
|
||||
def test_onion_queries_go_to_the_tor_resolver(self):
|
||||
self.assertIn("server=/onion/127.0.0.1#9053", _render_dnsmasq())
|
||||
|
||||
|
||||
Reference in new issue
Block a user