On Thu, Nov 03, 2022 at 12:04:43AM +0100, Stefano Brivio wrote: > Now that we allow loopback DNS addresses to be used as targets for > forwarding, we need to check if DNS answers come from those targets, > before deciding to eventually remap traffic for local redirects. > > Otherwise, the source address won't match the one configured as > forwarder, which means that the guest or the container will refuse > those responses. > > Signed-off-by: Stefano Brivio > --- > udp.c | 17 ++++++++--------- > 1 file changed, 8 insertions(+), 9 deletions(-) > > diff --git a/udp.c b/udp.c > index 4b201d3..7c77e09 100644 > --- a/udp.c > +++ b/udp.c > @@ -680,8 +680,10 @@ static void udp_sock_fill_data_v4(const struct ctx *c, int n, > src = ntohl(b->s_in.sin_addr.s_addr); > src_port = ntohs(b->s_in.sin_port); > > - if (src >> IN_CLASSA_NSHIFT == IN_LOOPBACKNET || > - src == INADDR_ANY || src == ntohl(c->ip4.addr_seen)) { > + if (c->ip4.dns_fwd && src == htonl(c->ip4.dns[0]) && src_port == 53) { I guess this is not a newly introduced bug, but for the case of multiple host nameservers, don't you need to check against everything in the ip4.dns[] array, not just entry 0? > + b->iph.saddr = c->ip4.dns_fwd; > + } else if (IPV4_IS_LOOPBACK(src) || src == INADDR_ANY || > + src == ntohl(c->ip4.addr_seen)) { > b->iph.saddr = c->ip4.gw; > udp_tap_map[V4][src_port].ts = now->tv_sec; > udp_tap_map[V4][src_port].flags |= PORT_LOCAL; > @@ -692,9 +694,6 @@ static void udp_sock_fill_data_v4(const struct ctx *c, int n, > udp_tap_map[V4][src_port].flags |= PORT_LOOPBACK; > > bitmap_set(udp_act[V4][UDP_ACT_TAP], src_port); > - } else if (c->ip4.dns_fwd && > - src == htonl(c->ip4.dns[0]) && src_port == 53) { > - b->iph.saddr = c->ip4.dns_fwd; > } else { > b->iph.saddr = b->s_in.sin_addr.s_addr; > } > @@ -770,6 +769,10 @@ static void udp_sock_fill_data_v6(const struct ctx *c, int n, > if (IN6_IS_ADDR_LINKLOCAL(src)) { > b->ip6h.daddr = c->ip6.addr_ll_seen; > b->ip6h.saddr = b->s_in6.sin6_addr; > + } else if (!IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns_fwd) && > + IN6_ARE_ADDR_EQUAL(src, &c->ip6.dns[0]) && src_port == 53) { > + b->ip6h.daddr = c->ip6.addr_seen; > + b->ip6h.saddr = c->ip6.dns_fwd; > } else if (IN6_IS_ADDR_LOOPBACK(src) || > IN6_ARE_ADDR_EQUAL(src, &c->ip6.addr_seen) || > IN6_ARE_ADDR_EQUAL(src, &c->ip6.addr)) { > @@ -794,10 +797,6 @@ static void udp_sock_fill_data_v6(const struct ctx *c, int n, > udp_tap_map[V6][src_port].flags &= ~PORT_GUA; > > bitmap_set(udp_act[V6][UDP_ACT_TAP], src_port); > - } else if (!IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns_fwd) && > - IN6_ARE_ADDR_EQUAL(src, &c->ip6.dns[0]) && src_port == 53) { > - b->ip6h.daddr = c->ip6.addr_seen; > - b->ip6h.saddr = c->ip6.dns_fwd; > } else { > b->ip6h.daddr = c->ip6.addr_seen; > b->ip6h.saddr = b->s_in6.sin6_addr; -- David Gibson | 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