feat(dns): resolvers for the Moshpit namespace, and the rest of the internet - #77
Merged
Conversation
…nternet A Moshpit name only resolved for people running the extension or a node. These are public resolvers anyone can point a laptop, phone or router at: `.moshpit`, `.eggs`, `.yeah` come from the registry, and `.com` and everything else is forwarded to 8.8.8.8 and 1.1.1.1, relayed byte for byte so DNSSEC and EDNS survive the trip. One setting, no install — PRD 0004 R1 approached from the resolver side rather than asking people to type a gateway URL. Which namespace owns a contested name (`profullstack.ai` exists in both) is a mode, defaulting to clearnet-wins with the registry as a backfill: a public resolver that silently redirected a domain resolving perfectly well would be indistinguishable from a hijack. `MOSHPIT_RESOLVE_MODE=moshpit` is the override. This is the extension's policy, so switching between them does not change which site you land on. The wire codec is written out rather than pulled from npm: this is the one process strangers can send arbitrary bytes to on UDP/53, and a parser bug there is remotely reachable by anyone. Nothing is installed at all — node built-ins and fetch — which is also why the container needs no dependency step. Open resolvers are reflection amplifiers, so the defences are on by default: a per-client token bucket that drops rather than replies, ANY refused, non-recursive clearnet queries refused, and responses arriving at the listening socket ignored. Failure is one-directional on purpose. A registry outage costs Moshpit names and leaves the web alone; a gateway with no known address answers nothing rather than caching a name as address-less; an upstream that dies is SERVFAIL rather than a hung client. Also: DoH on the same policy for locked-down machines where system DNS is not yours to change, docs/moshpit-dns.md for the records to publish and how to run one, and deploy/ for Docker and systemd. The gateway half is not done and the docs say so: Railway's edge answers "Application not found" for a Moshpit Host, and no Moshpit name can be registered against it. deploy/Caddyfile.gateway is the any-Host ingress to point MOSHPIT_GATEWAY_A at until the hosting grid lands. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
vu1nz Security Review0 finding(s) in PR #? No security issues found. |
ralyodio
marked this pull request as ready for review
July 31, 2026 03:21
This was referenced Jul 31, 2026
ralyodio
added a commit
to moshcoder/moshcode
that referenced
this pull request
Jul 31, 2026
The pit could sell you `scrambled.eggs` and then leave you with no way to open it. Resolvers now exist (moshcoder/moshcoding#77) that answer Moshpit names from this registry and forward everything else to the ordinary internet — this is the page that tells a person how to use one. A tab rather than a link in a paragraph: `/pit` is the namespace and `/pit/dns` is how you reach it, two halves of the same thing, and nobody finds the second one buried in prose. The addresses come from MOSHPIT_DNS_RESOLVERS rather than the source, because they are operational facts that change when a box moves, and a page that keeps telling people to use an address that moved is worse than one that says nothing. Unset — which is today — it says the resolvers are not published yet and explains how to run one. It never invents an address for a stranger to paste into their network settings, and entries that are not addresses are dropped rather than rendered. Also states what does not work: HTTPS on a Moshpit name warns, because no public CA will issue for a namespace outside the ICANN root, and clearnet lookups are forwarded to Google and Cloudflare. Both are reasons to run your own, which the page then tells them how to do. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
ralyodio
added a commit
to moshcoder/moshcode
that referenced
this pull request
Jul 31, 2026
) * feat(pit): a DNS tab, so the namespace is reachable from a machine The pit could sell you `scrambled.eggs` and then leave you with no way to open it. Resolvers now exist (moshcoder/moshcoding#77) that answer Moshpit names from this registry and forward everything else to the ordinary internet — this is the page that tells a person how to use one. A tab rather than a link in a paragraph: `/pit` is the namespace and `/pit/dns` is how you reach it, two halves of the same thing, and nobody finds the second one buried in prose. The addresses come from MOSHPIT_DNS_RESOLVERS rather than the source, because they are operational facts that change when a box moves, and a page that keeps telling people to use an address that moved is worse than one that says nothing. Unset — which is today — it says the resolvers are not published yet and explains how to run one. It never invents an address for a stranger to paste into their network settings, and entries that are not addresses are dropped rather than rendered. Also states what does not work: HTTPS on a Moshpit name warns, because no public CA will issue for a namespace outside the ICANN root, and clearnet lookups are forwarded to Google and Cloudflare. Both are reasons to run your own, which the page then tells them how to do. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * feat(pit): land a typed-in name on the shortest path to holding it `/pit?name=mosh.whatever` is where a resolver or the gateway sends someone whose name did not resolve to a site. They have just demonstrated demand for a name, so the page opens with what they can do about it rather than a 404. Four honest answers, because what can be offered depends on who holds the ending, and today only a TLD's owner may mint names under it: nobody holds `.whatever` -> claim the ending, prefilled; the name and every other one under it comes with it you hold it -> one form, prefilled, registers `mosh.whatever` you already minted it -> it is yours, it is in your list someone else holds it -> say so. `registerName` refuses anyone but the owner and there is no way for them to sell it through the pit yet, so an offer button would be an invitation into a flow that does not exist The decision lives in lib/moshpit-landing.mjs with no database and no request, so the wording is testable and cannot drift from the rule it describes. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
Public DNS resolvers for
*.pit.moshcode.sh, so.moshpitand every other Moshpit TLD resolve without the TronBrowser extension — and.com,.organd the rest of the internet keep working from the same resolver, forwarded to 8.8.8.8 and 1.1.1.1.One setting, nothing to install. PRD
0004R1 from the resolver side instead of asking people to typescrambled.eggs.pit.moshcode.sh.What it answers
scrambled.eggs(registered TLD)www.scrambled.eggsexample.comnobody.zzzzCNAMEto where it points, then the addressContested names —
profullstack.aiexists in both namespaces — are a mode, defaulting to clearnet wins, registry backfills. A public resolver that silently redirected a domain which resolves perfectly well would be indistinguishable from a hijack.MOSHPIT_RESOLVE_MODE=moshpitis the override. Same policy as the extension'smoshpit-resolve.ts, so moving between them does not change which site you land on.Shape
lib/dns/wire.ts— the DNS codec, written out rather than pulled from npm: this is the one process strangers can send arbitrary bytes to on UDP/53. Total decoder, guards on compression loops and short reads.lib/dns/policy.ts— which namespace a query belongs to. Pure, no I/O.lib/dns/registry.ts— reads/api/moshpit/resolveover HTTP, cached and coalesced. Non-authoritative by construction (0004R2), which is also what makes it self-hostable (R8).lib/dns/upstream.ts— staggered failover across upstreams, not a race: racing doubles the traffic and the number of parties who see it to save a few ms.lib/dns/answers.ts,gateway.ts,ratelimit.ts,server.ts,doh.ts; entryscripts/moshpit-dns.ts.fetch.Safety
Open resolvers are reflection amplifiers, and scanners find them within hours. On by default: per-client token bucket that drops rather than replies,
ANYrefused, non-recursive clearnet queries refused, responses arriving at the listening socket ignored.Failure is one-directional on purpose: a registry outage costs Moshpit names and leaves the web alone; a gateway with no known address answers nothing rather than caching a name as address-less; a dead upstream is SERVFAIL, not a hung client.
Verified
116 tests pass (44 new),
tsc --noEmitclean, and it was run against the live registry and gateway:The gateway half is not done, and this says so
Resolution is half of reaching a site. The browser then connects to the gateway with
Host: scrambled.eggs, and today nothing accepts that Host —curl -H 'Host: fuck.yeah' http://<pit address>/gets Railway's{"status":"error","code":404,"message":"Application not found"}, and no Moshpit name can be registered against that service, because the premise is that anyone can invent one.deploy/Caddyfile.gatewayis the any-Host ingress to run alongside a resolver, withMOSHPIT_GATEWAY_Apointed at it; it serves the clearnet preview page (0004R11) until the hosting grid exists to proxy into. The resolver does not change either way — that is why the gateway address is a setting.Also not fixed, and documented: HTTPS on a Moshpit name (no public CA will issue for
scrambled.eggs), and DNSSEC on synthesized answers (no chain from a root the namespace does not descend from). Forwarded clearnet answers keep their signatures.One assumption to confirm
The deployed registry returns fields no branch in this repo has yet (
target,name_registered,prefer). The client readstargetand honours it when DNS can express it — an address becomes A/AAAA, a hostname becomes a CNAME, a URL falls back to the gateway. It deliberately ignores the owner-suppliedprefer: on a public resolver, letting a name owner declare that their lookalike outranks the real domain is the hijack the clearnet-first default exists to prevent. Say the word ifpreferwas meant to bind resolvers.Deploying
docs/moshpit-dns.mdhas the records to publish (dns1.pit/dns2.pitas explicit A records — an exact name beats the*.pitwildcard that serves the gateway), client setup per OS, Docker, systemd, and the operating notes.Not Railway: DNS is UDP. A small VPS with a static address is the entire requirement.
🤖 Generated with Claude Code