So after some more work and thinking, I found a site that reminded me why I have rules 1 and 2. And, surprise, I was using them wrong. Here’s my current setup:
0 ;;; defconf: masquerade
chain=srcnat action=masquerade out-interface-list=WAN ipsec-policy=out,none
1 ;;; Rewrite DNS lookups UDP
chain=srcnat action=masquerade to-ports=53 protocol=udp dst-address=10.1.0.2 dst-port=53 log=yes log-prefix=""
2 ;;; Rewrite DNS lookups TCP
chain=srcnat action=masquerade to-ports=53 protocol=tcp dst-address=10.1.0.2 dst-port=53 log=no log-prefix=""
3 ;;; DNS Redirect UDP
chain=dstnat action=dst-nat to-addresses=10.1.0.2 to-ports=53 protocol=udp src-address=!10.1.0.2/31 dst-port=53
log=yes log-prefix=""
4 ;;; DNS Redirect TCP
chain=dstnat action=dst-nat to-addresses=10.1.0.2 to-ports=53 protocol=tcp src-address=!10.1.0.2/31 dst-port=53
log=no log-prefix=""
This site: https://jeff.vtkellers.com/posts/technology/force-all-dns-queries-through-pihole-with-openwrt/
Is where I remembered I needed rules 1/2 for helping to fool client devices into thinking their DNS server choice was what actually responded.
And, this seems to kind of work. However, it’s intermittent. Sometimes dig is getting a timeout, sometimes it goes through instantly. Here’s a log for those rules.
In this example, the first one responded in 0ms. Then ran dig immediatly again and got 3 timeouts.
2025-05-04 16:48:46 firewall,info dstnat: in:bridge out:(unknown 0), connection-state:new src-mac 55:4a:a4:fc:88:1b, proto UDP, 10.1.0.20:54910->1.2.3.4:53, len 84
2025-05-04 16:48:46 firewall,info srcnat: in:bridge out:bridge, connection-state:new,dnat src-mac 55:4a:a4:fc:88:1b, proto UDP, 10.1.0.20:54910->10.1.0.2:53, NAT 10.1.0.20:54910->(1.2.3.4:53->10.1.0.2:53), len 84
2025-05-04 16:48:59 firewall,info dstnat: in:bridge out:(unknown 0), connection-state:new src-mac 55:4a:a4:fc:88:1b, proto UDP, 10.1.0.20:37091->1.2.3.4:53, len 84
2025-05-04 16:48:59 firewall,info srcnat: in:bridge out:bridge, connection-state:new,dnat src-mac 55:4a:a4:fc:88:1b, proto UDP, 10.1.0.20:37091->10.1.0.2:53, NAT 10.1.0.20:37091->(1.2.3.4:53->10.1.0.2:53), len 84
2025-05-04 16:49:04 firewall,info dstnat: in:bridge out:(unknown 0), connection-state:new src-mac 55:4a:a4:fc:88:1b, proto UDP, 10.1.0.20:38934->1.2.3.4:53, len 84
2025-05-04 16:49:04 firewall,info srcnat: in:bridge out:bridge, connection-state:new,dnat src-mac 55:4a:a4:fc:88:1b, proto UDP, 10.1.0.20:38934->10.1.0.2:53, NAT 10.1.0.20:38934->(1.2.3.4:53->10.1.0.2:53), len 84
2025-05-04 16:49:09 firewall,info dstnat: in:bridge out:(unknown 0), connection-state:new src-mac 55:4a:a4:fc:88:1b, proto UDP, 10.1.0.20:58143->1.2.3.4:53, len 84
2025-05-04 16:49:09 firewall,info srcnat: in:bridge out:bridge, connection-state:new,dnat src-mac 55:4a:a4:fc:88:1b, proto UDP, 10.1.0.20:58143->10.1.0.2:53, NAT 10.1.0.20:58143->(1.2.3.4:53->10.1.0.2:53), len 84