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. A host is reached on 443 and 80 unless a rule names host:port (port_policy).
  • 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 except, with Tls set, a tunnel to the host of a secret that says tls: terminate (ADR-043): its one request is checked against the leak check and the secret’s allow rules, given the value, sent over the proxy’s own verified TLS, and its answer searched for every value.
  • 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, ADR-044) every request must carry its session’s credential: one the proxy holds (Credential) or one a Verify accepts. 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.
CaFiles
A new CA, as the files openmoat proxy ca init writes. The key is zeroed when dropped and left out of Debug.
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).
Tls
One proxy run’s termination: the CA’s signer, the leaves made from it and the configuration upstream connections use.

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.
Roots
What upstream certificates are verified against.
Target
What the client asked the proxy to reach.
TlsError
Why a CA cannot be made or used, or a terminated connection set up.

Constants§

CA_VALID_DAYS
How long a CA new_ca makes is valid, in days.
DEFAULT_PORTS
The ports a host pattern without a port allows: HTTPS and HTTP.
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_CAPACITY
Rule id for a connection refused at accept because the proxy, or the connections not yet authenticated, hold all the slots they may.
RULE_PORT
Rule id for a host the policy allows, refused on a port no rule names.
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_SECRET_ROUTE
Rule id for a request to a secret’s host that the secret’s allow rules do not name: it would have received the value, so it is not sent.
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_TLS
Rule id of a terminated tunnel refused for its TLS: a handshake that failed on either side, or an upstream certificate that did not verify.
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.
Verify
Checks credentials the proxy does not hold: those the standalone proxy’s sessions were issued after it started (ADR-044). The CLI implements it.

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, IPv4-translated, 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_named_on
Whether addresses allows addr’s address: named, or, for IPv4, an allow rule that names it with this port (10.0.0.5:5432).
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. Exclusions are all kept, and one without a port excludes the address on every port.
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, alone or with port. 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. The port is not looked at here: host_port decides both.
decide_host_port
Decide whether host, normalised as Request::host reports it, may be reached on port. ports is compiled from port_policy of policy’s policy. 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).
new_ca
Make a CA that may sign for hosts (and names under them) alone, valid from yesterday for a year.
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.
port_policy
The part of policy that decides a host and its port, as host_port uses it: every deny and repository ask rule as written, and the allow rules’ host:port patterns only, so that a pattern without a port (*, example.com) never opens another port. Every exclusion without a port (!evil.example.com) also excludes the host on every port. Anything else is left to the caller (defer).
server_name
Read the SNI from the TLS records at the start of buf.