* Feature request: option to prevent guest from reaching host external addresses
@ 2026-05-02 14:25 baleti
2026-05-04 5:41 ` David Gibson
0 siblings, 1 reply; 2+ messages in thread
From: baleti @ 2026-05-02 14:25 UTC (permalink / raw)
To: passt-user
Hi,
I'd like to propose a new option for passt, working title --no-map-host,
as a complement to the existing --no-map-gw.
The gap
--no-map-gw prevents the guest from reaching host loopback services via
the gateway address mapping, which is useful. However, there is
currently no mechanism to prevent the guest from reaching services bound
to the host's real external address (e.g. 0.0.0.0:22).
Because passt proxies outbound guest connections as the host user, a
connection from the guest to the host's own external IP is transparently
forwarded — passt opens the socket on the host side and the connection
succeeds. From the perspective of the service being connected to (e.g.
sshd), it appears as a local connection.
A concrete example with a typical setup:
passt -t 2222 --no-map-gw --vhost-user --socket /tmp/passt-vm
ss -tulpn shows:
tcp LISTEN 0.0.0.0:22 sshd
From inside the guest, a compromised or untrusted workload can reach
sshd directly:
ssh user@192.168.1.x # host's external IP, connection succeeds
This also enables VM-to-VM lateral movement when multiple guests share
the same host: each guest can reach the others' forwarded ports via the
host's external IP.
The operator has no indication this is happening. Services bound to
0.0.0.0 are generally considered "LAN-exposed" rather than
"VM-guest-exposed", and this assumption is silently violated.
Proposed option
--no-map-host, which would cause passt to drop or reject TCP/UDP
connections from the guest whose destination matches any of the host's
own configured addresses (the same addresses passt already knows about
for DHCP/NDP assignment purposes).
An alternative spelling --map-host-addr none modelled on
--map-host-loopback none would also be consistent with the existing
option naming.
This would stay entirely within passt's existing socket-layer design and
require no new privileges.
Why this matters for rootless setups
The primary audience for passt is rootless VM deployments where
TAP+bridge (the traditional isolation mechanism) is not available
without privilege. In these setups, passt is the only network layer, so
operators rely on it to provide whatever isolation is possible.
--no-map-gw is a good step in that direction; --no-map-host would close
the remaining obvious gap.
Happy to discuss or test patches. Thanks for the project — it's been
very useful.
Best,
baleti
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: Feature request: option to prevent guest from reaching host external addresses
2026-05-02 14:25 Feature request: option to prevent guest from reaching host external addresses baleti
@ 2026-05-04 5:41 ` David Gibson
0 siblings, 0 replies; 2+ messages in thread
From: David Gibson @ 2026-05-04 5:41 UTC (permalink / raw)
To: baleti; +Cc: passt-user
[-- Attachment #1: Type: text/plain, Size: 7888 bytes --]
On Sat, May 02, 2026 at 03:25:17PM +0100, baleti wrote:
> Hi,
>
> I'd like to propose a new option for passt, working title --no-map-host, as
> a complement to the existing --no-map-gw.
So, I can see that might be useful, and I'm not necessarily against
it, but there are some important differences between the proposed
option and --no-map-gw, that make it trickier to work out exactly what
it should do and how.
Further details noted below, but the key difference is that
--no-map-gw behaviour arises naturally: the guest cannot reach the
host's loopback unless we specifically implement translation. We do
that translation by default, but --no-map-gw turns it off. That's not
true for the host's external address(es) - from the guest's point of
view (and even passt's, to an extent) there's no inherent difference
between a host external address and the address of any random machine
on the internet. To block this case we'd instead need to explicitly
filter out such connection attempts.
> The gap
>
> --no-map-gw prevents the guest from reaching host loopback services via the
> gateway address mapping, which is useful. However, there is currently no
> mechanism to prevent the guest from reaching services bound to the host's
> real external address (e.g. 0.0.0.0:22).
>
> Because passt proxies outbound guest connections as the host user, a
> connection from the guest to the host's own external IP is transparently
> forwarded — passt opens the socket on the host side and the connection
> succeeds. From the perspective of the service being connected to (e.g.
> sshd), it appears as a local connection.
That depends on what you mean by "local" here (unfortunately there are
several possible meanings, even within kernel networking interfaces).
The connection will *not* appear to come from a local scope address
(127.0.0.0/8 or ::1) - it will come from one of the host's external IP
addresses - typically the same one that you're connecting to.
It will, obviously, come from an IP that the host owns, and will
usually be routed over the host's 'lo' interface.
> A concrete example with a typical setup:
>
> passt -t 2222 --no-map-gw --vhost-user --socket /tmp/passt-vm
>
> ss -tulpn shows:
> tcp LISTEN 0.0.0.0:22 sshd
>
> From inside the guest, a compromised or untrusted workload can reach sshd
> directly:
>
> ssh user@192.168.1.x # host's external IP, connection succeeds
Yes, although this is also true for an untrusted external machine on
the host's LAN.
> This also enables VM-to-VM lateral movement when multiple guests share the
> same host: each guest can reach the others' forwarded ports via the host's
> external IP.
Right, the usual assumption here is that guest's forwarded ports are
intended to be exposed to the surrounding network - that does include
other VMs or containers, as well as the host and whatever's on the
host's LAN.
> The operator has no indication this is happening. Services bound to 0.0.0.0
> are generally considered "LAN-exposed" rather than "VM-guest-exposed", and
> this assumption is silently violated.
As far as I can tell something bound to 0.0.0.0 would be
VM-guest-exposed with most VM network setups, not just passt, unless
you explicitly introduce a firewall to catch it.
> Proposed option
>
> --no-map-host, which would cause passt to drop or reject TCP/UDP connections
> from the guest whose destination matches any of the host's own configured
> addresses (the same addresses passt already knows about for DHCP/NDP
> assignment purposes).
So, when the guest is sharing the host's IP (default behaviour) the
host's address is already implicitly blocked unless -map-guest-addr is
also specified, simply because if the guest tries to send to the
host's external address it will instead address itself. However, the
guest does have the ability to ignore the suggested IP, so that's not
really enforced.
Enforcing it raises several edge cases that need consideration though:
* If the host has several external addresses, do we want to block all
of them? One of them? Some of them?
* If the host changes external address, how do we update the
filtering to cover the new address?
We're looking (for other reasons) to introduce a netlink monitor
to track host address changes, which could be used for this.
However the update would not be instant. Is a short window where
the old/new address could be accessed acceptable?
These semantics would need to be pinned down in order to implement
this.
> An alternative spelling --map-host-addr none modelled on --map-host-loopback
> none would also be consistent with the existing option naming.
Right, I don't like that naming because although the effects are
analagous from the point of view of your usecase, they're very
different in terms of what they mean internally (an explicit filter
versus disabling a translation).
> This would stay entirely within passt's existing socket-layer design and
> require no new privileges.
No, but it does need new filtering logic to be implemented (but we're
kind of working on that already, see below).
> Why this matters for rootless setups
>
> The primary audience for passt is rootless VM deployments where TAP+bridge
> (the traditional isolation mechanism) is not available without privilege. In
> these setups, passt is the only network layer, so operators rely on it to
> provide whatever isolation is possible. --no-map-gw is a good step in that
> direction; --no-map-host would close the remaining obvious gap.
This doesn't fully make sense to me - AFAICT, TAP-bridges would also
leave the host's external address exposed to the VMs, unless filtered
by an additional mechanism (e.g. iptables / nftables).
> Happy to discuss or test patches. Thanks for the project — it's been very
> useful.
Thoughts on possible ways to achieve what you're looking for.
# Existing approaches
## --outbound-if4 and --outbound-if6
These options let you route VM traffic explicitly to specific host
interface. That won't directly make host addresses inaccessible, but
might be enough to stop it appearing as "local". You'd have to check
for the details of your use case.
## Isolate VMs within a netns
You can create a network namespace using unshare -Un, and run your VM
along with the associated passt within it. That lets the namespace
owner configure routing between it and the host as you like, including
explicit filters, if you want.
# Upcoming approaches
## Forwarding tables
We're in the process of implementing much more flexible forwarding /
filtering rules, which should make this a lot more feasible. We hope
to merge the first draft pretty soon, but that will only over incoming
and "spliced" (for containers) connections. We do plan to extend that
to filtering outbound connections as well though. That would
certainly allow you to block specific addresses from the VMs. This is
just waiting on the time to implement it.
## Multiple guest address handling
Only indirectly related, but we're also working on better handling of
multiple guest addresses, allowing (amongst other things) all the
host's addresses to be reflected in the guest, not just one. We
hadn't discussed it but we could potentially add to that enforcement
that the guest only use the addresses it's told do, which would also
effectively block host addresses from the guest (without
--map-guest-addr). There would likely be unavoidable races in
updating that for host address changes, however.
--
David Gibson (he or they) | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you, not the other way
| around.
http://www.ozlabs.org/~dgibson
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-05-04 6:56 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-05-02 14:25 Feature request: option to prevent guest from reaching host external addresses baleti
2026-05-04 5:41 ` David Gibson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for IMAP folder(s).