fwd: Broaden what we consider for DNS specific forwarding rules

passt/pasta has options to redirect DNS requests from the guest to a
different server address on the host side.  Currently, however, only UDP
packets to port 53 are considered "DNS requests".  This ignores DNS
requests over TCP - less common, but certainly possible.  It also ignores
encrypted DNS requests on port 853.

Extend the DNS forwarding logic to handle both of those cases.

Link: https://github.com/containers/podman/issues/23239
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Tested-by: Paul Holzinger <pholzing@redhat.com>
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
This commit is contained in:
David Gibson 2024-07-24 17:51:12 +10:00 committed by Stefano Brivio
parent 0ada84e3f8
commit becf81ab88
2 changed files with 21 additions and 7 deletions

18
fwd.c
View file

@ -156,6 +156,20 @@ void fwd_scan_ports_init(struct ctx *c)
} }
} }
/**
* is_dns_flow() - Determine if flow appears to be a DNS request
* @proto: Protocol (IP L4 protocol number)
* @ini: Flow address information of the initiating side
*
* Return: true if the flow appears to be directed at a dns server, that is a
* TCP or UDP flow to port 53 (domain) or port 853 (domain-s)
*/
static bool is_dns_flow(uint8_t proto, const struct flowside *ini)
{
return ((proto == IPPROTO_UDP) || (proto == IPPROTO_TCP)) &&
((ini->fport == 53) || (ini->fport == 853));
}
/** /**
* fwd_nat_from_tap() - Determine to forward a flow from the tap interface * fwd_nat_from_tap() - Determine to forward a flow from the tap interface
* @c: Execution context * @c: Execution context
@ -169,10 +183,10 @@ void fwd_scan_ports_init(struct ctx *c)
uint8_t fwd_nat_from_tap(const struct ctx *c, uint8_t proto, uint8_t fwd_nat_from_tap(const struct ctx *c, uint8_t proto,
const struct flowside *ini, struct flowside *tgt) const struct flowside *ini, struct flowside *tgt)
{ {
if (proto == IPPROTO_UDP && ini->fport == 53 && if (is_dns_flow(proto, ini) &&
inany_equals4(&ini->faddr, &c->ip4.dns_match)) inany_equals4(&ini->faddr, &c->ip4.dns_match))
tgt->eaddr = inany_from_v4(c->ip4.dns_host); tgt->eaddr = inany_from_v4(c->ip4.dns_host);
else if (proto == IPPROTO_UDP && ini->fport == 53 && else if (is_dns_flow(proto, ini) &&
inany_equals6(&ini->faddr, &c->ip6.dns_match)) inany_equals6(&ini->faddr, &c->ip6.dns_match))
tgt->eaddr.a6 = c->ip6.dns_host; tgt->eaddr.a6 = c->ip6.dns_host;
else if (!c->no_map_gw && inany_equals4(&ini->faddr, &c->ip4.gw)) else if (!c->no_map_gw && inany_equals4(&ini->faddr, &c->ip4.gw))

10
passt.1
View file

@ -244,11 +244,11 @@ usage of DNS addresses altogether.
.TP .TP
.BR \-\-dns-forward " " \fIaddr .BR \-\-dns-forward " " \fIaddr
Map \fIaddr\fR (IPv4 or IPv6) as seen from guest or namespace to the first Map \fIaddr\fR (IPv4 or IPv6) as seen from guest or namespace to the
configured DNS resolver (with corresponding IP version). Mapping is limited to first configured DNS resolver (with corresponding IP version). Maps
UDP traffic directed to port 53, and DNS answers are translated back with a only UDP and TCP traffic to port 53 or port 853. Replies are
reverse mapping. translated back with a reverse mapping. This option can be specified
This option can be specified zero to two times (once for IPv4, once for IPv6). zero to two times (once for IPv4, once for IPv6).
.TP .TP
.BR \-S ", " \-\-search " " \fIlist .BR \-S ", " \-\-search " " \fIlist