big hammer to get ip-transparent working with pf divert-to rules on obsd.

if you divert all dns requests to an unbound server, this sets
things up so replies to diverted udp requests come from what looks
like the right IP.

set_recvpktinfo() needs to be called on listening sockets so the
kernel will wire up the control messages that include the original
destination ip address of the packet.

comm_point_create_udp_ancil() needs to be used instead of
comm_point_create_udp() so it will use recvmsg with a control message
buffer and process the CMSGs inside it.

for IP_SENDSRCMSG to work when sending the replies to the diverted
client, the listening socket also has to be set up with the SO_BINDANY
sockopt.
This commit is contained in:
David Gwynne 2023-08-17 13:22:28 +10:00
parent d4145772b5
commit feb101bc70

View file

@ -1297,6 +1297,13 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
if (sock_queue_timeout && !set_recvtimestamp(s)) {
log_warn("socket timestamping is not available");
}
/* getting source addr packet info is highly non-portable */
if(!set_recvpktinfo(s, hints->ai_family)) {
sock_close(s);
freeaddrinfo(ub_sock->addr);
free(ub_sock);
return 0;
}
if(!port_insert(list, s, is_dnscrypt
?listen_type_udpancil_dnscrypt:listen_type_udpancil,
is_pp2, ub_sock)) {
@ -1454,7 +1461,7 @@ listen_create(struct comm_base* base, struct listen_port* ports,
struct comm_point* cp = NULL;
if(ports->ftype == listen_type_udp ||
ports->ftype == listen_type_udp_dnscrypt) {
cp = comm_point_create_udp(base, ports->fd,
cp = comm_point_create_udp_ancil(base, ports->fd,
front->udp_buff, ports->pp2_enabled, cb,
cb_arg, ports->socket);
} else if(ports->ftype == listen_type_tcp ||