You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
refactor(server): remove allows_loopback_endpoints from ComputeRuntime
SSRF protection is now handled at the network and proxy layers
(openshell-core net.rs, openshell-sandbox proxy.rs) rather than
requiring per-driver flags on ComputeRuntime. Update architecture
docs to reflect supervisor relay SSH transport and add rootless
networking deep-dive.
Signed-off-by: Adam Miller <admiller@redhat.com>
-**Bridge network**: Created by `client.ensure_network()` with DNS enabled. Containers on the bridge can see each other at L3, but sandbox processes cannot because they are isolated inside the nested netns.
137
137
-**Nested netns**: The supervisor creates a private `NetworkNamespace` with a veth pair (10.200.0.1/24 <-> 10.200.0.2/24). Sandbox processes enter this netns via `setns(fd, CLONE_NEWNET)` in the `pre_exec` hook, forcing all traffic through the CONNECT proxy.
138
-
-**Port publishing**: SSH uses `host_port: 0` (ephemeral port assignment). The gateway reads the assigned port from `podman inspect` and connects via `127.0.0.1:<host_port>`.
138
+
-**Port publishing**: SSH uses `host_port: 0` (ephemeral port assignment) for health checks and debug access. The gateway SSH tunnel uses the supervisor relay (`supervisor_sessions.open_relay()`) rather than connecting directly to the published port.
139
139
-**Host gateway**: `host.containers.internal:host-gateway` in `/etc/hosts` allows containers to reach the gateway server on the host.
140
140
-**nsenter**: The supervisor uses `nsenter --net=` instead of `ip netns exec` for namespace operations, avoiding the sysfs remount that fails in rootless containers.
141
141
@@ -158,7 +158,7 @@ The SSH handshake secret is injected via Podman's `secret_env` API rather than a
| Supervisor relay socket path (`OPENSHELL_SSH_SOCKET_PATH`) | Plaintext env var, override-protected (same value as `PodmanComputeConfig::sandbox_ssh_socket_path`) | Yes | Yes |
160
160
161
-
The `build_env()` function in `container.rs` inserts user-supplied variables first, then unconditionally overwrites security-critical variables (`OPENSHELL_ENDPOINT`, `OPENSHELL_SANDBOX_ID`, `OPENSHELL_SSH_SOCKET_PATH`, `OPENSHELL_SANDBOX`, etc.) to prevent spoofing via sandbox templates.
161
+
The `build_env()` function in `container.rs` inserts user-supplied variables first, then unconditionally overwrites all security-critical variables to prevent spoofing via sandbox templates: `OPENSHELL_SANDBOX`, `OPENSHELL_SANDBOX_ID`, `OPENSHELL_ENDPOINT`, `OPENSHELL_SSH_SOCKET_PATH`, `OPENSHELL_SSH_LISTEN_ADDR`, `OPENSHELL_SSH_HANDSHAKE_SKEW_SECS`, `OPENSHELL_CONTAINER_IMAGE`, `OPENSHELL_SANDBOX_COMMAND`.
162
162
163
163
The `PodmanComputeConfig::Debug` impl redacts the handshake secret as `[REDACTED]`.
164
164
@@ -174,7 +174,7 @@ sequenceDiagram
174
174
175
175
GW->>D: create_sandbox(DriverSandbox)
176
176
D->>D: validate name + id
177
-
D->>D: validate_container_name()
177
+
D->>D: validated_container_name()
178
178
179
179
D->>P: pull_image(supervisor, "missing")
180
180
D->>P: pull_image(sandbox_image, policy)
@@ -226,7 +226,7 @@ If the container is already gone during inspect or remove, the driver still perf
226
226
|`OPENSHELL_SSH_HANDSHAKE_SECRET`|`--ssh-handshake-secret`| (required) | Shared secret for NSSH1 handshake |
227
227
|`OPENSHELL_SANDBOX_SSH_SOCKET_PATH`|`--sandbox-ssh-socket-path`|`/run/openshell/ssh.sock`| Standalone driver only: supervisor Unix socket path in `PodmanComputeConfig` (in-gateway Podman uses server `config.sandbox_ssh_socket_path`) |
228
228
|`OPENSHELL_STOP_TIMEOUT`|`--stop-timeout`|`10`| Container stop timeout in seconds (SIGTERM -> SIGKILL) |
229
-
|`OPENSHELL_SUPERVISOR_IMAGE`|`--supervisor-image`|`openshell/supervisor:latest`| OCI image containing the supervisor binary |
@@ -236,15 +236,15 @@ The Podman driver is designed for rootless operation. The following adaptations
236
236
237
237
2.**cgroups v2 requirement**: The driver refuses to start if cgroups v1 is detected. Rootless Podman requires the unified cgroup hierarchy.
238
238
239
-
3.**nsenter for namespace operations**: `run_ip_netns()` and `run_iptables_netns()` in the sandbox's `netns.rs` use `nsenter --net=` instead of `ip netns exec` to avoid the sysfs remount that requires real `CAP_SYS_ADMIN` in the host user namespace.
239
+
3.**nsenter for namespace operations**: `run_ip_netns()` and `run_iptables_netns()` in `crates/openshell-sandbox/src/sandbox/linux/netns.rs` use `nsenter --net=` instead of `ip netns exec` to avoid the sysfs remount that requires real `CAP_SYS_ADMIN` in the host user namespace.
240
240
241
241
4.**DAC_READ_SEARCH capability**: Required for the proxy to read `/proc/<pid>/fd/` across UIDs within the user namespace.
242
242
243
243
5.**SETUID/SETGID capabilities**: Required for `drop_privileges()` to call `setuid()`/`setgid()` after `cap_drop: ALL` removes them from the bounding set.
244
244
245
245
6.**host.containers.internal**: Used instead of Docker's `host.docker.internal` for container-to-host communication. Injected via `hostadd` with Podman's `host-gateway` magic value.
246
246
247
-
7.**Ephemeral port publishing**: SSH port uses `host_port: 0` because the bridge network IP (10.89.x.x) is not routable from the host in rootless mode. The gateway reads the assigned host port from `podman inspect`.
247
+
7.**Ephemeral port publishing**: SSH port uses `host_port: 0` because the bridge network IP (10.89.x.x) is not routable from the host in rootless mode. The published port is used for health checks and debug access; the gateway SSH tunnel uses the supervisor relay.
248
248
249
249
8.**tmpfs at `/run/netns`**: A private tmpfs is mounted so the supervisor can create named network namespaces via `ip netns add`, which requires `/run/netns` to exist and be writable.
250
250
@@ -253,7 +253,7 @@ The Podman driver is designed for rootless operation. The following adaptations
253
253
- Gateway integration: `crates/openshell-server/src/compute/mod.rs` (`new_podman` and `PodmanComputeDriver` wiring)
254
254
- Server configuration: `crates/openshell-server/src/lib.rs` (`ComputeDriverKind::Podman` — builds `PodmanComputeConfig` including `sandbox_ssh_socket_path` from gateway `Config`)
255
255
- Gateway relay path: `openshell-core``Config::sandbox_ssh_socket_path` in `crates/openshell-core/src/config.rs`
0 commit comments