openmoat_proxy/lib.rs
1//! `openmoat-proxy`: the default-deny egress proxy behind `moat proxy` (ADR-020).
2//!
3//! It serves HTTP `CONNECT` tunnels and absolute-form plain-HTTP requests on a
4//! loopback port:
5//!
6//! - Hosts are decided by openmoat-core's [`CompiledPolicy`](openmoat_core::CompiledPolicy)
7//! as `moat guard` decides a fetch tool's URL: only an `allow` passes.
8//! - Cloud metadata and link-local addresses are refused whatever the policy
9//! says, by name and on every address the proxy resolves. Private and CGNAT
10//! addresses are refused unless an allow rule names the address.
11//! - A tunnel's TLS `ClientHello` must name the CONNECT host (SNI); nothing is
12//! decrypted.
13//! - A request that carries a brokered secret's placeholder or value to a host
14//! other than the secret's own is refused ([`Broker`]).
15//! - Every decision is recorded through a [`Recorder`]; a failed record is a
16//! refused connection.
17//! - In session mode ([`Sessions`], ADR-027) every request must carry its
18//! session's credential. The session's audit id goes on each row, a
19//! session that read secret material reaches only that secret's host, and
20//! no session holds more than half the connections.
21//! - A connection that starts with a [`LocalService`]'s prefix goes to that
22//! service of the proxy's own process (ADR-028), not upstream.
23//!
24//! Plain `std::net` and one thread per connection, capped by [`Limits`]; the
25//! choice is explained in `docs/ARCHITECTURE.md` ยง12.
26
27#![warn(missing_docs)]
28// A library reports to its caller; only the `moat` binary prints.
29#![warn(clippy::print_stdout, clippy::print_stderr)]
30
31mod audit;
32mod body;
33mod broker;
34mod decide;
35mod local;
36mod request;
37mod server;
38mod session;
39mod slots;
40mod sni;
41mod tunnel;
42mod upstream;
43
44pub use audit::{Connection, RecordError, Recorder};
45pub use broker::{Broker, BrokerError, Carried, Leak, RULE_SECRET};
46pub use decide::{
47 Forbidden, RULE_ADDRESS, RULE_AUDIT, RULE_REQUEST, RULE_SNI, RULE_UPSTREAM, address_policy,
48 denied as address_denied, forbidden, host as decide_host, named as address_named,
49 tainted as decide_tainted,
50};
51pub use local::LocalService;
52pub use request::{
53 MAX_HEADERS, ProxyCredential, Request, RequestError, Target, parse as parse_request,
54};
55pub use server::{Limits, Proxy};
56pub use session::{
57 AuthError, Credential, CredentialError, MIN_TOKEN_LEN, RULE_SESSION, Sessions, TaintLookup,
58 constant_time_eq,
59};
60pub use sni::{Hello, HelloError, MAX_HELLO, server_name};
61pub use upstream::{Refusal, Resolve, SystemResolver, connect};