From feb101bc70f1176f3bbfdf5261e84928771cbf4e Mon Sep 17 00:00:00 2001 From: David Gwynne Date: Thu, 17 Aug 2023 13:22:28 +1000 Subject: [PATCH] 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. --- services/listen_dnsport.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/services/listen_dnsport.c b/services/listen_dnsport.c index 60f9b41e5..b47f5e8a6 100644 --- a/services/listen_dnsport.c +++ b/services/listen_dnsport.c @@ -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 ||