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.
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.
- 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.
- Record
Error - A decision could not be recorded.
- Request
- A parsed request head.
- System
Resolver - The operating system’s resolver (
getaddrinfoand its equivalents).
Enums§
- Broker
Error - A secret value the broker cannot use.
- Carried
- Which form of a secret a request carried.
- 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. - 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_
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§
- Recorder
- Where connection decisions go. An error refuses the connection.
- Resolve
- Name resolution, injectable so tests can map names without a DNS server.
Functions§
- 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 can open aForbidden::Privateaddress: 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. Everything else is 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, then connect to the first address that answers. A private address passes only whenaddresses(compiled fromdecide::address_policy) names it.loopback_oklists loopback addresses that may be reached anyway (tests); nothing exempts link-local or metadata. - decide_
host - Decide whether
host, normalised asRequest::hostreports it, may be reached. Only anallowlets the connection proceed. - 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.