Solved Redirecting DNS requests

I am trying to recreate a rule that I have previously used with iptables in Linux. I would like the firewall to take outbound DNS requests and redirect them to the DNS server of my choosing. I am learning pf and cannot recreate this functionality.

I do realize that the alternative way to do this is to just the DNS on host machines to 8.8.8.8, but that is not my goal.

In iptables I had a rule like this:
Code:
iptables -t nat -A PREROUTING -p udp --dport 53 -j DNAT --to 8.8.8.8

In pf my attempts were:
#1 the firewall in this example is just a test machine, so this machine itself is making the dns requests. ue0 is the firewall host.
Code:
rdr on ue0 proto udp from ue0 to port 53 -> 8.8.8.8 port 53
#2 more generic
Code:
rdr proto udp to port 53 -> 8.8.8.8 53

I ran tcpdump -i ue0 -n port 53 to monitor DNS traffic as I did queries using host somewebsite.com. Unfortunately DNS request are not being redirected to 8.8.8.8 as they do on my Linux/iptables setup.

Questions
1. Am I simply using an incorrect rule? Does pf have what is equivalent to the PREROUTING when it comes to rules?
2. Is there an equivalent to iptables -nvL for pf that would let me monitor my rules and get a numbered increment when my rule is actually being matched and used?
 
Are you doing this on the host itself? Or from some other host in the same network? If it's the later it's probably never going to work:
Code:
     Translation rules apply only to packets that pass through the specified
     interface, and if no interface is specified, translation is applied to
     packets on all interfaces.  For instance, redirecting port 80 on an
     external interface to an internal web server will only work for connec-
     tions originating from the outside.  Connections to the address of the
     external interface from local hosts will not be redirected, since such
     packets do not actually pass through the external interface.  [b]Redirec-
     tions cannot reflect packets back through the interface they arrive on,
     they can only be redirected to hosts connected to different interfaces or
     to the firewall itself.[/b]
From pf.conf(5).
 
Are you doing this on the host itself? Or from some other host in the same network? If it's the later it's probably never going to work:
Code:
     Translation rules apply only to packets that pass through the specified
     interface, and if no interface is specified, translation is applied to
     packets on all interfaces.  For instance, redirecting port 80 on an
     external interface to an internal web server will only work for connec-
     tions originating from the outside.  Connections to the address of the
     external interface from local hosts will not be redirected, since such
     packets do not actually pass through the external interface.  Redirec-
     tions cannot reflect packets back through the interface they arrive on,
     they can only be redirected to hosts connected to different interfaces or
     to the firewall itself.
From pf.conf(5).

Yes, I have been trying this on the host itself. After a solid day and night of head banging I finally threw my hands up in defeat. Tomorrow I said I would read the entire man page to make sure I wasn't missing anything. Just before bed I decided to Google one more thing and I found the post below.

PF can not redirect traffic that originates from the host itself because the routing decision for the traffic has been already made by the time it gets to the filter. It's a FreeBSD specific limitation that does not exist on OpenBSD's PF for example.
from Thread redirect.all.local.outbound.traffic.49422

Just as I came to post what I had found in this thread and hopefully see that this information was outdated and incorrect, I see your post. :(

I wonder if there are any plans for FreeBSD for upgrade pf to the version that OpenBSD uses?
 
I wonder if there are any plans for FreeBSD for upgrade pf to the version that OpenBSD uses?
Probably not any time soon. As I understood it FreeBSD's PF code has been heavily modified to make it perform/function better on FreeBSD, the code is now so different it's nothing like the OpenBSD PF code it used to be. So it's not as simple as it sounds.
 
I don't know the specifics but one of the biggest changes was the way it integrated with our network stack. So even a port wouldn't be a simple task.
 
I was just playing around with some jails that I am NAT'ing though a VPN. It seems that seems that FreeBSD sees traffic that is coming from the jailed network on lo1 just the same as traffic coming from the host itself, seemingly placing it with the pf limitation of traffic that cannot be redirected.

The idea being:
I want to prevent DNS requests from leaking
- jail tries to use dns to server 8.8.4.4
- pf redirects this dns request to 8.8.8.8 instead
(note: I am trying to direct it to a specific internal VPN DNS, not Google DNS of course)

Code:
vpn="tun0"
jail="lo1"
vpn_dns="8.8.8.8"

nat on $vpn from $jail:network to any -> ($vpn)
rdr on $jail { tcp udp } from $jail:network to port 53 -> $vpn_dns

I also tried carpet bombing the rdr rule and making a rule for each interface, just in case I overlooked the obvious and set it to the wrong one. I monitored the pflog interface and the DNS traffic would not redirect.
 
I added a second physical NIC to the machine for testing stuff. I was able to get redirection to work since traffic is actually coming into the interface from the outside.


Code:
wan="em0"
lan="re0"
lan_net="$lan:network"

nat log on $wan from $lan_net to any -> $wan
rdr log on $lan proto udp from $lan_net to port 53 -> 8.8.4.4


On the LAN client I run

Code:
host google.com 8.8.8.8

Using tcpdump on pflog on the WAN machine shows that the redirect rules are firing :D
Code:
00:00:00.000000 rule 0..16777216/0(match): rdr in on re0: 172.16.50.20.56598 > 8.8.4.4.53: 46325+ A? google.com. (28)
00:00:00.000013 rule 1..16777216/0(match): nat out on em0: 192.168.0.100.57507 > 8.8.4.4.53: 46325+ A? google.com. (28)
 
Back
Top