fix(dns): prove the bridge is there before routing the machine at it - #361
Merged
Conversation
`startDaemon` spawned with `stdio: "ignore"`, wrote the pidfile from `child.pid`, and returned `started: true` in the same tick — before the child had done anything, including exist. On a machine where the daemon dies on startup that printed `ok bridge started (pid 22900)` for a process that was already gone, and `enable` went on to install catch-all routing (`Domains=~.`) pointing every lookup on the box at a dead port. The machine lost DNS entirely and the reason was unrecoverable: the daemon had written it to stderr, which was routed to /dev/null. Found on a Kubuntu desktop whose node comes from mise — under the privilege escalation `enable` performs, the interpreter was not where the daemon needed it. The specific cause matters less than the class: every startup failure arrived as the same confident success line. - stdout and stderr go to moshpit-dns.log next to the pidfile, truncated per run, so a startup failure has somewhere to have happened - an early exit (or a spawn that never ran) is a failed start carrying the daemon's own output; no pidfile is left behind for a dead process, which is what made the next run believe a bridge was already up - "started" now means it answered a real query on the port; alive but silent is reported as unproven rather than rounded up or killed, since a slow registry fetch looks exactly like that - `enable` refuses to write the drop-in at all when the bridge is down, and takes back the restore point it recorded Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
ThreatCrush Security Scan93 finding(s) HIGH/CRITICAL: 2 | MEDIUM: 43 | LOW: 48
…and 43 more. Full results in the Security tab. Snippets are redacted; ThreatCrush never prints matched credential material. |
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What broke
moshcode dns enablereportedok bridge started on 127.0.0.1:5354 (pid 22900)for a bridge that was already dead, then installed catch-all routing —Domains=~.— pointing every lookup on the machine at that dead port. The box lost DNS entirely, and there was no way to find out why: the daemon wrote its reason to stderr, and stderr went to/dev/null.startDaemonspawned withstdio: "ignore", wrote the pidfile fromchild.pid, and returnedstarted: truein the same tick — before the child had done anything, including exist.Found on a Kubuntu desktop whose node comes from mise: under the privilege escalation
enableperforms, the interpreter was not where the daemon needed it. That specific cause matters less than the class — a port it cannot bind, a half-written install, a missing interpreter all arrived as the same confident success line.What changed
moshpit-dns.logbeside the pidfile, truncated per run so a previous crash can't be mistaken for this one's.exit/erroragainst a readiness probe; either one meansstarted: false, carrying the daemon's own words back to the caller.enablebelieve a bridge was already running and skip starting one.started: true, verified: falseand says so. Killing a bridge that was merely waking up is the worse mistake.enablerefuses to route at a bridge that is down, before writing the drop-in, and takes back the restore point it recorded.READY_TIMEOUT_MSis 8s. It costs nothing on a real failure — a daemon that dies resolves the race immediately — and only bounds the unproven case. The bridge binds after fetching the ending list, measured at ~2.9s against the live registry with 5674 endings.Before / after
Tests
test/dns-daemon-verify.test.mjs, 11 cases: startup death, spawn that never ran, no stale pidfile, log capture and persistence, a bridge that really answers over UDP, alive-but-silent, the already-running short-circuit, and the fourenabledecisions — refuse, take back the restore point, flag the unproven, and don't accuse a starter that simply doesn't report verification.Full suite: 1545 tests, 0 failures.
🤖 Generated with Claude Code