Add the origin side: nginx template and a setup script that proves itself - #6
Merged
Conversation
…self The gateway config in this repo describes the box that routes without decrypting. Nothing described the box that actually terminates the session, which is where every live Moshpit name currently goes wrong. Diagnosed on a real one. `chovy.hacker` is registered with an IPv6 target pointing at a droplet, and direct-to-origin resolution works — no gateway involved. But the droplet answers :443 for that name with a Let's Encrypt certificate for `dev.profullstack.com`, because there is no server block for `chovy.hacker` and it falls through to the default vhost. Its :80 block then 301s to https://, so a browser is redirected straight into the error. The registry also has `pins: []`, so no client would accept the name even once the certificate is right. That is three separate mistakes and none of them is exotic. Hence a template and a script rather than prose. setup-origin.sh generates the key and self-signed certificate, writes the server block, reloads, and then connects back to 127.0.0.1:443 with the name as SNI to check what is actually presented. A clean `nginx -t` does not mean the name reaches the intended block, and the default-vhost fallthrough is precisely the bug this exists to prevent — so it is verified, not assumed. Reuses an existing key when one is present, because the pin is over the key: certificates can be regenerated freely without invalidating what is published. The template pins TLS 1.3 and asks for X25519MLKEM768, which needs nginx built against OpenSSL 3.5+. The script reads `nginx -V`, warns, and comments the line out rather than handing someone a failed reload that takes their live site down with it. Verified the pin the script prints is byte-identical to what lib/spki.ts computes — the value moshpit-proxy and TronBrowser actually check against. Shell syntax checked, dry-run exercised. 35 tests pass, tsc clean. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
vu1nz Security Review0 finding(s) in PR #? No security issues found. |
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.
This repo described the gateway (routes without decrypting) but nothing described the box that actually terminates the session — which is where every live Moshpit name currently goes wrong.
Diagnosed on a real one
chovy.hackeris registered with an IPv6 target pointing at a DigitalOcean droplet. Direct-to-origin resolution works — the registry hands back the address, no gateway involved. But:{"name":"chovy.hacker","target":"2604:a880:400:d1:0:4:c3fe:1","pins":[]}Three independent mistakes, none exotic:
dev.profullstack.com. Browser reports an invalid certificate; the site looks broken when what's broken is one missingserver_name.pins: []— nothing published, so no client would accept the name even once the certificate is fixed.Hence a template and a script rather than prose.
What the script does
sh scripts/setup-origin.sh chovy.hacker # as rootKey + self-signed certificate → server block → reload → connect back to
127.0.0.1:443with the name as SNI and check what is actually presented.That last step is the point. A clean
nginx -tdoes not mean the name reaches the intended block, and the default-vhost fallthrough is exactly the bug this exists to prevent. So it is verified, not assumed:Other decisions:
X25519MLKEM768, needing nginx against OpenSSL 3.5+. The script readsnginx -V, warns, and comments the line out rather than handing someone a failed reload that takes their live site down with it.Verification
The pin the script prints is byte-identical to what
lib/spki.tscomputes — the valuemoshpit-proxyand TronBrowser actually check against:sh -nclean,--dry-runexercised, 35 tests pass,tsc --noEmitclean.Not run against a live droplet — I have no access to one. The reload-and-verify path is untested end to end and should get one real run before this is relied on.
Note on
.hackerbeing IPv6-onlychovy.hacker's target has no A record, so IPv4-only clients cannot reach it at all regardless of certificates. Out of scope here, but worth fixing before treating it as live.🤖 Generated with Claude Code