Saphan StudioDocs
Security/Egress control

What no policy can open

The address floor every connection is checked against, and the checks applied to each connection after the policy admits it.

A policy says what a run may reach. Underneath it sits a floor that no policy, and no setting short of --egress-open, can lift.

The address floor

A connection is refused if its destination address — after the name is resolved — falls in any of these ranges:

rangewhat it is
169.254.0.0/16, fe80::/10link-local, including the cloud metadata endpoint 169.254.169.254
127.0.0.0/8, ::1loopback
0.0.0.0/8, ::/128, ::/96unspecified and reserved
100.64.0.0/10carrier-grade NAT
192.0.0.0/24, 198.18.0.0/15IETF protocol assignments and benchmarking
224.0.0.0/4, ff00::/8multicast
240.0.0.0/4, fec0::/10reserved
::ffff:0:0:0/96, 64:ff9b::/96, 64:ff9b:1::/48, 2001::/32, 2002::/16IPv4-translated, NAT64, Teredo and 6to4 — other spellings that could reach the addresses above. An IPv4-mapped address (::ffff:a.b.c.d) is judged as the IPv4 address it carries
any IPv6 address outside 2000::/3, and any address with a zonenot a global unicast destination
10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, fc00::/7private networks — closed unless you opt in, see Policies

The floor is checked twice: when the policy loads, so a document that names a floored range is refused outright, and again on the address the name actually resolved to, so a public name that resolves to a private address is still refused.

The checks on every connection

A connection is judged in this order, and the first failure ends it:

  1. Normalise the destination name.
  2. Literal addresses. A connection to a bare IP address is refused unless the policy lists that address under literals. This closes the bypass of dialling the address behind an allowed name.
  3. Policy. The host and the port must match an allow rule.
  4. Resolve once. The name is resolved one time, and that answer is the address used — it cannot change between the check and the connection.
  5. Floor. The resolved address must not be on the floor above.
  6. Self. The door's own socket is never a destination.

TLS and HTTP

  • TLS. The host name the client sends in its TLS handshake (SNI) must equal the name that was approved. A missing or different name is refused as egress-sni-mismatch. A destination approved as a literal address skips this check.
  • Plain HTTP. The Host the request names must match the approved destination, or the request is refused as egress-destination-not-allowed; an ambiguous one is refused as egress-protocol-error. A destination approved as a literal address skips this check too.

Connection ceilings

Every policy carries seven ceilings, all required. The baselines use these values:

ceilingbaseline valuewhat it bounds
preface_bytes16384the start of the encrypted stream read before the TLS host name is known
request_bytes8192the proxy request: the CONNECT line and headers, or the SOCKS5 greeting and request
header_count64headers in the proxy request
line_bytes8192the length of one header line
handshake_deadline20sthe time to complete the handshake
idle_deadline300show long a connection may sit idle
total_transfer536870912 (512 MiB)bytes moved over one connection

A connection that exceeds one is closed and refused as egress-limit-preface-bytes, egress-limit-header-count, egress-limit-line-length (for request_bytes and line_bytes), egress-limit-handshake-deadline, egress-limit-idle-deadline or egress-limit-total-transfer.

What the agent sees

lanea refused connection looks like
the network wall (Linux, containers)a name the policy does not list does not resolve; a port it does not name gets a reset; a destination the door refuses closes — an EOF or a reset, with no HTTP status
the CONNECT door (macOS)403 Forbidden from the proxy

A refused connection looks exactly like a network that does not work. If a toolchain fails to fetch, check which policy the run got first — see When something is refused.

On this page