Forcing all DNS traffic from the LAN to the firewall

Continuing the discussion from URL filter for HTTPS:

Hello - I am trying to redirect all of my DNS traffic to go thru the IPFire DNS instead of directly to an outside DNS server. I am able to successfully block DNS traffic with this:
Force clients to use IPFire’s DNS proxy - Option 2. Block all DNS traffic except through IPFire’s DNS proxy

But this is not what I want. I’d rather redirect it.

I found this method here offered by Andreas @troll-op :
URL filter for HTTPS

vi /etc/sysconfig/firewall.local

#Force DNS for green to query the firewall, and not an outside DNS server
iptables -t nat -A CUSTOMPREROUTING ! -o green0 -p udp --destination-port 53 -j REDIRECT --to-ports 53
iptables -t nat -A CUSTOMPREROUTING ! -o green0 -p tcp --destination-port 53 -j REDIRECT --to-ports 53

But as best as I can tell it is not working as hoped. I’ve been testing it with nslooked and dig but either my rule doesn’t work or my test is not working.

Yes, I’ve RTFM many times but it didnt help. And I’ve searched thru the various examples here in the Community.

And I did find the web gui issue on bugzilla #11168 and I understand I cannot use the IPFire web gui to create the firewall rule. For today I need to use iptables.

FYI - I did try Matthias’ example in Comment #6 and that didnt seem to work either.

so right now I am blaming my testing more than anything else. How to I determine if my firewall rule is being redirected to my IPFire DNS versus going to an outside internet DNS??

1 Like

the switch ! -o (output) is not available in the PREROUTING chain. Try -i instead. (Without the negation. Maybee you need also rule for blue and orange.

Howzit Jon

When you do a
iptables -nvL -t nat

What is the output on CUSTOMPREROUTING? And does port 53 show up anywhere else?

Just out of interest sake…
These are the rules I have in my
/etc/sysconfig/firewall.local`

	## add your 'start' rules here
	# Force DNS for green to query the firewall, and not an outside DNS server
	/sbin/iptables -t nat -A CUSTOMPREROUTING ! -o green0 -p udp --destination-port 53 -j REDIRECT --to-ports 53
	/sbin/iptables -t nat -A CUSTOMPREROUTING ! -o green0 -p tcp --destination-port 53 -j REDIRECT --to-ports 53
	/sbin/iptables -t nat -A CUSTOMPREROUTING ! -o green0 -p udp --destination-port 853 -j REDIRECT --to-ports 853
	/sbin/iptables -t nat -A CUSTOMPREROUTING ! -o green0 -p tcp --destination-port 853 -j REDIRECT --to-ports 853
	
	## add your 'stop' rules here
	# DNS ReDirect flushing related chains
	/sbin/iptables -t nat -F CUSTOMPREROUTING

In the GUI FW side I also have entries permitting UDP&TCP traffic on ports 53 and 853.
These are however firewall rules, and not NAT rules.

I know they work, because on my LAN external DNS replies or results change when I change the DNS server I use to resolve things with on the FW.
For example, instead of 8.8.8.8 change it to 185.228.168.10 or 185.228.168.168 (currently the server uses DNS over TLS, but that does not make a difference to the results below).

From a workstation on that network, check that you have another DNS server as the primary DNS entry. I for example set 8.8.8.8, no secondary DNS, and this is the result from the command prompt.

C:\Users\andi>nslookup google.com
Server:  dns.google
Address:  8.8.8.8

Non-authoritative answer:
Name:    google.com
Addresses:  2a00:1450:4001:801::200e
          172.217.170.78


C:\Users\andi>nslookup pornhub.com
Server:  dns.google
Address:  8.8.8.8

DNS request timed out.
    timeout was 2 seconds.
DNS request timed out.
    timeout was 2 seconds.
DNS request timed out.
    timeout was 2 seconds.
*** dns.google can't find pornhub.com: Server failed

As far as the workstation is concerned it is talking to 8.8.8.8 ias its DNS server, it does not know that the FW has a routing table entry that redirects the request to itself. The FW is currently using 185.228.168.10 and 185.228.168.11 as it’s source. Those two IP belong to Cleanbrowsing and have an Adult Filter on it. This means no xxx sites are accessible.

If your results differ, then you may have something else in the FW rules, causing a problem.
There won’t be any FW log entries, just in case you were wondering about it.

Hope this shines a bit more light on the matter.

cheers

UPDATE: Just a note on the -o versus -i

  • -i is for the name of an interface via which a packet was received. As the request from the workstation may not be directed at the FW, but an external DNS server this entry would be mute. Otherwise you would need an entry for every DNS server that could be used.
  • -o is the name of an interface via which a packet is going to be sent or forward to.
    As we are not trying to modify packets, and don’t know the destination IP, but do know on which protocols those packets will be send, we want to redirect only that traffic to another machine the -o is the correct use.

    I have seen the errors of my ways :slight_smile:

DNS is usually UDP, but can also be done via TCP so you would need to have an entry for both on port 53.
DNS over TLS and DNS over HTTPS (shudder) are most likely not used by workstations directly, but if you want to prevent that add port 853 as well.

DNS over HTTPS would indicate the the queries go via 443, but that’s a misnomer. The client hopes that the DoH server will do the right thing, it however still sends out queries via UDP/53 or TCP/53, or 853.

1 Like

Forgot to mention, once you have edited the firewall.local you need to reload it or restart your FW, otherwise those NAT entries or any other changes won’t do Jack… don’t know Jack so don’t go near him. Apparently he is always on the road.

/etc/sysconfig/firewall.local reload

something just dawned on me… Does the web proxy need to be in non-transparent mode? Or is Transparent ok and it doesn’t matter??

 


@arne_f - I’ll give the -i a try without the negation. (also, I removed the blue and orange rules just for testing.)

@troll-op - I’ll gather some info and be back!

The proxy doesn’t matter. Your DNS queries don’t get send to it, only http traffic is.

After re-reading that :arrow_double_up: i think i may be confusing myself and probably everyone else with that explanation

Let me try again… using the -i and -o
The -i is for the interface we will receive information on.
The -o is for the interface we want to send information on.

We don’t want the traffic, in this case DNS requests, to go out directly but only via our DNS server. This means that the we need to control the outgoing traffic. This makes -i unimportant for the NAT redirect rule.
After all the return path or receiving takes care of itself. The FW will send the request to the predefined DNS server, get the responses back, and then pass it on to the workstation. The workstation is non the wiser that the FW changed the DNS server that the request was send to. It after all was expecting the FW to pass on the information, and was expecting the info back from it.

If we forward the requests we would be implementing filtering, gut feel tells me more resources are used, doing a routing table is more elegant.

I think that explanation may be a bit clearer… at least this time even I understood what I said… which is a bonus… doesn’t happen often :laughing:
How wrong I was hahaha

1 Like

This is my firewall.local:

...
iptables -vt nat -A CUSTOMPREROUTING ! -o green0 -p udp --destination-port 53 -j REDIRECT --to-ports 53
iptables -vt nat -A CUSTOMPREROUTING ! -o green0 -p tcp --destination-port 53 -j REDIRECT --to-ports 53
...

 
and this is what I see:

[root@ipfire ~]# iptables -nvL -t nat | grep -A5 -B1 CUSTOMPREROUTING

 pkts bytes target     prot opt in     out     source               destination         
 275K   23M CUSTOMPREROUTING  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
--
Chain CUSTOMPREROUTING (1 references)
 pkts bytes target     prot opt in     out     source               destination         
  377 30604 LOG        all  --  *      *       0.0.0.0/0            0.0.0.0/0            limit: avg 2/sec burst 5 LOG flags 0 level 4 prefix "CUSTOMPREROUTING "
  269 18495 REDIRECT   udp  --  *      !green0  0.0.0.0/0            0.0.0.0/0            udp dpt:53 redir ports 53
    0     0 REDIRECT   tcp  --  *      !green0  0.0.0.0/0            0.0.0.0/0            tcp dpt:53 redir ports 53

 

nslookup results:

iMac:~ jon$ networksetup -getdnsservers Ethernet
192.168.60.1

iMac:~ jon$ nslookup google.com
Server:		192.168.60.1
Address:	192.168.60.1#53

Non-authoritative answer:
Name:	google.com
Address: 172.217.9.78

iMac:~ jon$ nslookup google.com 8.8.8.8
Server:		8.8.8.8
Address:	8.8.8.8#53

Non-authoritative answer:
Name:	google.com
Address: 172.217.9.78

 

All webgui firewall rules are turned off for this testing. The only firewall rule I have running is this one to redirect DNS.

PS - “Don’t know Jack” is my middle name!

 


TL;DR - For completeness:

  • This is my DHCP configuration:


 

  • And my DNS:

I changed the firewall Domain Name System to the Cleanbrowsing DoT servers. And it works the same as yours. So it appears my testing in wrong.

iMac:~ jon$ nslookup google.com
Server:		192.168.60.1
Address:	192.168.60.1#53

Non-authoritative answer:
Name:	google.com
Address: 216.58.192.142

iMac:~ jon$ nslookup pornhub.com
Server:		192.168.60.1
Address:	192.168.60.1#53

** server can't find pornhub.com: SERVFAIL

iMac:~ jon$ nslookup pornhub.com 8.8.8.8
Server:		8.8.8.8
Address:	8.8.8.8#53

** server can't find pornhub.com: SERVFAIL

If my DNS server is set to quad9 (9.9.9.9) or giggle (8.8.8.8), how do I know my firewall rule is working??

Everything looks right… except the nslookup from the iMac.
How do you know that the request was being redirected ?

Hence my suggestion to use a DNS on the firewall that will block something like adult sites.
Before a redirect pornhub would resolve to IP xyz, after the redirect and using the Cleanbrowsing DNS, it should either time out like it did on the Windows machine or you should get something like

$ nslookup kindgirls.com
;; Got SERVFAIL reply from 8.8.8.8, trying next server
Server:		8.8.8.8
Address:	8.8.8.8#53

** server can't find kindgirls.com: NXDOMAIN

This is the response I get when I enable the NAT redirect, and use 185.228.168.10 as the DNS server on the FW. My Mac still thinks it is using 8.8.8.8.

With the redirect FW entry flushed, I have the following result.

$ nslookup kindgirls.com
Server:		8.8.8.8
Address:	8.8.8.8#53

Non-authoritative answer:
Name:	kindgirls.com
Address: 91.192.108.32

Based on this I know that the DNS requests are intercepted and forced to talk to my FW. And the FW will use which ever DNS server I have told it to use in the Domain Name System entry, or recursive if none are entered.

This would give you real live results… I’m not sure how else you would be able to test it, there are no log entries as far as I remember. I guess you could do a

tcpdump dst port 53
or
tcpdump -i green0 -s0 port 53
or if you really want to know everything and go total overboard
tcpdump -i green0 -nn -s0 -v port 53

That would give you geek speak info :slight_smile:

Btw the DHCP DNS is all nice and well, but a user can change that entry manually on their machine. The redirect rule, however won’t care if they do, and force them to use your DNS no matter what they have there. The only way to bypass this is if they use a VPN and push all their request over that. At which point I go, there is only so much stupidity I can protect users from, anything more and HR (my wife in the case of the kids) can deal with it.

UPDATE: Just noticed you add the second entry, so the above is mute. Except for those that like reading geeky things late at night hahahaha
Happy you all sorted. Have a nice evening.
Cheers

The ** server can't find pornhub.com: SERVFAIL indicates that the redirect is working, and the Adult filter DNS server is doing its job.
That means you can now change the firewall Domain Name System to whatever you want and the redirect will use those. The workstations will not know the difference. As far as it is concerned it is sending the DNS request to which ever DNS it has configured.

That is my million dollar question!

I’ll give tcpdump a try. It has been a very long time since I used it last!

This is what I want! I am using the DNS redirect for IoT devices that seem to have a hardcoded DNS setting (one I cannot change).

Nope, we already have the answer. Your settings are correct and working.

This will let the IoT think it is using a DNS it is not. Basically anything inside the LAN is a mushroom :smiley:

The FW will decide what DNS server to talk to and hand back the results, or in case of the Adult filter not. That way the URL filters (which can be bypassed) become mute and mostly decoration. A machine cannot connect to what it cannot find. Only problem in that case are IP based sites, but that can be dropped on the proxy. Or you could be like me an create IPset blocklists… but that’s a different topic.

Last post! Yes it seems to work. And thank you for all of your help!

I just wanted to prove it with quad9 or giggle DNS. So I gave tcpdump a try but it doesn’t seem to show what I expect!

Here is my 1st nslookup:

iMac:~ jon$ nslookup google.com 8.8.8.8
Server:		8.8.8.8
Address:	8.8.8.8#53

Non-authoritative answer:
Name:	google.com
Address: 216.58.192.142

And here is my 1st tcpdump:

[root@ipfire ~]# tcpdump host 192.168.60.105 and port 53 -nn -s0 -v

tcpdump: listening on green0, link-type EN10MB (Ethernet), capture size 262144 bytes
14:30:48.716484 IP (tos 0x0, ttl 64, id 20107, offset 0, flags [none], proto UDP (17), length 56)
    192.168.60.105.54371 > 8.8.8.8.53: 34122+ A? google.com. (28)
14:30:48.716801 IP (tos 0x0, ttl 64, id 22354, offset 0, flags [none], proto UDP (17), length 72)
    8.8.8.8.53 > 192.168.60.105.54371: 34122 1/0/0 google.com. A 216.58.192.142 (44)

 

And here is another nslookup:

iMac:~ jon$ nslookup pornhub.com 8.8.8.8
Server:		8.8.8.8
Address:	8.8.8.8#53

** server can't find pornhub.com: SERVFAIL

And here is another tcpdump:

[root@ipfire ~]# tcpdump host 192.168.60.105 and port 53 -nn -s0 -v

tcpdump: listening on green0, link-type EN10MB (Ethernet), capture size 262144 bytes
14:37:55.909626 IP (tos 0x0, ttl 64, id 37554, offset 0, flags [none], proto UDP (17), length 57)
    192.168.60.105.62945 > 8.8.8.8.53: 41925+ A? pornhub.com. (29)
14:37:55.910241 IP (tos 0x0, ttl 64, id 13877, offset 0, flags [none], proto UDP (17), length 57)
    8.8.8.8.53 > 192.168.60.105.62945: 41925 ServFail 0/0/0 (29)

 

It seems to read as if the DNS lookup happened via 8.8.8.8.

Yes thats because you are looking at what the 192.168.60.105 machine is doing. I take it that is your workstation you and not the FW.
Ofcourse it will show you it is happily talking to 8.8.8.8 because it doesn’t know that the redirect is happening. Change that to show what the FW is doing. You should see the requests coming in for 8.8.8.8 and then what it does with it… or at least i think it should show you this info.

I have a feeling FW are like women, they don’t tell you much unless you ask the right questions… nicely :slight_smile:

UPDATE:
Hang ten just read the SERVFAIL, that means you are using the adult filter DNS still on the FW. So working… but yes either change the host to the FW, or better yet, do a -i green0 instead, and it will give you all 53 traffic.

Yes, 192.168.60.105 is my workstation (my Mac). And 192.168.60.1 is the IPFire firewall.

The tcpdump program is running on the FW.

I ran tcpdump with -i green and got a flood of info. No references to Cleanbrowsing DNS or the IP addresses for Cleanbrowsing (185.228.168.10 or 185.228.168.11).

Here is my 1st nslookup:

iMac:~ jon$ nslookup pornhub.com 8.8.8.8
Server:		8.8.8.8
Address:	8.8.8.8#53

** server can't find pornhub.com: SERVFAIL

And here is my 1st tcpdump:

[root@ipfire ~]# tcpdump -i green0 -nn -s0 -v port 53

tcpdump: listening on green0, link-type EN10MB (Ethernet), capture size 262144 bytes
...
15:31:54.962288 IP (tos 0x0, ttl 64, id 60016, offset 0, flags [none], proto UDP (17), length 57)
    192.168.60.105.53944 > 8.8.8.8.53: 29334+ A? pornhub.com. (29)
15:31:55.542069 IP (tos 0x0, ttl 64, id 62210, offset 0, flags [none], proto UDP (17), length 57)
    8.8.8.8.53 > 192.168.60.105.53944: 29334 ServFail 0/0/0 (29)

Still looks like the response is from 8.8.8.8:53

I happened to capture one of the IoT devices talking to other DNS servers. The IoT device talks with four DNS servers. Tcpdump captured two of them.

15:51:36.333540 IP (tos 0x0, ttl 64, id 53679, offset 0, flags [DF], proto UDP (17), length 56)
    192.168.60.74.59863 > 192.168.60.1.53: 35394+ A? google.com. (28)

15:51:36.333697 IP (tos 0x0, ttl 64, id 29567, offset 0, flags [none], proto UDP (17), length 72)
    192.168.60.1.53 > 192.168.60.74.59863: 35394 1/0/0 google.com. A 216.58.192.142 (44)

15:51:36.334324 IP (tos 0x0, ttl 64, id 53680, offset 0, flags [DF], proto UDP (17), length 59)
    192.168.60.74.48140 > 192.168.60.1.53: 35395+ A? microsoft.com. (31)

15:51:36.334425 IP (tos 0x0, ttl 64, id 29568, offset 0, flags [none], proto UDP (17), length 139)
    192.168.60.1.53 > 192.168.60.74.48140: 35395 5/0/0 microsoft.com. A 104.215.148.63, microsoft.com. A 40.112.72.205, microsoft.com. A 40.113.200.201, microsoft.com. A 13.77.161.179, microsoft.com. A 40.76.4.15 (111)

I wish this was a built in firewall rule. check box.

2 Likes

:+1: :+1:

I did give the -i a try and it worked A-OK. (just like the ! -o)

So this works:

iptables -t nat -A CUSTOMPREROUTING ! -o green0 -p udp --destination-port 53 -j REDIRECT --to-ports 53

 

and this works:

iptables -t nat -A CUSTOMPREROUTING -i green0 -p udp --destination-port 53 -j REDIRECT --to-ports 53

 

I did not notice any functionality difference. For the 1st code block above I am guessing ! -o green will ignore anything that was sent from green. But it will accept anything sent from red, orange, blue. Does this sound right? Close? Maybe?

And for the 2nd code block -i green0 will allow anything sent to green. But ignore anything send to red, orange, blue. Does this sound right?

So why would you need/want the 1st and not the second?!?

I found this after LOTS of searching!

Help us Matthias @mfischer, you are our only hope!


German reference (sorry!):

just to finish this off…

  1. I downloaded an empty firewall.local:

    https://github.com/ipfire/ipfire-2.x/blob/master/src/initscripts/sysconfig/firewall.local

  2. I added the dns redirect rules I needed (for green network in my case).

    • The login entries are commented out. Feel free to remove their comment # but it produces lots of log entries in the /var/log/messages file.
#!/bin/sh
# Used for private firewall rules

# See how we were called.
case "$1" in
  start)
        ## add your 'start' rules here
        #iptables -t nat -A CUSTOMPREROUTING -i green0 -p udp -m udp --dport 53 -m limit --limit 10/sec --limit-burst 20 -j LOG --log-prefix "CUSTOMPREROUTING "
        iptables -t nat -A CUSTOMPREROUTING -i green0 -p udp -m udp --dport 53 -j REDIRECT --to-ports 53
        #iptables -t nat -A CUSTOMPREROUTING -i green0 -p tcp -m tcp --dport 53 -m limit --limit 10/sec --limit-burst 20 -j LOG --log-prefix "CUSTOMPREROUTING "
        iptables -t nat -A CUSTOMPREROUTING -i green0 -p tcp -m tcp --dport 53 -j REDIRECT --to-ports 53
        ;;
  stop)
        ## add your 'stop' rules here
        #iptables -t nat -D CUSTOMPREROUTING -i green0 -p udp -m udp --dport 53 -m limit --limit 10/sec --limit-burst 20 -j LOG --log-prefix "CUSTOMPREROUTING "
        iptables -t nat -D CUSTOMPREROUTING -i green0 -p udp -m udp --dport 53 -j REDIRECT --to-ports 53
        #iptables -t nat -D CUSTOMPREROUTING -i green0 -p tcp -m tcp --dport 53 -m limit --limit 10/sec --limit-burst 20 -j LOG --log-prefix "CUSTOMPREROUTING "
        iptables -t nat -D CUSTOMPREROUTING -i green0 -p tcp -m tcp --dport 53 -j REDIRECT --to-ports 53
        ;;
  reload)
        $0 stop
        $0 start
        ## add your 'reload' rules here
        ;;
  flush)
        iptables -t nat -F CUSTOMPREROUTING
        ;;        
  *)
        echo "Usage: $0 {start|stop|reload}"
        ;;
esac
  1. Make the firewall.local executable:
chmod +x /etc/sysconfig/firewall.local
  1. If running the first time enter:
/etc/sysconfig/firewall.local start

What to see if anything is happening?

  1. view menu Firewall > iptables
  2. scroll down to IPTable Network Address Translation, click CUSTOMPREROUTING and click Update
  3. you should see the pkts / bytes changing

-or-

  1. view menu Status > Connections
  2. scroll thru looking for port 53 destination
  3. you should see a redirect!

Hope this helps!