[PR #435] [CLOSED] feat(proxy): tunnel sandbox TCP connections through the gateway #436

Closed
opened 2026-10-29 14:23:23 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/kvcache-ai/AgentENV/pull/435
Author: @guozy18
Created: 10/25/2026
Status: ❌ Closed

Base: main ← Head: sync/sandbox-http-connect


📝 Commits (3)

  • 6794f40 feat: support HTTP CONNECT tunneling to sandboxes in proxy
  • bdc1db0 feat: relay HTTP CONNECT data-plane tunnels through the gateway
  • 8935236 feat: route gateway CONNECT requests via authority-aware host route

📊 Changes

9 files changed (+1216 additions, -8 deletions)

View changed files

📝 docs/src/internals/proxy-design.md (+49 -1)
📝 services/README.md (+15 -1)
➕ services/gateway/internal/connect.go (+297 -0)
➕ services/gateway/internal/connect_test.go (+440 -0)
📝 services/gateway/internal/host_route.go (+40 -0)
📝 services/gateway/internal/host_route_test.go (+90 -0)
📝 services/gateway/internal/metrics.go (+13 -1)
📝 services/gateway/internal/server.go (+8 -3)
📝 src/api/proxy.rs (+264 -2)

📄 Description

What

Support raw TCP access to sandbox ports with HTTP/1.1 CONNECT, directly through a node or through the gateway. Clients can select a sandbox with the existing routing headers or the configured {port}-{sandboxID}.{domain} authority.

Why

The sandbox proxy currently handles HTTP and WebSocket traffic but cannot establish a TCP tunnel. A gateway also cannot relay a successful CONNECT with its ordinary ReverseProxy, which bridges 101 upgrades rather than CONNECT's 200 response.

No linked issue.

Scope and non-goals

One end-to-end proxy capability: node tunnel establishment, gateway relay, authority-aware routing, tests and documentation. Existing HTTP/WebSocket routing and forwarded-header behavior are preserved. This does not introduce an arbitrary-destination forward proxy.

Design and behavior changes

client CONNECT -> gateway route/auth classification -> scheduler Lookup -> node authorization and runtime lookup/auto-resume -> guest TCP port

  • The node connects to the resolved guest before returning 200; connection failure remains an HTTP error. Existing private-traffic and secure-envd tokens are required where applicable.
  • The gateway replays the authenticated routing headers to the selected node, forwards rejection responses, preserves bytes buffered on either side, and bridges both directions with half-close support. An I/O error closes both connections.
  • Routing deadlines bound establishment and are cleared after success. HTTP node endpoints without an explicit port use port 80.
  • Gateway authority routing is shared by authorization classification, lookup and metrics. Ordinary host, path and header routes retain their existing behavior.

Compatibility and operations

  • Public API or generated protocol: additive HTTP/1.1 CONNECT support; no schema changes.
  • Configuration or defaults: uses existing proxy domains, tokens and timeouts; no new settings.
  • Snapshot manifest, artifact layout, or storage format: unchanged.
  • Upgrade and rollback: each node must support CONNECT before the gateway can successfully establish a tunnel to it. Rolling back removes the new capability; existing proxy protocols remain available.
  • Host requirements, permissions, ports, or dependencies: existing listeners and guest networking; no new dependencies. Gateway relay currently accepts http:// node endpoints only.

Validation

  • make fmt (equivalent cargo fmt --all -- --check)
  • make clippy (explicit package/all-target/all-feature command below)
  • make test-unit
  • Relevant Rust integration tests (separate gateway-to-KVM end-to-end validation below)
  • make -C services test
  • Generated clients/server regenerated with the documented make target (no generated changes)
  • Documentation updated
  • Benchmarks or performance comparison completed

Commands and results on isolated Linux, from this branch alone on 424b852:

cargo fmt --all -- --check: passed
cargo clippy --locked -p agentenv --all-targets --all-features -- -D warnings: passed
cargo test --locked -p agentenv --lib: 1021 passed, 5 ignored
make -C services test: passed
make -C services fmt-check vet: passed
cd services && go test -race ./...: passed
cargo build --locked -p agentenv --bin server -p uvm-ublk-daemon --bin uvm-ublk-daemon: passed

Real scheduler + gateway + non-root node + KVM guest: cold create/assignment; header and authority CONNECT to envd; private-traffic and secure-envd authentication; API key cannot replace a private-traffic token; 1 MiB binary echo with coalesced early bytes and client half-close; closed port and unknown sandbox errors; unauthorized access leaves a sandbox paused; authorized CONNECT auto-resumes the guest and its echo process; auto-resume-disabled returns 410; deletion rejects new access. All passed; task sandboxes and processes were cleaned up.

Skipped checks: the aggregate make test-unit and unrelated storage suites were not run; relevant Rust tests, all Go packages with race detection, and the actual gateway-to-KVM flow were run. No throughput benchmark was performed.

Risks and reviewer notes

Established tunnels have no new idle timeout or lifecycle cancellation signal. An idle tunnel is not actively terminated by pause/delete; the KVM check observed no EOF within two seconds, then closed the client explicitly. New connections still enforce current sandbox state and authorization.

Review the token-preserving request replay, buffered readers and half-close/error cleanup in services/gateway/internal/connect.go, and node establishment in src/api/proxy.rs.

Checklist

  • The PR contains one coherent change and no unrelated formatting or refactoring.
  • New behavior is covered by tests, or I explained why testing is impractical.
  • Logs and examples contain no credentials, tokens, or private registry information.
  • I did not manually edit generated code without updating its source and regenerating it.

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/kvcache-ai/AgentENV/pull/435 **Author:** [@guozy18](https://github.com/guozy18) **Created:** 10/25/2026 **Status:** ❌ Closed **Base:** `main` ← **Head:** `sync/sandbox-http-connect` --- ### 📝 Commits (3) - [`6794f40`](https://github.com/kvcache-ai/AgentENV/commit/6794f4029c39891f37dc4ad03d0218deac431b95) feat: support HTTP CONNECT tunneling to sandboxes in proxy - [`bdc1db0`](https://github.com/kvcache-ai/AgentENV/commit/bdc1db0e3b18eb0f115b9696099d3ec4fd214451) feat: relay HTTP CONNECT data-plane tunnels through the gateway - [`8935236`](https://github.com/kvcache-ai/AgentENV/commit/8935236da241c0059e817365886a4f52c3d3c704) feat: route gateway CONNECT requests via authority-aware host route ### 📊 Changes **9 files changed** (+1216 additions, -8 deletions) <details> <summary>View changed files</summary> 📝 `docs/src/internals/proxy-design.md` (+49 -1) 📝 `services/README.md` (+15 -1) ➕ `services/gateway/internal/connect.go` (+297 -0) ➕ `services/gateway/internal/connect_test.go` (+440 -0) 📝 `services/gateway/internal/host_route.go` (+40 -0) 📝 `services/gateway/internal/host_route_test.go` (+90 -0) 📝 `services/gateway/internal/metrics.go` (+13 -1) 📝 `services/gateway/internal/server.go` (+8 -3) 📝 `src/api/proxy.rs` (+264 -2) </details> ### 📄 Description ## What Support raw TCP access to sandbox ports with HTTP/1.1 CONNECT, directly through a node or through the gateway. Clients can select a sandbox with the existing routing headers or the configured `{port}-{sandboxID}.{domain}` authority. ## Why The sandbox proxy currently handles HTTP and WebSocket traffic but cannot establish a TCP tunnel. A gateway also cannot relay a successful CONNECT with its ordinary `ReverseProxy`, which bridges 101 upgrades rather than CONNECT's 200 response. ## Related issue No linked issue. ## Scope and non-goals One end-to-end proxy capability: node tunnel establishment, gateway relay, authority-aware routing, tests and documentation. Existing HTTP/WebSocket routing and forwarded-header behavior are preserved. This does not introduce an arbitrary-destination forward proxy. ## Design and behavior changes `client CONNECT -> gateway route/auth classification -> scheduler Lookup -> node authorization and runtime lookup/auto-resume -> guest TCP port` - The node connects to the resolved guest before returning 200; connection failure remains an HTTP error. Existing private-traffic and secure-envd tokens are required where applicable. - The gateway replays the authenticated routing headers to the selected node, forwards rejection responses, preserves bytes buffered on either side, and bridges both directions with half-close support. An I/O error closes both connections. - Routing deadlines bound establishment and are cleared after success. HTTP node endpoints without an explicit port use port 80. - Gateway authority routing is shared by authorization classification, lookup and metrics. Ordinary host, path and header routes retain their existing behavior. ## Compatibility and operations - Public API or generated protocol: additive HTTP/1.1 CONNECT support; no schema changes. - Configuration or defaults: uses existing proxy domains, tokens and timeouts; no new settings. - Snapshot manifest, artifact layout, or storage format: unchanged. - Upgrade and rollback: each node must support CONNECT before the gateway can successfully establish a tunnel to it. Rolling back removes the new capability; existing proxy protocols remain available. - Host requirements, permissions, ports, or dependencies: existing listeners and guest networking; no new dependencies. Gateway relay currently accepts `http://` node endpoints only. ## Validation - [x] `make fmt` (equivalent `cargo fmt --all -- --check`) - [x] `make clippy` (explicit package/all-target/all-feature command below) - [ ] `make test-unit` - [ ] Relevant Rust integration tests (separate gateway-to-KVM end-to-end validation below) - [x] `make -C services test` - [ ] Generated clients/server regenerated with the documented `make` target (no generated changes) - [x] Documentation updated - [ ] Benchmarks or performance comparison completed Commands and results on isolated Linux, from this branch alone on `424b852`: ```text cargo fmt --all -- --check: passed cargo clippy --locked -p agentenv --all-targets --all-features -- -D warnings: passed cargo test --locked -p agentenv --lib: 1021 passed, 5 ignored make -C services test: passed make -C services fmt-check vet: passed cd services && go test -race ./...: passed cargo build --locked -p agentenv --bin server -p uvm-ublk-daemon --bin uvm-ublk-daemon: passed ``` Real scheduler + gateway + non-root node + KVM guest: cold create/assignment; header and authority CONNECT to envd; private-traffic and secure-envd authentication; API key cannot replace a private-traffic token; 1 MiB binary echo with coalesced early bytes and client half-close; closed port and unknown sandbox errors; unauthorized access leaves a sandbox paused; authorized CONNECT auto-resumes the guest and its echo process; auto-resume-disabled returns 410; deletion rejects new access. All passed; task sandboxes and processes were cleaned up. Skipped checks: the aggregate `make test-unit` and unrelated storage suites were not run; relevant Rust tests, all Go packages with race detection, and the actual gateway-to-KVM flow were run. No throughput benchmark was performed. ## Risks and reviewer notes Established tunnels have no new idle timeout or lifecycle cancellation signal. An idle tunnel is not actively terminated by pause/delete; the KVM check observed no EOF within two seconds, then closed the client explicitly. New connections still enforce current sandbox state and authorization. Review the token-preserving request replay, buffered readers and half-close/error cleanup in `services/gateway/internal/connect.go`, and node establishment in `src/api/proxy.rs`. ## Checklist - [x] The PR contains one coherent change and no unrelated formatting or refactoring. - [x] New behavior is covered by tests, or I explained why testing is impractical. - [x] Logs and examples contain no credentials, tokens, or private registry information. - [x] I did not manually edit generated code without updating its source and regenerating it. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-29 14:23:23 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
kvcache-ai/AgentENV#436
No description provided.