Skip to content

Add a loopback proxy, forwarded ports, and exec environments to the native-host backend - #420

Closed
Enrique Saurez (esaurez) wants to merge 1 commit into
esaurez/nvxhost-edge-fsnetfrom
esaurez/nvxhost-edge-proxy
Closed

Enrique Saurez (esaurez) wants to merge 1 commit into
esaurez/nvxhost-edge-fsnetfrom
esaurez/nvxhost-edge-proxy

Conversation

@esaurez

Copy link
Copy Markdown
Contributor

Replaces #414 on the rebased stack. Stacked on #419. Adds a host-loopback proxy, forwarded ports, and exec environments to the opt-in native-host backend.

Summary

  • Loopback proxy. runtimeConfig.networkProxy (ProvisionRequest::with_network_proxy) names an http or https proxy on host loopback with an explicit port. As in MXC's schema, the proxy is the guest's only way out, so the network policy must deny egress without allow or deny rules. The guest's only reachable destination is TCP to its gateway at the proxy's port, which OpenVMM connects to the proxy. Every workload gets HTTP_PROXY, HTTPS_PROXY, http_proxy, and https_proxy naming the proxy at the gateway, plus NO_PROXY and no_proxy set to localhost,127.0.0.1. Callers can never set these variables, with or without a proxy.
  • Forwarded ports. microvm.provision.hostLoopbackForwards (ProvisionRequest::with_host_loopback_forward) publishes up to 64 guest TCP or UDP ports on host loopback. Forwarded ports need network.ingress.hostLoopback: allow, an egress default of allow, and no deny rule that covers the guest network, because OpenVMM filters the guest's replies. In OpenVMM, hostLoopback: allow also lets the guest reach host loopback services through its gateway. allow without forwarded ports is still rejected, and a proxy and forwarded ports cannot be combined.
  • Exec environments and working directories. process.cwd and process.env with inheritDefaultEnv: true now apply, layered over the guest's default PATH (at most 256 entries and 32 KiB). Replacing the default environment still fails with policy_validation. ExecuteCommandRequest gains working_directory and environment.
  • Capabilities and validation. NetworkCapabilities gains network_proxy and host_loopback_forwards; validation accepts hostLoopback: allow only together with forwarded ports. The private library plans every combination rule, so an unenforceable policy fails provision with policy_validation.
  • Guest ABI. The runtime ABI name moves to microvm-abi-v2-edge-ramfs-v3.
  • Tests and example. New ignored guest tests: a_loopback_proxy_is_the_only_way_out, forwarded_ports_publish_guest_listeners_on_host_loopback, and exec_environments_layer_over_the_guest_defaults. The example takes --network-proxy, --host-loopback, --host-loopback-forward, --env, and --cwd.

Dependencies

  • Requires the matching private host library and edge guest (runtime ABI v3). The C ABI is unchanged.
  • OpenVMM is unchanged: the pinned revision provides --network-proxy, --host-loopback, and --host-loopback-forward.

Changes since #414

None: the commit replays onto the rebased stack unchanged.

Validation

  • Each PR head in this stack passes cargo test --all-features and Clippy with -D warnings on all targets with --all-features, on Windows with Rust 1.93 (135, 137, 139, 139, and 140 unit tests).
  • At the top of the stack (5b0a315), on Windows and on Linux with Rust 1.93: the crate's CI checks, which are fmt, Clippy with --all-features and with --no-default-features, tests with --all-features and with default features, docs with -D warnings, cargo +1.89 check, and, on Linux, the macOS build check. The pinned library test passes against freshly built nvxhost.dll and libnvxhost.so.
  • Guest suite at the top of the stack, 20 tests, --release --test-threads=1, each checking that no OpenVMM process outlives its sandbox, with dev's Linux 6.18.38 kernel:
    • Windows/WHP on an AMD EPYC 7763, which amd.milan.v1 serves: all pass, in about 100 s, and again with a host profile;
    • Linux/MSHV on an AMD EPYC 9V74, which no built-in profile serves: all pass with a host profile, in about 82 s.

The new tests check, among others, that the six proxy variables are exactly the gateway URL and localhost,127.0.0.1; that TCP to the proxy's port reaches the host proxy while UDP to the same port, another host loopback port, and a host service are blocked; that forwarded TCP and UDP ports reach guest listeners; and that the largest accepted environment (240 entries of control characters, 32,640 bytes) reaches the workload.

Notes

  • An HTTPS proxy's certificate must be valid for the gateway address, where workloads reach it.
  • Forwarded ports leave the guest's other egress open, and expose every host loopback service at the gateway; that is how OpenVMM publishes ports.
  • Stored plans are revalidated but not authenticated; that is the existing trust model, and the README says that the plan also decides the proxy port and forwarded ports.

The native-host backend accepts two more provision options. A
runtimeConfig.networkProxy names an HTTP or HTTPS proxy on host loopback; it
must be the guest's only way out, so the network policy denies egress without
rules. The guest reaches the proxy over TCP at its gateway, and every workload
gets HTTP_PROXY, HTTPS_PROXY, and NO_PROXY in both cases, pointing there.
microvm.provision.hostLoopbackForwards publishes guest TCP and UDP ports on
host loopback; forwarded ports need hostLoopback allow and an egress default of
allow, because the guest's replies pass the egress filter.

Executions may now set a working directory and environment variables layered
over the guest's defaults (inheritDefaultEnv). Callers can never set the proxy
variables. ExecuteCommandRequest gains working_directory and environment, and
the guest runtime ABI moves to microvm-abi-v2-edge-ramfs-v3.

New guest tests prove that the proxy is the only way out, that forwarded TCP
and UDP ports reach guest listeners, and that the largest accepted environment
reaches the workload. The example gains matching options.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@esaurez

Copy link
Copy Markdown
Contributor Author

Folded into #418, which now carries the whole change. The native library implements this feature behind the model types that #418 adds, and its guest tests are part of the end-to-end suite there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant