Solved Redirect outgoing DNS and NTP requests back to my home router

Hi,

I've just finished setting up my FreeBSD router and it's been a very fun project! I've learned a lot about DHCP, NTP, DNS and specially pf! There's just a couple of rules that I can't understand why they aren't working:
Code:
# redirect dns
rdr pass log on $int_if proto { udp, tcp } from any to ! 192.168.1.1 port domain -> 192.168.1.1 port domain
Code:
# redirect ntp
rdr pass log on $int_if proto udp from any to ! 192.168.1.1 port ntp -> 192.168.1.1 port ntp

When I hardcode 8.8.8.8 on my desktop for example, and run a test via https://www.dnsleaktest.com/, I get that I'm using Google :p

For anyone that's interested in setting up a router for your home, here's my full pf.conf
Code:
# read the log file: tcpdump -n -e -ttt -r /var/log/pflog
# real-time logging: tcpdump -neq -ttt -i pflog0
#                    tcpdump -nettti pflog0 action drop
#### macros
ext_if = "ng0"
int_if = "igb1"
localnet = $int_if:network
icmp_types = "{ echoreq unreach }"
#### tables
table <rfc6890> { 0.0.0.0/8 10.0.0.0/8 100.64.0.0/10 127.0.0.0/8 169.254.0.0/16          \
                  172.16.0.0/12 192.0.0.0/24 192.0.0.0/29 192.0.2.0/24 192.88.99.0/24    \
                  192.168.0.0/16 198.18.0.0/15 198.51.100.0/24 203.0.113.0/24            \
                  240.0.0.0/4 255.255.255.255/32 }
#### options
set block-policy drop
set skip on lo
#### normalization
scrub in log all fragment reassemble no-df max-mss 1440
#### queueing
#### translation
nat on $ext_if from $localnet to any -> ($ext_if)
# redirect ssh
rdr pass log on $ext_if proto tcp from any to any port 4242 -> 192.168.1.1 port ssh
# redirect dns
rdr pass log on $int_if proto { udp, tcp } from any to ! 192.168.1.1 port domain -> 192.168.1.1 port domain
# redirect ntp
rdr pass log on $int_if proto udp from any to ! 192.168.1.1 port ntp -> 192.168.1.1 port ntp
#### packet filtering
# anti spoofing
antispoof log quick for $ext_if
antispoof log quick for $int_if
# block rfc6890
block in log quick on $ext_if from <rfc6890>
block return out log quick on egress to <rfc6890>
# block all the rest
block log all
# allow traffic to internet
pass out quick inet
# allow internal LAN traffic
pass in on $int_if inet
#### packet filtering overrides
# allow ICMP and traceroute
pass inet proto icmp all icmp-type $icmp_types keep state
pass out on $ext_if inet proto udp from any to any port 33433 >< 33626 keep state

It's nothing fancy, but I'm running a local NTP server, Unbound, dhcpd, and a simple script for dynamic dns to help me maintain remote access to my SSH service, and it's using ssh-key only auth.

But back to topic, if anyone could please help me with those two redirect rules it would be great!

Thanks in advance for any help!
 
Try this instead:
Code:
# redirect dns
rdr pass log on $int_if proto { udp, tcp } from any to ! 192.168.1.1 port domain -> 127.0.0.1 port domain

You were trying to redirect to the same interface the traffic came in on, that's not going to work.
 
# redirect dns rdr pass log on $int_if proto { udp, tcp } from any to ! 192.168.1.1 port domain -> 192.168.1.1 port domain
Clients can easily detect the fake DNS because they will get a (unexpected) response from an address they did not send the request to. You would probably have to use binat rules to solve this problem, but then again binat rules do not support port numbers, so you'd have to redirect all traffic to a particular IP address, like 8.8.8.8 / 8.8.4.4.
 
Also keep in mind that Firefox and a few other browsers might use DoH, circumventing your DNS settings entirely.
 
Hi!

Try this instead:
Code:
# redirect dns
rdr pass log on $int_if proto { udp, tcp } from any to ! 192.168.1.1 port domain -> 127.0.0.1 port domain

Nope, it doesn't work unfortunately. Maybe there's a rule overriding it?

About the DoH, I'm already using Unbound to block common DoH domains via a list I've found on Github, and I pretend to block them via IP with when I understand PF better :p. But I understand it's a whack-a-mole thing :(

Edit: It works, just needed to reboot Windows, :p
 
Maybe there's a rule overriding it?
You used rdr pass, that automatically passed the traffic and ignores all other filter rules.

Code:
     If the pass modifier is given, packets matching the translation rule are
     passed without inspecting the filter rules:
pf.conf(5)
 
You're right, it works! I just needed to reboot my desktop, I guess the states table still had a connection or something like that! Thank you so much!
 
No need to reboot to flush the states, pfctl -f /etc/pf.conf -F all. Don't do this if you're working remotely though, it will kill your remote connection too.

Code:
     -F modifier
             Flush the filter parameters specified by modifier (may be
             abbreviated):

             -F nat        Flush the NAT rules.
             -F queue      Flush the queue rules.
             -F rules      Flush the filter rules.
             -F states     Flush the state table (NAT and filter).
             -F Sources    Flush the source tracking table.
             -F info       Flush the filter information (statistics that are
                           not bound to rules).
             -F Tables     Flush the tables.
             -F osfp       Flush the passive operating system fingerprints.
             -F all        Flush all of the above.
From pfctl(8).
 
Clients can easily detect the fake DNS because they will get a (unexpected) response from an address they did not send the request to. You would probably have to use binat rules to solve this problem, but then again binat rules do not support port numbers, so you'd have to redirect all traffic to a particular IP address, like 8.8.8.8 / 8.8.4.4.
You can easily fix the issue by adding an option to unbound.conf:

Code:
interface-automatic: yes

By doing that Unbound will use destination IP address of query as source IP address for reply.

Dnsmasq is supporting the same feature too.
 
Also keep in mind that Firefox and a few other browsers might use DoH, circumventing your DNS settings entirely.
block 53 port access and only allow that port access to your dns server

SirDice , It's true, and somethimes DoH come enabled by default
is a pain in the a$%
 
Back
Top