aboutgitcodebugslistschat
diff options
context:
space:
mode:
authorStefano Brivio <sbrivio@redhat.com>2024-03-15 15:17:08 +0100
committerStefano Brivio <sbrivio@redhat.com>2024-03-18 08:57:40 +0100
commitd989eae308c2ea2032fc91cc04fb02dffe4a4b63 (patch)
tree61f6fb7738b54a5509cf4bf6241017b7be6bcc67
parentf919dc7a4b1ced7e80d790a654900415e1d6250e (diff)
downloadpasst-d989eae308c2ea2032fc91cc04fb02dffe4a4b63.tar
passt-d989eae308c2ea2032fc91cc04fb02dffe4a4b63.tar.gz
passt-d989eae308c2ea2032fc91cc04fb02dffe4a4b63.tar.bz2
passt-d989eae308c2ea2032fc91cc04fb02dffe4a4b63.tar.lz
passt-d989eae308c2ea2032fc91cc04fb02dffe4a4b63.tar.xz
passt-d989eae308c2ea2032fc91cc04fb02dffe4a4b63.tar.zst
passt-d989eae308c2ea2032fc91cc04fb02dffe4a4b63.zip
udp: Translate source address of resolver only for DNS remapped queries
Paul reports that if pasta is configured with --dns-forward, and the container queries a resolver which is configured on the host directly, without using the address given for --dns-forward, we'll translate the source address of the response pretending it's coming from the address passed as --dns-forward, and the client will discard the reply. That is, $ cat /etc/resolv.conf 198.51.100.1 $ pasta --config-net --dns-forward 192.0.2.1 nslookup passt.top will not work, because we change the source address of the reply from 198.51.100.1 to 192.0.2.1. But the client contacted 198.51.100.1, and it's from that address that it expects an answer. Add a PORT_DNS_FWD flag for tap-facing ports, which is triggered by activity in the opposite direction as the other flags. If the tap-facing port was seen sending a DNS query that was remapped, we'll remap the source address of the response, otherwise we'll leave it unaffected. Reported-by: Paul Holzinger <pholzing@redhat.com> Signed-off-by: Stefano Brivio <sbrivio@redhat.com> Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
-rw-r--r--udp.c21
1 files changed, 15 insertions, 6 deletions
diff --git a/udp.c b/udp.c
index 0a7f3b7..694424a 100644
--- a/udp.c
+++ b/udp.c
@@ -127,15 +127,16 @@
/**
* struct udp_tap_port - Port tracking based on tap-facing source port
* @sock: Socket bound to source port used as index
- * @flags: Flags for local bind, loopback address/unicast address as source
+ * @flags: Flags for recent activity type seen from/to port
* @ts: Activity timestamp from tap, used for socket aging
*/
struct udp_tap_port {
int sock;
uint8_t flags;
-#define PORT_LOCAL BIT(0)
-#define PORT_LOOPBACK BIT(1)
-#define PORT_GUA BIT(2)
+#define PORT_LOCAL BIT(0) /* Port was contacted from local address */
+#define PORT_LOOPBACK BIT(1) /* Port was contacted from loopback address */
+#define PORT_GUA BIT(2) /* Port was contacted from global unicast */
+#define PORT_DNS_FWD BIT(3) /* Port used as source for DNS remapped query */
time_t ts;
};
@@ -579,7 +580,8 @@ static size_t udp_update_hdr4(const struct ctx *c, struct udp4_l2_buf_t *b,
struct in_addr src = b->s_in.sin_addr;
if (!IN4_IS_ADDR_UNSPECIFIED(&c->ip4.dns_match) &&
- IN4_ARE_ADDR_EQUAL(&src, &c->ip4.dns_host) && srcport == 53) {
+ IN4_ARE_ADDR_EQUAL(&src, &c->ip4.dns_host) && srcport == 53 &&
+ (udp_tap_map[V4][dstport].flags & PORT_DNS_FWD)) {
src = c->ip4.dns_match;
} else if (IN4_IS_ADDR_LOOPBACK(&src) ||
IN4_ARE_ADDR_EQUAL(&src, &c->ip4.addr_seen)) {
@@ -632,7 +634,8 @@ static size_t udp_update_hdr6(const struct ctx *c, struct udp6_l2_buf_t *b,
dst = &c->ip6.addr_ll_seen;
} else if (!IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns_match) &&
IN6_ARE_ADDR_EQUAL(src, &c->ip6.dns_host) &&
- srcport == 53) {
+ srcport == 53 &&
+ (udp_tap_map[V4][dstport].flags & PORT_DNS_FWD)) {
src = &c->ip6.dns_match;
} else if (IN6_IS_ADDR_LOOPBACK(src) ||
IN6_ARE_ADDR_EQUAL(src, &c->ip6.addr_seen) ||
@@ -841,6 +844,9 @@ int udp_tap_handler(struct ctx *c, uint8_t pif,
if (IN4_ARE_ADDR_EQUAL(&s_in.sin_addr, &c->ip4.dns_match) &&
ntohs(s_in.sin_port) == 53) {
s_in.sin_addr = c->ip4.dns_host;
+ udp_tap_map[V4][src].ts = now->tv_sec;
+ udp_tap_map[V4][src].flags |= PORT_DNS_FWD;
+ bitmap_set(udp_act[V4][UDP_ACT_TAP], src);
} else if (IN4_ARE_ADDR_EQUAL(&s_in.sin_addr, &c->ip4.gw) &&
!c->no_map_gw) {
if (!(udp_tap_map[V4][dst].flags & PORT_LOCAL) ||
@@ -890,6 +896,9 @@ int udp_tap_handler(struct ctx *c, uint8_t pif,
if (IN6_ARE_ADDR_EQUAL(daddr, &c->ip6.dns_match) &&
ntohs(s_in6.sin6_port) == 53) {
s_in6.sin6_addr = c->ip6.dns_host;
+ udp_tap_map[V6][src].ts = now->tv_sec;
+ udp_tap_map[V6][src].flags |= PORT_DNS_FWD;
+ bitmap_set(udp_act[V6][UDP_ACT_TAP], src);
} else if (IN6_ARE_ADDR_EQUAL(daddr, &c->ip6.gw) &&
!c->no_map_gw) {
if (!(udp_tap_map[V6][dst].flags & PORT_LOCAL) ||