mirror of
https://github.com/wirenboard/agent-vm.git
synced 2026-07-10 00:14:30 +00:00
auto-publish: forward 127.0.0.1 guest binds too, not only 0.0.0.0
Lima itself defaults to loopback-only (skipping 0.0.0.0) because on its host-network model 0.0.0.0 in the guest is reachable from the LAN and silently mirroring that on host loopback would change the security posture. Our setup is the other way around — smoltcp is in-process inside agent-vm, so 0.0.0.0 in the guest is reachable only from the agent-vm process anyway. Forwarding both is the same trust boundary and saves the user from having to remember which address their dev server happened to pick. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
913d9e0066
commit
800b51c411
2 changed files with 25 additions and 19 deletions
|
|
@ -5,10 +5,15 @@
|
|||
//! listener forwards each accepted connection through a
|
||||
//! per-connection in-guest python3 tunneller (see [`crate::exec_tunnel`]).
|
||||
//!
|
||||
//! Mirrors Lima's default policy: only `0.0.0.0` / `[::]` binds are
|
||||
//! auto-forwarded — loopback-only guest services stay private. To
|
||||
//! reach a guest 127.0.0.1 service from the host, use `--publish`
|
||||
//! (native, declarative) instead.
|
||||
//! Forwards both `127.0.0.1` *and* `0.0.0.0` listeners. Lima's
|
||||
//! default is loopback-only (because on Lima's host-network model
|
||||
//! `0.0.0.0` inside the guest is genuinely reachable from the LAN,
|
||||
//! and silently re-exposing that on host loopback would change the
|
||||
//! security posture). For us, smoltcp is in-process — both 127.0.0.1
|
||||
//! and 0.0.0.0 inside the guest are reachable only from the
|
||||
//! agent-vm process anyway, so forwarding either is the same trust
|
||||
//! boundary and skipping 0.0.0.0 would just mean "the user has to
|
||||
//! remember which one their dev server picked."
|
||||
//!
|
||||
//! Cancellation: the discovery task aborts itself when reading
|
||||
//! `/proc/net/tcp` errors repeatedly (sandbox shutting down). On
|
||||
|
|
@ -124,13 +129,14 @@ struct ForwardedPort {
|
|||
task: JoinHandle<()>,
|
||||
}
|
||||
|
||||
/// Decide whether to auto-forward this listener. Mirrors Lima's
|
||||
/// default: only forward wildcard binds; loopback-only services
|
||||
/// stay private to the guest.
|
||||
/// Decide whether to auto-forward this listener. Wildcard *and*
|
||||
/// loopback both qualify — see the module-level comment for why
|
||||
/// 0.0.0.0 is safe to forward in our in-process-smoltcp setup
|
||||
/// (unlike Lima).
|
||||
fn should_forward(entry: ListenEntry) -> bool {
|
||||
match entry.addr {
|
||||
IpAddr::V4(a) => a.is_unspecified(),
|
||||
IpAddr::V6(a) => a.is_unspecified(),
|
||||
IpAddr::V4(a) => a.is_unspecified() || a.is_loopback(),
|
||||
IpAddr::V6(a) => a.is_unspecified() || a.is_loopback(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -141,15 +141,13 @@ pub struct Args {
|
|||
#[arg(long = "publish", short = 'p')]
|
||||
publish: Vec<String>,
|
||||
|
||||
/// Auto-detect new `0.0.0.0` / `[::]` TCP listeners inside the
|
||||
/// guest and mirror each on `127.0.0.1:<same port>` on the host
|
||||
/// (Lima-style). Polls `/proc/net/tcp{,6}` over the agentd
|
||||
/// channel every ~2s; spawns a tokio TCP listener per detected
|
||||
/// port and bridges each accepted connection through a
|
||||
/// per-connection in-guest python3 tunneller. Loopback-only
|
||||
/// guest binds (`127.0.0.1`) are intentionally NOT forwarded
|
||||
/// (privacy / Lima parity). Heavy on overhead — fine for
|
||||
/// dev tunnels, use `--publish` for high-throughput.
|
||||
/// Auto-detect new TCP listeners inside the guest (both
|
||||
/// `127.0.0.1` and `0.0.0.0`/`[::]`) and mirror each on
|
||||
/// `127.0.0.1:<same port>` on the host. Polls `/proc/net/tcp{,6}`
|
||||
/// over the agentd channel every ~2s; spawns a tokio TCP listener
|
||||
/// per detected port and bridges each accepted connection through
|
||||
/// a per-connection in-guest python3 tunneller. Heavy on overhead
|
||||
/// — fine for dev tunnels, use `--publish` for high-throughput.
|
||||
#[arg(long = "auto-publish", default_value_t = false)]
|
||||
auto_publish: bool,
|
||||
|
||||
|
|
@ -682,7 +680,9 @@ pub async fn launch(agent: Agent, args: Args) -> Result<i32> {
|
|||
.context("verifying image-API contract version")?;
|
||||
|
||||
if args.auto_publish {
|
||||
eprintln!("==> auto-publish: polling /proc/net/tcp every ~2s for new 0.0.0.0 listeners");
|
||||
eprintln!(
|
||||
"==> auto-publish: polling /proc/net/tcp every ~2s for new 127.0.0.1 / 0.0.0.0 listeners"
|
||||
);
|
||||
crate::auto_publish::spawn(sandbox.clone());
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue