From: Stefano Brivio <sbrivio@redhat.com>
To: David Gibson <david@gibson.dropbear.id.au>
Cc: passt-dev@passt.top
Subject: Re: [PATCH 3/3] fwd: Rework inconsistencies in translation of inbound flows
Date: Mon, 12 Aug 2024 23:51:17 +0200 [thread overview]
Message-ID: <20240812235117.6a48a817@elisabeth> (raw)
In-Reply-To: <20240812095355.1721876-4-david@gibson.dropbear.id.au>
I applied up to 2/3, I just have one doubt here, and a nit:
On Mon, 12 Aug 2024 19:53:55 +1000
David Gibson <david@gibson.dropbear.id.au> wrote:
> We usually avoid NAT, but in a few cases we need to apply address
> translations. The current logic for this on inbound flows has some
> inconsistencies:
>
> * For IPv4 (but not IPv6) we translated unspecified source addresses
...I know we already talked about this, but 0.0.0.0/8 is not just
unspecified, it also means "this host on this network" (RFC 6890,
2.2.2), and that's the reason for this apparent inconsistency (::
doesn't). By the way, somebody was reminded of this just recently:
https://www.oligo.security/blog/0-0-0-0-day-exploiting-localhost-apis-from-the-browser
https://lwn.net/Articles/984838/
Now, if I recall correctly, the kernel translates that anyway to a
loopback address before we see it. But still it's a legitimate address
to use, so I would keep handling it as a loopback address.
> While an unspecified source probably doesn't make sense, it makes no less
> sense in the guest context than it does for the host, it's possible there
> could be protocols / flow types where this works. At the moment, this
> should never happen since the protocols will drop the flow before getting
> here. So, don't alter unspecified addresses for either IP version.
>
> * For IPv6 (but not IPv4) we translated the guest's assigned address
>
> We always translated the guest's observed address, but for the case where
> the assigned address different we should be consistent. Translate the
> guest assigned address for IPv4 as well.
Hm, right, this looks like an oversight in e58828f34067 ("tcp: Fixes
for closing states, spliced connections, out-of-order packets, etc.").
> The overall point is that we need to translate here if and only if the host
> address is one that's not accessible to the guest. Create some helper
> functions to determine this, which will have additional uses later.
>
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> ---
> fwd.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++--------
> 1 file changed, 77 insertions(+), 11 deletions(-)
>
> diff --git a/fwd.c b/fwd.c
> index dea36f6c..24700998 100644
> --- a/fwd.c
> +++ b/fwd.c
> @@ -170,6 +170,73 @@ static bool is_dns_flow(uint8_t proto, const struct flowside *ini)
> ((ini->fport == 53) || (ini->fport == 853));
> }
>
> +/**
> + * fwd_guest_accessible4() - Is IPv4 address guest accessible
> + * @c: Execution context
> + * @addr: Host visible IPv4 address
> + *
> + * Return: true if @addr on the host is accessible to the guest without
> + * translation, false otherwise
> + */
> +static bool fwd_guest_accessible4(const struct ctx *c,
> + const struct in_addr *addr)
> +{
> + if (IN4_IS_ADDR_LOOPBACK(addr))
> + return false;
> +
> + if (IN4_ARE_ADDR_EQUAL(addr, &c->ip4.addr))
> + return false;
> +
> + if (!IN4_IS_ADDR_UNSPECIFIED(&c->ip4.addr_seen) &&
> + IN4_ARE_ADDR_EQUAL(addr, &c->ip4.addr_seen))
> + return false;
> +
> + return true;
> +}
> +
> +/**
> + * fwd_guest_accessible6() - Is IPv6 address guest accessible
> + * @c: Execution context
> + * @addr: Host visible IPv6 address
> + *
> + * Return: true if @addr on the host is accessible to the guest without
> + * translation, false otherwise
> + */
> +static bool fwd_guest_accessible6(const struct ctx *c,
> + const struct in6_addr *addr)
> +{
> + if (IN6_IS_ADDR_LOOPBACK(addr))
> + return false;
> +
> + if (IN6_ARE_ADDR_EQUAL(addr, &c->ip6.addr))
> + return false;
> +
> + if (!IN6_IS_ADDR_UNSPECIFIED(&c->ip6.addr_seen) &&
> + IN6_ARE_ADDR_EQUAL(addr, &c->ip6.addr_seen))
> + return false;
> +
> + return true;
> +}
> +
> +/**
> + * fwd_guest_accessible() - Is IPv[46] address guest accessible
> + * @c: Execution context
> + * @addr: Host visible IPv[46] address
> + *
> + * Return: true if @addr on the host is accessible to the guest without
> + * translation, false otherwise
> + */
> +static bool fwd_guest_accessible(const struct ctx *c,
> + const union inany_addr *addr)
> +{
> + const struct in_addr *a4 = inany_v4(addr);
> +
> + if (a4)
> + return fwd_guest_accessible4(c, a4);
> +
> + return fwd_guest_accessible6(c, &addr->a6);
> +}
> +
> /**
> * fwd_nat_from_tap() - Determine to forward a flow from the tap interface
> * @c: Execution context
> @@ -307,21 +374,20 @@ uint8_t fwd_nat_from_host(const struct ctx *c, uint8_t proto,
> return PIF_SPLICE;
> }
>
> - tgt->faddr = ini->eaddr;
> - tgt->fport = ini->eport;
> -
> - if (inany_is_loopback4(&tgt->faddr) ||
> - inany_is_unspecified4(&tgt->faddr) ||
> - inany_equals4(&tgt->faddr, &c->ip4.addr_seen)) {
> - tgt->faddr = inany_from_v4(c->ip4.gw);
> - } else if (inany_is_loopback6(&tgt->faddr) ||
> - inany_equals6(&tgt->faddr, &c->ip6.addr_seen) ||
> - inany_equals6(&tgt->faddr, &c->ip6.addr)) {
> - if (IN6_IS_ADDR_LINKLOCAL(&c->ip6.gw))
> + /* These host-visible addresses aren't visible to the guest, so need
I guess you wrote this before moving the checks to their own function:
it took me a bit to figure out that "These host-visible addresses" are
not really mentioned here. Maybe s/These/Some/?
> + * translation
> + */
> + if (!fwd_guest_accessible(c, &ini->eaddr)) {
> + if (inany_v4(&ini->eaddr))
> + tgt->faddr = inany_from_v4(c->ip4.gw);
> + else if (IN6_IS_ADDR_LINKLOCAL(&c->ip6.gw))
> tgt->faddr.a6 = c->ip6.gw;
> else
> tgt->faddr.a6 = c->ip6.addr_ll;
> + } else {
> + tgt->faddr = ini->eaddr;
> }
> + tgt->fport = ini->eport;
>
> if (inany_v4(&tgt->faddr)) {
> tgt->eaddr = inany_from_v4(c->ip4.addr_seen);
--
Stefano
next prev parent reply other threads:[~2024-08-12 21:51 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-08-12 9:53 [PATCH 0/3] Assorted fixes related to addressing David Gibson
2024-08-12 9:53 ` [PATCH 1/3] Correct inaccurate comments on ip[46]_ctx::addr David Gibson
2024-08-12 9:53 ` [PATCH 2/3] conf: Delay handling -D option until after addresses are configured David Gibson
2024-08-12 9:53 ` [PATCH 3/3] fwd: Rework inconsistencies in translation of inbound flows David Gibson
2024-08-12 21:51 ` Stefano Brivio [this message]
2024-08-15 5:01 ` David Gibson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240812235117.6a48a817@elisabeth \
--to=sbrivio@redhat.com \
--cc=david@gibson.dropbear.id.au \
--cc=passt-dev@passt.top \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://passt.top/passt
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).