Skip to content

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

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

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

Conversation

@esaurez

Copy link
Copy Markdown
Contributor

Summary

Stacked on #407. Adds a host-loopback proxy, forwarded ports, and exec environments to the opt-in native-host backend.

  • 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 9524065 already provides --network-proxy, --host-loopback, and --host-loopback-forward.

Validation (head f8eec4c)

  • Windows: cargo test --features nvxhost,testing,async (136 unit tests plus every integration suite) and the default cargo test (102 unit tests); Clippy with -D warnings on all targets for both configurations; cargo +1.89 check for both.
  • Linux (Rust 1.98.1): fmt and the same Clippy and test commands (136 and 102 unit tests).
  • Guest suite, 19 tests, --release --test-threads=1, each checking that no OpenVMM process outlives its sandbox:
    • Windows/WHP: all pass, about 108 s;
    • Linux/MSHV: all pass, about 83 s.
  • Coverage of the new tests:
    • proxy: the six variables are exactly the gateway URL and localhost,127.0.0.1; 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; a proxy with egress rules or with egress allow, a remote or IPv6 proxy, a proxy without a port, and an exec that sets a proxy variable all fail with policy_validation;
    • forwarded ports: forwarded TCP and UDP host-loopback ports reach guest listeners, and the guest reaches a host loopback service at its gateway; generic host-loopback access, forwarded ports without it, and forwarded ports with egress deny fail with policy_validation;
    • environments: the working directory and layered variables apply, a later entry wins, PATH can be replaced, a missing directory ends the command with 126 and NVX-EDGE-STAGE-ERROR, and the largest accepted environment (240 entries of control characters, 32,640 bytes) reaches the workload.
  • The example, with a proxy, two variables, and /tmp, prints /tmp and B|two words|http://10.0.0.1:3128|localhost,127.0.0.1.

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.
  • An independent review found one medium and two low issues, all addressed: the guest now passes its workload stage configuration through a descriptor, because the largest environment, made of control characters, exceeded execve's per-string limit once encoded (the new environment test failed with the earlier guest); the forwarding test bounds its waits and retries a start when another process takes a released port; and a doc comment was reworded. It also noted that stored plans are revalidated but not authenticated. That is the existing trust model; the README now 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

Superseded by #418, which carries this change on dev as part of the whole native-host edge backend, over nanvix/openvmm#121, and is validated end to end on WHP and MSHV. Closing.

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