Expand description
openmoat-proxy: the default-deny egress proxy behind moat proxy (ADR-020).
It serves HTTP CONNECT tunnels and absolute-form plain-HTTP requests on a
loopback port:
- Hosts are decided by openmoat-core’s
CompiledPolicyasmoat guarddecides a fetch tool’s URL: only anallowpasses. - Cloud metadata and link-local addresses are refused whatever the policy says, by name and on every address the proxy resolves. Private and CGNAT addresses are refused unless an allow rule names the address.
- A tunnel’s TLS
ClientHellomust name the CONNECT host (SNI); nothing is decrypted. - A request that carries a brokered secret’s placeholder or value to a host
other than the secret’s own is refused (
Broker). - Every decision is recorded through a
Recorder; a failed record is a refused connection. - In session mode (
Sessions, ADR-027) every request must carry its session’s credential. The session’s audit id goes on each row, a session that read secret material reaches only that secret’s host, and no session holds more than half the connections. - A connection that starts with a
LocalService’s prefix goes to that service of the proxy’s own process (ADR-028), not upstream.
Plain std::net and one thread per connection, capped by Limits; the
choice is explained in docs/ARCHITECTURE.md §12.
Structs§
- Broker
- The brokered secrets of one proxy run.
Broker::defaultholds none. - Connection
- One connection decision.
- Credential
- One session’s credential: its audit session id and its token.
- Leak
- A brokered secret found in a request to another host.
- Limits
- Bounds on what one client can make the proxy hold.
- Proxy
- The proxy: a policy, a resolver, an audit sink and limits.
- Proxy
Credential - One
Proxy-Authorizationvalue (ADR-027): zeroed when dropped, never printed, and never part of the head forwarded upstream. - Record
Error - A decision could not be recorded.
- Request
- A parsed request head.
- Sessions
- Session mode: the credentials the proxy accepts and where their taint is read.
- System
Resolver - The operating system’s resolver (
getaddrinfoand its equivalents).
Enums§
- Auth
Error - Why a request’s credential is refused. The reply does not say whether the session id or the token was wrong.
- Broker
Error - A secret value the broker cannot use.
- Carried
- Which form of a secret a request carried.
- Credential
Error - Why a
Credentialcannot be made. - Forbidden
- The classes of address the proxy refuses.
- Hello
- What the start of a tunnel says about the server it wants.
- Hello
Error - Why the start of a tunnel is not a
ClientHellothe proxy can check. - Refusal
- Why no connection was made.
- Request
Error - Why a request head is refused.
- Target
- What the client asked the proxy to reach.
Constants§
- MAX_
HEADERS - Most headers one request head may carry.
- MAX_
HELLO - Largest
ClientHellohandshake message accepted. Real ones are 0.5–2 KiB, more with post-quantum key shares; 64 KiB leaves room without letting a client make the proxy buffer without bound. - MIN_
TOKEN_ LEN - Shortest token a
Credentialaccepts, in characters. - RULE_
ADDRESS - Rule id for a destination refused whatever the policy says.
- RULE_
AUDIT - Rule id for a connection refused because it could not be recorded.
- RULE_
REQUEST - Rule id for a request the proxy could not parse or does not serve.
- RULE_
SECRET - Rule id for a request refused because it carries a brokered secret to a host that is not the secret’s own.
- RULE_
SESSION - Rule id for a request refused for its session: no valid credential, the session’s connection share used up, or its history unreadable.
- RULE_
SNI - Rule id for a tunnel whose TLS SNI is missing or names another host.
- RULE_
UPSTREAM - Rule id for a destination that could not be resolved or reached.
Traits§
- Local
Service - A service that shares the proxy’s port.
- Recorder
- Where connection decisions go. An error refuses the connection.
- Resolve
- Name resolution, injectable so tests can map names without a DNS server.
- Taint
Lookup - What a session was exposed to, read when one of its requests is decided. The CLI reads it from the audit log; tests pass a fixed map.
Functions§
- address_
denied - The deny rules of
addresses(compiled fromaddress_policy) that matchip, if any: a deny naming an address holds for every name that resolves to it. Matched in canonical text form, and for a NAT64, IPv4-compatible, 6to4 or Teredo address also as the IPv4 addresses it reaches. Allow rules never widen anything here; an address no deny rule matches givesNone. - address_
named - Whether
addresses(compiled fromaddress_policy) allowsip, matched in its canonical text form (::ffff:10.0.0.5as10.0.0.5). - address_
policy - The part of
policythat decides a resolved address: its deny rules, and the allow rules’netandfetchpatterns that name an address: a pattern starting with a digit or containing:, not starting with a glob metacharacter, and made only of what an address’s text and a glob use. Anything else is left undecided (ask), which neither opens aForbidden::Privateaddress (named) nor refuses one (denied), so a wildcard such as*or*.example, or a name such asdb.internal:5432, never reaches the local network by DNS. - connect
- Resolve
host, refuse if any address is forbidden or matched by a deny rule ofaddresses(compiled fromdecide::address_policy), then connect to the first address that answers. A private address passes only whenaddressesnames it.loopback_oklists loopback addresses that may be reached anyway (tests); nothing exempts link-local or metadata. - constant_
time_ eq - Whether
aandbare equal, in time that depends only on their lengths. - decide_
host - Decide whether
host, normalised asRequest::hostreports it, may be reached. Only anallowlets the connection proceed. - decide_
tainted - The refusal for a request to
host:portfrom a session withtaint, if any (ADR-027). The core’s taint rules decide (POLICY.md §4.1): after the session read secret material, network to every host but that secret’s own asks. The proxy cannot ask, so that ask is refused. Untrusted content alone changes nothing here: its taint protects writes. - forbidden
- Why the proxy never connects to
ip, if it does not. Checked on every resolved address, so a name the policy allows cannot be pointed at a local or metadata service (DNS rebinding). - parse_
request - Parse one request head from the start of
buf.Ok(None)means the head is not complete yet; the caller bounds how much it reads. - server_
name - Read the SNI from the TLS records at the start of
buf.