|
|
f07426 |
From ae0004f591d816f1b6e78c57c3d9530098f123b0 Mon Sep 17 00:00:00 2001
|
|
|
f07426 |
From: Stefano Brivio <sbrivio@redhat.com>
|
|
|
f07426 |
Date: Thu, 23 Feb 2023 16:41:47 +0000
|
|
|
f07426 |
Subject: [PATCH 03/20] conf, udp: Allow any loopback address to be used as
|
|
|
f07426 |
resolver
|
|
|
f07426 |
|
|
|
f07426 |
Andrea reports that with a Fedora 37 guest running on a Fedora 37
|
|
|
f07426 |
host, both using systemd-resolved, with passt connecting them,
|
|
|
f07426 |
running with default options, DNS queries don't work.
|
|
|
f07426 |
|
|
|
f07426 |
systemd-resolved on the host is reachable only at the loopback
|
|
|
f07426 |
address 127.0.0.53.
|
|
|
f07426 |
|
|
|
f07426 |
We advertise the default gateway address to the guest as resolver,
|
|
|
f07426 |
because our local address is of course unreachable from there, which
|
|
|
f07426 |
means we see DNS queries directed to the default gateway, and we
|
|
|
f07426 |
redirect them to 127.0.0.1. However, systemd-resolved doesn't answer
|
|
|
f07426 |
on 127.0.0.1.
|
|
|
f07426 |
|
|
|
f07426 |
To fix this, set @dns_match to the address of the default gateway,
|
|
|
f07426 |
unless a different resolver address is explicitly configured, so that
|
|
|
f07426 |
we know we explicitly have to map DNS queries, in this case, to the
|
|
|
f07426 |
address of the local resolver.
|
|
|
f07426 |
|
|
|
f07426 |
This means that in udp_tap_handler() we need to check, first, if
|
|
|
f07426 |
the destination address of packets matches @dns_match: even if it's
|
|
|
f07426 |
the address of the local gateway, we want to map that to a specific
|
|
|
f07426 |
address, which isn't necessarily 127.0.0.1.
|
|
|
f07426 |
|
|
|
f07426 |
Do the same for IPv6 for consistency, even though IPv6 defines a
|
|
|
f07426 |
single loopback address.
|
|
|
f07426 |
|
|
|
f07426 |
Reported-by: Andrea Bolognani <abologna@redhat.com>
|
|
|
f07426 |
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
|
|
|
f07426 |
Tested-by: Andrea Bolognani <abologna@redhat.com>
|
|
|
f07426 |
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
|
|
|
f07426 |
(cherry picked from commit bad252687271c0255f6a077f19cbc19aa0427f8d)
|
|
|
f07426 |
---
|
|
|
f07426 |
conf.c | 6 ++++++
|
|
|
f07426 |
udp.c | 20 ++++++++++----------
|
|
|
f07426 |
2 files changed, 16 insertions(+), 10 deletions(-)
|
|
|
f07426 |
|
|
|
f07426 |
diff --git a/conf.c b/conf.c
|
|
|
f07426 |
index ed25e35..37f25d6 100644
|
|
|
f07426 |
--- a/conf.c
|
|
|
f07426 |
+++ b/conf.c
|
|
|
f07426 |
@@ -395,6 +395,9 @@ static void add_dns4(struct ctx *c, struct in_addr *addr, struct in_addr **conf)
|
|
|
f07426 |
if (!c->no_map_gw) {
|
|
|
f07426 |
**conf = c->ip4.gw;
|
|
|
f07426 |
(*conf)++;
|
|
|
f07426 |
+
|
|
|
f07426 |
+ if (IN4_IS_ADDR_UNSPECIFIED(&c->ip4.dns_match))
|
|
|
f07426 |
+ c->ip4.dns_match = c->ip4.gw;
|
|
|
f07426 |
}
|
|
|
f07426 |
} else {
|
|
|
f07426 |
**conf = *addr;
|
|
|
f07426 |
@@ -419,6 +422,9 @@ static void add_dns6(struct ctx *c,
|
|
|
f07426 |
if (!c->no_map_gw) {
|
|
|
f07426 |
memcpy(*conf, &c->ip6.gw, sizeof(**conf));
|
|
|
f07426 |
(*conf)++;
|
|
|
f07426 |
+
|
|
|
f07426 |
+ if (IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns_match))
|
|
|
f07426 |
+ memcpy(&c->ip6.dns_match, addr, sizeof(*addr));
|
|
|
f07426 |
}
|
|
|
f07426 |
} else {
|
|
|
f07426 |
memcpy(*conf, addr, sizeof(**conf));
|
|
|
f07426 |
diff --git a/udp.c b/udp.c
|
|
|
f07426 |
index 1d65559..20a9ea0 100644
|
|
|
f07426 |
--- a/udp.c
|
|
|
f07426 |
+++ b/udp.c
|
|
|
f07426 |
@@ -857,17 +857,16 @@ int udp_tap_handler(struct ctx *c, int af, const void *addr,
|
|
|
f07426 |
|
|
|
f07426 |
udp_tap_map[V4][src].ts = now->tv_sec;
|
|
|
f07426 |
|
|
|
f07426 |
- if (IN4_ARE_ADDR_EQUAL(&s_in.sin_addr, &c->ip4.gw) &&
|
|
|
f07426 |
- !c->no_map_gw) {
|
|
|
f07426 |
+ if (IN4_ARE_ADDR_EQUAL(&s_in.sin_addr, &c->ip4.dns_match) &&
|
|
|
f07426 |
+ ntohs(s_in.sin_port) == 53) {
|
|
|
f07426 |
+ s_in.sin_addr = c->ip4.dns_host;
|
|
|
f07426 |
+ } else if (IN4_ARE_ADDR_EQUAL(&s_in.sin_addr, &c->ip4.gw) &&
|
|
|
f07426 |
+ !c->no_map_gw) {
|
|
|
f07426 |
if (!(udp_tap_map[V4][dst].flags & PORT_LOCAL) ||
|
|
|
f07426 |
(udp_tap_map[V4][dst].flags & PORT_LOOPBACK))
|
|
|
f07426 |
s_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
|
|
f07426 |
else
|
|
|
f07426 |
s_in.sin_addr = c->ip4.addr_seen;
|
|
|
f07426 |
- } else if (IN4_ARE_ADDR_EQUAL(&s_in.sin_addr,
|
|
|
f07426 |
- &c->ip4.dns_match) &&
|
|
|
f07426 |
- ntohs(s_in.sin_port) == 53) {
|
|
|
f07426 |
- s_in.sin_addr = c->ip4.dns_host;
|
|
|
f07426 |
}
|
|
|
f07426 |
} else {
|
|
|
f07426 |
s_in6 = (struct sockaddr_in6) {
|
|
|
f07426 |
@@ -880,7 +879,11 @@ int udp_tap_handler(struct ctx *c, int af, const void *addr,
|
|
|
f07426 |
sa = (struct sockaddr *)&s_in6;
|
|
|
f07426 |
sl = sizeof(s_in6);
|
|
|
f07426 |
|
|
|
f07426 |
- if (IN6_ARE_ADDR_EQUAL(addr, &c->ip6.gw) && !c->no_map_gw) {
|
|
|
f07426 |
+ if (IN6_ARE_ADDR_EQUAL(addr, &c->ip6.dns_match) &&
|
|
|
f07426 |
+ ntohs(s_in6.sin6_port) == 53) {
|
|
|
f07426 |
+ s_in6.sin6_addr = c->ip6.dns_host;
|
|
|
f07426 |
+ } else if (IN6_ARE_ADDR_EQUAL(addr, &c->ip6.gw) &&
|
|
|
f07426 |
+ !c->no_map_gw) {
|
|
|
f07426 |
if (!(udp_tap_map[V6][dst].flags & PORT_LOCAL) ||
|
|
|
f07426 |
(udp_tap_map[V6][dst].flags & PORT_LOOPBACK))
|
|
|
f07426 |
s_in6.sin6_addr = in6addr_loopback;
|
|
|
f07426 |
@@ -888,9 +891,6 @@ int udp_tap_handler(struct ctx *c, int af, const void *addr,
|
|
|
f07426 |
s_in6.sin6_addr = c->ip6.addr;
|
|
|
f07426 |
else
|
|
|
f07426 |
s_in6.sin6_addr = c->ip6.addr_seen;
|
|
|
f07426 |
- } else if (IN6_ARE_ADDR_EQUAL(addr, &c->ip6.dns_match) &&
|
|
|
f07426 |
- ntohs(s_in6.sin6_port) == 53) {
|
|
|
f07426 |
- s_in6.sin6_addr = c->ip6.dns_host;
|
|
|
f07426 |
} else if (IN6_IS_ADDR_LINKLOCAL(&s_in6.sin6_addr)) {
|
|
|
f07426 |
bind_addr = &c->ip6.addr_ll;
|
|
|
f07426 |
}
|
|
|
f07426 |
--
|
|
|
f07426 |
2.39.2
|
|
|
f07426 |
|