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>
This commit is contained in:
parent
f919dc7a4b
commit
d989eae308
1 changed files with 15 additions and 6 deletions
21
udp.c
21
udp.c
|
@ -127,15 +127,16 @@
|
||||||
/**
|
/**
|
||||||
* struct udp_tap_port - Port tracking based on tap-facing source port
|
* struct udp_tap_port - Port tracking based on tap-facing source port
|
||||||
* @sock: Socket bound to source port used as index
|
* @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
|
* @ts: Activity timestamp from tap, used for socket aging
|
||||||
*/
|
*/
|
||||||
struct udp_tap_port {
|
struct udp_tap_port {
|
||||||
int sock;
|
int sock;
|
||||||
uint8_t flags;
|
uint8_t flags;
|
||||||
#define PORT_LOCAL BIT(0)
|
#define PORT_LOCAL BIT(0) /* Port was contacted from local address */
|
||||||
#define PORT_LOOPBACK BIT(1)
|
#define PORT_LOOPBACK BIT(1) /* Port was contacted from loopback address */
|
||||||
#define PORT_GUA BIT(2)
|
#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;
|
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;
|
struct in_addr src = b->s_in.sin_addr;
|
||||||
|
|
||||||
if (!IN4_IS_ADDR_UNSPECIFIED(&c->ip4.dns_match) &&
|
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;
|
src = c->ip4.dns_match;
|
||||||
} else if (IN4_IS_ADDR_LOOPBACK(&src) ||
|
} else if (IN4_IS_ADDR_LOOPBACK(&src) ||
|
||||||
IN4_ARE_ADDR_EQUAL(&src, &c->ip4.addr_seen)) {
|
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;
|
dst = &c->ip6.addr_ll_seen;
|
||||||
} else if (!IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns_match) &&
|
} else if (!IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns_match) &&
|
||||||
IN6_ARE_ADDR_EQUAL(src, &c->ip6.dns_host) &&
|
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;
|
src = &c->ip6.dns_match;
|
||||||
} else if (IN6_IS_ADDR_LOOPBACK(src) ||
|
} else if (IN6_IS_ADDR_LOOPBACK(src) ||
|
||||||
IN6_ARE_ADDR_EQUAL(src, &c->ip6.addr_seen) ||
|
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) &&
|
if (IN4_ARE_ADDR_EQUAL(&s_in.sin_addr, &c->ip4.dns_match) &&
|
||||||
ntohs(s_in.sin_port) == 53) {
|
ntohs(s_in.sin_port) == 53) {
|
||||||
s_in.sin_addr = c->ip4.dns_host;
|
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) &&
|
} else if (IN4_ARE_ADDR_EQUAL(&s_in.sin_addr, &c->ip4.gw) &&
|
||||||
!c->no_map_gw) {
|
!c->no_map_gw) {
|
||||||
if (!(udp_tap_map[V4][dst].flags & PORT_LOCAL) ||
|
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) &&
|
if (IN6_ARE_ADDR_EQUAL(daddr, &c->ip6.dns_match) &&
|
||||||
ntohs(s_in6.sin6_port) == 53) {
|
ntohs(s_in6.sin6_port) == 53) {
|
||||||
s_in6.sin6_addr = c->ip6.dns_host;
|
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) &&
|
} else if (IN6_ARE_ADDR_EQUAL(daddr, &c->ip6.gw) &&
|
||||||
!c->no_map_gw) {
|
!c->no_map_gw) {
|
||||||
if (!(udp_tap_map[V6][dst].flags & PORT_LOCAL) ||
|
if (!(udp_tap_map[V6][dst].flags & PORT_LOCAL) ||
|
||||||
|
|
Loading…
Reference in a new issue