[draft] mitm-df: NameConstraints-scoped CA + file keystore (foundation)#262
Draft
myleshorton wants to merge 2 commits into
Draft
[draft] mitm-df: NameConstraints-scoped CA + file keystore (foundation)#262myleshorton wants to merge 2 commits into
myleshorton wants to merge 2 commits into
Conversation
Collaborator
|
@myleshorton FYI I already had Claude implement a MITM outbound to replicate what's missing |
Contributor
Author
|
Oh sweet!! Yeah the only interesting thing my planning on this uncovered is the NameConstraints RFC so we can specify a targeted set of domains we can generate certs for. |
First slice of the MITM-DomainFronting outbound from engineering#3482.
Lands the foundational crypto piece — a CA generator whose RFC 5280
NameConstraints extension cryptographically restricts the set of DNS
names it can sign for — before any of the outbound machinery that will
use it.
What's in:
- internal/mitmca/ca.go: CA struct, GenerateCA, LoadCA, SignLeaf, plus
the in-Go pre-check that rejects out-of-subtree SNIs before even
reaching the signer.
- internal/mitmca/keystore.go: KeyStore interface and the default
FileKeyStore implementation (PKCS#8 PEM, mode 0600, atomic rename).
Per-platform hardware-backed implementations (Secure Enclave /
Android StrongBox / TPM) satisfy the same interface and will land in
follow-ups behind build tags.
- internal/mitmca/ca_test.go: table-driven coverage for the constraint
cases that matter — subdomain matching, subtree-suffix lookalikes
("notexample.com", "example.com.evil.com"), unconstrained-CA
rejection on Load, fresh-vs-reloaded sign equivalence, file mode
0o600 (POSIX), Erase idempotence.
- docs/mitm-df/architecture.md: design doc for the whole feature.
Covers component map, package layout, public Go types, the
sing-box outbound config schema, end-to-end request flow, and
the security properties as enforced by this code.
Not yet in (follow-ups):
- internal/mitmdf: the outbound itself (TLS termination, fronts table,
SPKI pinner, audit log, session loop).
- option/mitmdf.go: sing-box config schema for type="mitm-df".
- Hardware-backed keystores: keystore_darwin.go (Secure Enclave),
keystore_android.go (StrongBox), keystore_windows.go (TPM/NCrypt),
keystore_linux.go (TPM via PKCS#11 if available; fall back to file).
- Flutter UI: opt-in toggle, per-platform CA-install flow, audit-log
viewer.
- Cross-repo: config-server push channel for fronts updates, weekly
validation CI in lantern-cloud, kill-switch flag.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1bd646c to
8b6083d
Compare
Collaborator
|
Part of the |
5 tasks
PR #263 (mitmfront-outbound) lands the actual outbound under protocol/mitmdf/ rather than internal/mitmdf/ — sibling to the existing protocol/ transports (algeneva, lanturn, samizdat, unbounded, water). Update the architecture doc to match: - Component diagram: MITM box now labeled protocol/mitmdf - Package layout block: mitmdf/ moves out from under internal/ to protocol/, with a one-line note explaining why mitmca stays under internal/ (private helper, consumed only by mitmdf) - Implementation-order list: the three mitmdf paths now reference protocol/mitmdf/... - Drop session.go from the layout (its responsibilities fold into outbound.go's serve goroutine — matches what #263 actually shipped) - Add utls_preset.go to the layout with a note about the HelloCustom + ApplyPreset ALPN-inheritance detail that PR #263 caught - Add test/e2e/mitmdf_test.go to the layout (#263 ships it; the previous draft of this doc deferred it) No code changes; doc-only. Co-Authored-By: Claude Opus 4.7 (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.
Draft — first slice of engineering#3482 (MITM-DomainFronting outbound for lantern-box). Posting early as a marker; not for review yet.
What's here
The foundational crypto piece — a CA generator whose RFC 5280
NameConstraintsextension cryptographically restricts the DNS names it can sign for. This lands first, before any of the outbound machinery that uses it, because the security model rests on it and the package is independent enough to review in isolation.Not yet here (follow-ups, in rough order)
Why `NameConstraints`
The user installs a personal root CA. If unconstrained, it can sign certs for any domain — banks, government, healthcare, anything. `NameConstraints` cryptographically restricts the CA to a fixed list of DNS subtrees. On any verifier that enforces it (Chrome, Firefox, Android API 30+, iOS 13+, modern Safari/Windows), the CA is incapable of producing a fraudulent cert for any domain outside that list — even if the private key is exfiltrated. That converts the threat model from "unbounded MITM authority" to "scoped MITM authority for ~10 named CDN families."
See engineering#3482 (security comment) for the full threat-model walk and the explanation of why on-the-wire SNI byte-swap doesn't work (TLS transcript HMAC binding).
Test plan
🤖 Generated with Claude Code