Skip to content

Commit 3f71414

Browse files
bbonabyCopilot
andauthored
add process container networking GA spec (#616)
* docs(process-container): add process container networking GA spec Add docs/process-container/networking.md, the Windows processcontainer implementation companion to the shared network configuration doc at docs/sandbox-policy/v2/networking.md: the two enforcement primitives, the three connectivity models with example configs, the current (in-OS) vs downlevel (Windows 23H2) enforcement paths, and WFP as the enforcement primitive. Converted from the reviewed design doc; external agent-runtime references and internal-only provenance are omitted. * docs(process-container): use jsonc fences for commented examples The three network config examples contain // comments, so label them as jsonc rather than json so readers can copy/paste without confusion. Addresses Copilot review feedback on PR #616. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 74ea4d7 commit 3f71414

1 file changed

Lines changed: 117 additions & 0 deletions

File tree

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
# Process Container Networking Configuration, GA
2+
3+
Implementation companion to the parent [MXC Network Configuration, GA](../sandbox-policy/v2/networking.md) doc, which owns the shared policy schema, the three connectivity models, and the GA goal (model 2, deny-all-except-proxy). This doc covers only how the Windows processcontainer backend enforces those models.
4+
5+
## 1. What this backend delivers at GA
6+
7+
Each sandbox gets two enforcement primitives, scoped to its container SID and applied with no UAC prompt per launch:
8+
9+
- **WFP outbound filters:** block all outbound traffic by default, then allow or block specific destinations by IP address or range, protocol, and port (a single port or a range), for both IPv4 and IPv6. An explicit block always wins over an allow, so a deny is expected to fall inside the allow it narrows; an allow and a deny matching the exact same destination, protocol, and port is rejected as an invalid policy. The rules apply only to this sandbox.
10+
- **Per-container WinHTTP HTTP/S proxy:** points WinHTTP-stack clients (e.g., the WinHTTP/Chromium stack) at a caller-provided loopback proxy container. MXC also sets the proxy env vars (`HTTP_PROXY` / `HTTPS_PROXY` / `NO_PROXY`, plus lowercase versions) to the same loopback endpoint. Runtimes that read those variables rather than WinHTTP (Node tooling, Python `requests` / `pip`, Go `net/http`, `curl`, `git`) route through the proxy using this mechanism. These variables are a compatibility layer for well-behaved clients, not the containment boundary. All traffic not destined for the proxy loopback will be dropped.
11+
12+
Each model is a specific combination of container network capabilities and enforcement. Example configs use the parent doc's proposed network schema + additional runtime.
13+
14+
### Model 1: direct egress, WFP-filtered (least restrictive)
15+
16+
- **Capabilities:** internetClient, plus a loopback exemption for same-container connections; no other network capability.
17+
- **Enforcement:** WFP allow/block rules; no proxy.
18+
19+
```jsonc
20+
{
21+
"network": {
22+
"egress": {
23+
"mode": "direct",
24+
"default": "deny",
25+
"allow": [
26+
{ "to": [ { "cidr": "140.82.112.0/20" } ],
27+
"ports": [ { "protocol": "tcp", "port": 443 } ] }
28+
]
29+
},
30+
"ingress": { "hostLoopback": "deny" }
31+
// direct egress, filtered by WFP
32+
}
33+
}
34+
```
35+
36+
### Model 2: proxy-only egress (recommended)
37+
38+
- **Capabilities:** no AppContainer networking capabilities. A loopback exemption for inter-container (to the proxy container) and intra-container communication.
39+
- **Enforcement:** The per-container WinHTTP proxy. With no internetClient, the only reachable egress is the loopback proxy; the system drops everything else. MXC resolves the proxy container's SID at launch to scope the loopback exemption.
40+
41+
```jsonc
42+
{
43+
"network": {
44+
"ingress": { "hostLoopback": "deny" }
45+
},
46+
"runtimeConfig": { // MXC runtime metadata (not policy)
47+
"networkProxy": "http://127.0.0.1:8080"
48+
},
49+
"processcontainer": {
50+
"network": {
51+
"allowedPeers": [
52+
"agent-proxy" // AppContainer SID derived at runtime, needed for loopback rules addition
53+
]
54+
}
55+
}
56+
}
57+
```
58+
59+
The proxy endpoint (e.g., 127.0.0.1:8080) is a config parameter for the process container backend and not part of the overall MXC network policy. MXC resolves the proxy container's SID at launch to scope the loopback exemption. In proxy mode there is no direct egress plane, so default, allow, and deny do not apply. MXC will not spin up the proxy for the caller. It is the caller's responsibility to spin up their own proxy inside an AppContainer, and provide MXC with the friendly name of the AppContainer that aligns with the [CreateAppContainerProfile function (userenv.h)](https://learn.microsoft.com/windows/win32/api/userenv/nf-userenv-createappcontainerprofile).
60+
61+
### Model 3: fully blocked (most restrictive)
62+
63+
- **Capabilities:** none; no loopback exemptions.
64+
- **Enforcement:** no proxy; all outbound and inbound dropped.
65+
66+
Since deny-all is the default, model 3 is also the result of providing no network policy at all: the explicit form, an omitted network block, and an empty `"network": {}` are equivalent:
67+
68+
```jsonc
69+
// explicit (canonical blocked: direct egress, default deny, no allow rules)
70+
{
71+
"network": {
72+
"egress": { "mode": "direct", "default": "deny" }, // no allow rules
73+
"ingress": { "hostLoopback": "deny" }
74+
}
75+
}
76+
77+
// or
78+
{ /* no "network" key at all */ }
79+
80+
// or
81+
{ "network": {} }
82+
```
83+
84+
### 1.1 Out of GA scope for this backend
85+
86+
Do not infer otherwise from the schema:
87+
88+
- Transparent TCP/UDP redirection through the proxy. GA proxying is WinHTTP HTTP/S only.
89+
- L7 classification (e.g., HTTPS vs SSH on :443).
90+
- Durable DNS-name rules.
91+
- Encrypted-payload inspection.
92+
- Inbound/listening policy.
93+
94+
See the parent doc on the last 4.
95+
96+
## 2. Two enforcement paths: current vs downlevel
97+
98+
Both (a) WFP filter writes and (b) per-container WinHTTP proxy configuration require a privileged context. How that privilege is obtained is the entire implementation story for this backend, and it splits by Windows build:
99+
100+
| Tier 1: the OS applies the policy in-process | Tier 2: downlevel (Windows 23H2) |
101+
|---|---|
102+
| On builds that expose the OS sandbox-creation API (`CreateProcessInSandbox`), the OS itself, in its own elevated context, applies the per-sandbox WFP filters and wires the WinHTTP proxy before the target process runs.<br><br>No MXC-side privileged component, no UAC. The filter lifetime is owned by the OS and bound to AppContainer. This is the preferred path and where new capabilities land first. | On builds without that API (Windows 23H2), only model 1 (direct egress, WFP-filtered) is supported. MXC applies the per-sandbox WFP filters by elevating on each launch to write them.<br><br>There is no per-container WinHTTP proxy support on 23H2, so model 2 (proxy-only egress) is available only on builds that expose `CreateProcessInSandbox`. |
103+
104+
### 2.1 Fail loud on version skew: never silently downgrade
105+
106+
`CreateProcessInSandbox` could be different between builds as the network-policy surface grows over time. A machine can expose the API but not yet honor a specific policy field MXC asks for. MXC must not silently fall back to Tier 2 in that case: the two paths have different security and cleanup properties, and the operator would not know. The contract:
107+
108+
- Fall back to Tier 2 only when the API is absent on the build, not when it is present but missing a requested field.
109+
- For a present-but-incomplete API, MXC rejects the launch with a typed error naming the missing capability.
110+
111+
## 3. WFP is the enforcement primitive (both tiers)
112+
113+
AppContainers today have 3 network capabilities: internetClient, internetClientServer, and privateNetworkClientServer. For GA we only ever use the internetClient capability, which basically acts as an on or off switch for outbound internet connectivity. Beyond that, the outbound policy is enforced with the Windows Filtering Platform (WFP), the OS's built-in network-filtering engine. When the sandbox tries to open an outbound connection, the kernel will check MXC's filters and allow or block it. Each filter is scoped to the sandbox's container SID, so it applies only to that one sandbox and to nothing else on the machine.
114+
115+
**Admin requirement.** Adding WFP filters is admin-only. On Tier 1 the OS applies them in its own elevated context; on Tier 2 (Windows 23H2) MXC elevates on each launch to write the filters.
116+
117+
**Cleanup.** Filters will need to have a lifetime ≤ sandbox lifetime. In both tiers the filters will need to be cleaned up when there are no more processes running in the container.

0 commit comments

Comments
 (0)