Network and egress design#
Egress is network traffic leaving a sandbox. In MAQPNA a sandbox has default-deny egress: the only place it can send traffic is the gateway (plus DNS, and two narrow control-plane ports when the session needs them). Everything the agent wants from the outside world, whether a tool, a model, another agent, a web page or a browser connection, is a governed call through the gateway, which then dials out through a residency-checking, SSRF-guarded transport.
flowchart LR
subgraph NS["Agent namespace (maqpna-agents)"]
subgraph POD["Session pod (NetworkPolicy session-maqpna)"]
A[agent]
R["egress-relay 127.0.0.1:3128"]
B["browser (CDP 127.0.0.1:9222)"]
X["exec :8888"]
end
end
subgraph SYS["maqpna-system"]
GW["gateway :8080"]
IB["identity broker<br/>bootstrap :8083"]
AT["attestation :8082"]
end
DNS["kube-dns :53"]
A -- "MCP, /llm, A2A" --> GW
B --> R -- "CONNECT + Proxy-Authorization" --> GW
A -. "claim mode only" .-> IB
POD -. "attested tiers only" .-> AT
POD --> DNS
GW -- "ingress allowed only from the gateway" --> X
GW == "residency dialer<br/>+ SSRF guard" ==> OUT["MCP servers, models,<br/>A2A peers, web"]
Per-session NetworkPolicy#
The operator creates <session>-maqpna for every session. It selects the session pod by maqpna.com/session=<name> (in warm-pool claim mode by agents.x-k8s.io/claim-uid=<uid>).
| Direction | Tier egress: gateway-only (default) |
Tier egress: deny-all |
|---|---|---|
| Ingress | Only from pods labelled app.kubernetes.io/name: maqpna-gateway in the gateway namespace |
Same |
| Egress: DNS | kube-dns, UDP and TCP 53 | Only when attested or in claim mode |
| Egress: gateway | Gateway pods | None |
| Egress: attestation | maqpna-attest pods, when the session is attested (also for deny-all, for the renewer) |
Same |
| Egress: bootstrap | The identity broker's bootstrap port (8083), in claim mode | Same |
A deny-all session that is neither attested nor claimed has no egress at all.
Chart NetworkPolicies#
templates/networkpolicies.yaml adds policies the operator does not:
maqpna-default-denyin each agent namespace (networkPolicy.agentNamespaces, defaultmaqpna-agents): all pods, no ingress, egress only to kube-system DNS, the gateway port, and, when enabled, the identity bootstrap port and the attestation port. Agent namespaces are created with Pod Securityenforce: baseline(warn and auditrestricted).- Control-plane ingress (
networkPolicy.controlPlane.enabled): the gateway accepts its port only from agent namespaces (labelmaqpna.com/agent-namespace=trueor listed) and from its own namespace; the identity broker's mint port only from its own namespace, its bootstrap port from agent namespaces; the attestation port from agent namespaces; the operator's metrics and health ports. - The example
mcp-echoserver accepts ingress only from the gateway.
Gateway egress: two guards#
| Guard | Used for | What it refuses |
|---|---|---|
Residency dialer (pkg/sovereignty) |
Every upstream: MCP servers, model routes, A2A peers, OIDC and JWKS fetches, notifiers, SIEM, WORM, OpenTelemetry | Any host whose resolved addresses are not all in allowedEgressCIDRs and whose name does not match allowedEgressHosts; cloud metadata and link-local ranges (169.254.0.0/16, fe80::/10, fd00:ec2::254/128) unless a CIDR explicitly allows them. Proxy-from-environment is disabled |
SSRF guard (pkg/webguard) |
Agent-chosen destinations: maqpna-web fetch and search, browser egress |
Loopback, private, CGNAT, link-local, multicast, reserved, documentation and transition ranges; numeric host tricks (0x7f.1, 2130706433); plus the residency check |
Both dialers resolve a name once, check every address, and dial the checked IP literal, so a second DNS answer (DNS rebinding) is never used. In sovereignty audit mode the residency dialer allows and reports violations, but metadata ranges stay blocked.
Agent-chosen destinations#
- Governed web (
maqpna-web). A built-in MCP server in the gateway with toolsfetchandsearch. Domains are checked against allow and deny lists from the gateway, the namespace andAgent.spec.web(strictest wins), then policy runs as for any tool call. Every result taints the session withuntrusted-input(web.taintLabels). - Browser egress. With
Agent.spec.profile: browser, Chromium sends every request through--proxy-server=http://127.0.0.1:3128, theegress-relaysidecar. The relay addsProxy-Authorization: Bearer <session token>(re-read per connection; the browser never sees the token) and forwardsCONNECTand absolute-form requests to the gateway, which acts as a forward proxy whenegress.enabled. The gateway authenticates the token (scopetools:maqpna-egress, kill switch), applies the domain policy withAgent.spec.browser.allowedDomains, evaluatesToolPolicywith servermaqpna-egressand toolconnectorhttp, dials through the SSRF guard and audits the connection. Arequire_approvaldecision is enforced as a denial (approval_required_not_supported_for_egress), because a browser cannot wait. - Code interpreter. The
execsidecar listens on 8888 inside the pod; only the gateway can reach it (NetworkPolicy ingress), atPOST /v1/sessions/{id}/exec. Code, output and files are DLP-scanned.
Ports#
| Component | Port | Purpose |
|---|---|---|
| Gateway | 8080 | Data plane and (without adminListen) admin API, /metrics |
| Identity broker | 8081 | Mint, verify, exchange, JWKS (control plane only) |
| Identity broker | 8083 | /v1/bootstrap for warm-pool pods |
| Attestation service | 8082 | Releases and renewals |
| Example MCP server | 8090 | mcp-echo (dev and smoke tests) |
| Operator | 8080 / 8081 | Metrics / health probes |
| Session pod | 3128, 9222, 6080, 8888 | Egress relay, browser CDP and live view (localhost or gateway only), exec |
What you see#
A domain outside the browser allow-list is refused by the egress proxy, and the agent's browser sees a failed connection; the ledger records it as a deny with server maqpna-egress. A blocked upstream on the model route returns:
{"error":{"message":"…","type":"maqpna_egress_denied","code":"egress_denied","reason":"egress_denied","domain":"maqpna.com"}}
maqpna preflight reports the CNI check, and maqpna doctor checks that every agent namespace has default-deny policies. See maqpna preflight and maqpna doctor.