Skip to main content

Crate openmoat_proxy

Crate openmoat_proxy 

Source
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 CompiledPolicy as moat guard decides a fetch tool’s URL: only an allow passes.
  • 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 ClientHello must 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::default holds 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.
ProxyCredential
One Proxy-Authorization value (ADR-027): zeroed when dropped, never printed, and never part of the head forwarded upstream.
RecordError
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.
SystemResolver
The operating system’s resolver (getaddrinfo and its equivalents).

Enums§

AuthError
Why a request’s credential is refused. The reply does not say whether the session id or the token was wrong.
BrokerError
A secret value the broker cannot use.
Carried
Which form of a secret a request carried.
CredentialError
Why a Credential cannot be made.
Forbidden
The classes of address the proxy refuses.
Hello
What the start of a tunnel says about the server it wants.
HelloError
Why the start of a tunnel is not a ClientHello the proxy can check.
Refusal
Why no connection was made.
RequestError
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 ClientHello handshake 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 Credential accepts, 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§

LocalService
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.
TaintLookup
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 from address_policy) that match ip, 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 gives None.
address_named
Whether addresses (compiled from address_policy) allows ip, matched in its canonical text form (::ffff:10.0.0.5 as 10.0.0.5).
address_policy
The part of policy that decides a resolved address: its deny rules, and the allow rules’ net and fetch patterns 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 a Forbidden::Private address (named) nor refuses one (denied), so a wildcard such as * or *.example, or a name such as db.internal:5432, never reaches the local network by DNS.
connect
Resolve host, refuse if any address is forbidden or matched by a deny rule of addresses (compiled from decide::address_policy), then connect to the first address that answers. A private address passes only when addresses names it. loopback_ok lists loopback addresses that may be reached anyway (tests); nothing exempts link-local or metadata.
constant_time_eq
Whether a and b are equal, in time that depends only on their lengths.
decide_host
Decide whether host, normalised as Request::host reports it, may be reached. Only an allow lets the connection proceed.
decide_tainted
The refusal for a request to host:port from a session with taint, 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.