What's new

Voxel Help needed with iptables rules

  • SNBForums Code of Conduct

    SNBForums is a community for everyone, no matter what their level of experience.

    Please be tolerant and patient of others, especially newcomers. We are all here to share and learn!

    The rules are simple: Be patient, be nice, be helpful or be gone!

agneev

Occasional Visitor
Currently, I have three rules that redirect all DNS queries to my DNS server:

Code:
iptables -t nat -I PREROUTING -p tcp --dport 53 ! -d 10.0.0.10 -j DNAT --to 10.0.0.10
iptables -t nat -I PREROUTING -p udp --dport 53 ! -d 10.0.0.10 -j DNAT --to 10.0.0.10
iptables -t nat -I POSTROUTING -d 10.0.0.10 -j SNAT --to 10.0.0.1

Now, I'd like to create some exceptions, for e.g. any TCP/UDP port 53 queries to 172.16.1.1 should go to source, instead of being redirected, but only when its made from a particular client.

Also, I want the ability to block all queries to 8.8.8.8 and 8.8.8.8 except those made by the DNS server at 10.0.0.10, if that's possible.
 
Currently, I have three rules that redirect all DNS queries to my DNS server:

Code:
iptables -t nat -I PREROUTING -p tcp --dport 53 ! -d 10.0.0.10 -j DNAT --to 10.0.0.10
iptables -t nat -I PREROUTING -p udp --dport 53 ! -d 10.0.0.10 -j DNAT --to 10.0.0.10
iptables -t nat -I POSTROUTING -d 10.0.0.10 -j SNAT --to 10.0.0.1

Now, I'd like to create some exceptions, for e.g. any TCP/UDP port 53 queries to 172.16.1.1 should go to source, instead of being redirected, but only when its made from a particular client.

Also, I want the ability to block all queries to 8.8.8.8 and 8.8.8.8 except those made by the DNS server at 10.0.0.10, if that's possible.

Maybe something like this? (untested):
Code:
iptables -t nat -I PREROUTING -p tcp --dport 53 ! -d 10.0.0.10,172.16.1.1 -j DNAT --to 10.0.0.10
iptables -t nat -I PREROUTING -p udp --dport 53 ! -d 10.0.0.10,172.16.1.1 -j DNAT --to 10.0.0.10
iptables -t nat -I PREROUTING -p tcp --dport 53 ! -s 10.0.0.10 -d 8.8.8.8 -j DROP
iptables -t nat -I PREROUTING -p udp --dport 53 ! -s 10.0.0.10 -d 8.8.8.8 -j DROP
iptables -t nat -I POSTROUTING -d 10.0.0.10 -j SNAT --to 10.0.0.1
 
Thanks, but I'm getting this:

Code:
~# iptables -t nat -I PREROUTING -p udp --dport 53 ! -s 10.0.0.10 -d 8
.8.8.8 -j DROP
iptables v1.8.7 (legacy):
The "nat" table is not intended for filtering, the use of DROP is therefore inhibited.


Try `iptables -h' or 'iptables --help' for more information.
 
Thanks, but I'm getting this:

Code:
~# iptables -t nat -I PREROUTING -p udp --dport 53 ! -s 10.0.0.10 -d 8
.8.8.8 -j DROP
iptables v1.8.7 (legacy):
The "nat" table is not intended for filtering, the use of DROP is therefore inhibited.


Try `iptables -h' or 'iptables --help' for more information.
Exact, we are in nat.
These two rules should go in the mangle table
Code:
iptables -t mangle -I PREROUTING -p tcp --dport 53 ! -s 10.0.0.10 -d 8.8.8.8 -j DROP
iptables -t mangle -I PREROUTING -p udp --dport 53 ! -s 10.0.0.10 -d 8.8.8.8 -j DROP
[CODE]
 
I modded the 8.8.8.8 rule to include all ports, and that seems to have worked.

Code:
iptables -t mangle -I PREROUTING -p tcp ! -s 10.0.0.10 -d 8.8.8.8 -j DROP

For the DNS exception rule for 172.16.1.1, now that I think about it, this is what I want:

All clients -> port 53 UDP/TCP -> 10.0.0.10 (this is what I have currently)
10.0.0.10 -> port 53 UDP/TCP to 172.16.1.1 -> 172.16.1.1 (instead of 10.0.0.10).
 
For the DNS exception rule for 172.16.1.1, now that I think about it, this is what I want:

All clients -> port 53 UDP/TCP -> 10.0.0.10 (this is what I have currently)
10.0.0.10 -> port 53 UDP/TCP to 172.16.1.1 -> 172.16.1.1 (instead of 10.0.0.10).
That would do what you describe in line 2
Code:
iptables -t nat -I PREROUTING -p udp --dport 53 -s 10.0.0.10 -d 172.16.1.1 -j ACCEPT
iptables -t nat -I PREROUTING -p tcp --dport 53 -s 10.0.0.10 -d 172.16.1.1 -j ACCEPT
Put it at the end of your nat rules script (before the. 8.8.8.8 ones), to make sure the rule shows first in iptables.
 
I guess I hadn't tested that enough, DNS port 53 udp/tcp queries to 8.8.8.8/8.8.4.4 are dropped. Is there a way those are allowed to pass to the rules on the top?

This is what all the rules look like:

Code:
iptables -t nat -I PREROUTING -p tcp --dport 53 ! -d 10.0.0.10 -j DNAT --to 10.0.0.10
iptables -t nat -I PREROUTING -p udp --dport 53 ! -d 10.0.0.10 -j DNAT --to 10.0.0.10
iptables -t nat -I POSTROUTING -d 10.0.0.10 -j SNAT --to 10.0.0.1
iptables -t mangle -I PREROUTING -p tcp ! -s 10.0.0.10 -d 8.8.8.8 -j DROP
iptables -t mangle -I PREROUTING -p tcp ! -s 10.0.0.10 -d 8.8.4.4 -j DROP
iptables -t mangle -I PREROUTING -p udp ! -s 10.0.0.10 -d 8.8.8.8 -j DROP
iptables -t mangle -I PREROUTING -p udp ! -s 10.0.0.10 -d 8.8.4.4 -j DROP
 
@agneev

If you grab the full set of rules and edit them in notepad it gets a lot easier.

Prerouting should just be accept
Mangle is NAT

Neither of those are needed to permit DNS
You're making this a lot more complicated than it needs to be.

Permit on the INPUT / OUTPUT should allow your LAN i.e. br0

Mangle - POSTROUTING -o <WAN -j MASQUERADE

The only sections you should be messing with are filter / nat

Having played around with the other options in the past and seeing less performance / not working scenarios don't try to reinvent the wheel. Everything you need to secure your network is in those two sections. The rest "can" work but, chances are you'll just get a headache trying to deal with them and add increased CPU utilization in the process and slow down your link speed.

Code:
# Generated by iptables-save v1.8.7 on Sun Jan 23 20:51:32 2022
*mangle
:PREROUTING ACCEPT [41:49134]
:INPUT ACCEPT [39:49020]
:FORWARD ACCEPT [2:114]
:OUTPUT ACCEPT [21:1544]
:POSTROUTING ACCEPT [22:1474]
COMMIT
# Completed on Sun Jan 23 20:51:32 2022
# Generated by iptables-save v1.8.7 on Sun Jan 23 20:51:32 2022
*security
:INPUT ACCEPT [24:32068]
:FORWARD ACCEPT [2:114]
:OUTPUT ACCEPT [20:1360]
COMMIT
# Completed on Sun Jan 23 20:51:32 2022
# Generated by iptables-save v1.8.7 on Sun Jan 23 20:51:32 2022
*raw
:PREROUTING ACCEPT [41:49134]
:OUTPUT ACCEPT [21:1544]
:FORWARD - [0:0]
COMMIT
# Completed on Sun Jan 23 20:51:32 2022
# Generated by iptables-save v1.8.7 on Sun Jan 23 20:51:32 2022
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]
:PERMIT-FWD - [0:0]
:PERMIT-IN - [0:0]
:PERMIT-OUT - [0:0]
-A INPUT -j PERMIT-IN
-A FORWARD -j PERMIT-FWD
-A OUTPUT -j PERMIT-OUT
-A PERMIT-FWD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A PERMIT-FWD -m conntrack --ctstate NEW -j ACCEPT
-A PERMIT-FWD -j DROP
-A PERMIT-IN -i lo -j ACCEPT
-A PERMIT-IN -i br0 -j ACCEPT
-A PERMIT-IN -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A PERMIT-IN -j DROP
-A PERMIT-OUT -o lo -j ACCEPT
-A PERMIT-OUT -o br0 -j ACCEPT
-A PERMIT-OUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A PERMIT-OUT -m conntrack --ctstate NEW -j ACCEPT
-A PERMIT-OUT -j DROP
COMMIT
# Completed on Sun Jan 23 20:51:32 2022
# Generated by iptables-save v1.8.7 on Sun Jan 23 20:51:32 2022
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -o bo0 -j MASQUERADE
COMMIT
# Completed on Sun Jan 23 20:51:32 2022


#br0 = LAN
#bo0 = WAN
 
Few nerdy things confuse me as much as rules in iptables.

Here's what I want to accomplish: redirect all port 53 udp/tcp to my server at 10.0.0.10, drop all other queries to 8.8.8.8 and 8.8.4.4, except those made from my server at 10.0.0.10.

I also want to access my ISP's DNS server, so port 53 udp/tcp queries to my ISP's gateway at 172.32.111.1 from my server are also allowed:

Code:
iptables -t nat -I PREROUTING -p tcp --dport 53 -s 10.0.0.10 -d 172.32.111.1 -j ACCEPT
iptables -t nat -I PREROUTING -p udp --dport 53 -s 10.0.0.10 -d 172.32.111.1 -j ACCEPT

I'd love your suggestions here.
 
Last edited:
Here's what I want to accomplish: redirect all port 53 udp/tcp to my server at 10.0.0.10, drop all other queries to 8.8.8.8 and 8.8.4.4, except those made from my server at 10.0.0.10.
Then set your DHCP options to DNS @ 10.0.0.10. If you don't want clients to override your DNS setting then put in a DNS rule for INPUT / OUTPUT

Don't use PREROUTING.

Only use Filter/ nat.
 
like to contact Google DNS (plaintext or DoH/DoT), thus bypassing it.
Do you have logs?

Are they hitting those by IP or by name?

If it's by name then using pihole would kill that by blocking the FQDN from being resolved. I have a soundbar that likes to reach out to 3-4 different names for a keep alive / network checks.

1643992270981.png


If it's more than just pinging those names then something like this should FORCE all clients to hit your internal server.

-A FORWARD -o $WAN -p tcp --dport 53 -j REJECT
-A FORWARD -o $WAN -p udp --dport 53 -j REJECT
 
Are they hitting those by IP or by name?
Chromecasts use 8.8.8.8/8.8.4.4 by default, so does the Netflix app (at least on TVs).

Blocking 8.8.8.8 and 8.8.4.4 is easy and can be done in the NG web UI itself, but the fallback behavior doesn't work properly all the time. It could simply fall back to DNS over HTTPS or DNS over TLS to evade this.

It's simply better if all DNS traffic is intercepted and redirected.
 

Maybe something like this then.

iptables -t nat -A PREROUTING -i eth1 -p udp --dport 53 -j DNAT --to $intdns
iptables -A FORWARD -p udp -d $intdns --dport 53 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A FORWARD -p udp -s $intdns --sport 53 -m state --state ESTABLISHED -j ACCEPT

$intdns = 10.0.0.10
 
I guess I hadn't tested that enough, DNS port 53 udp/tcp queries to 8.8.8.8/8.8.4.4 are dropped. Is there a way those are allowed to pass to the rules on the top?

This is what all the rules look like:

Code:
iptables -t nat -I PREROUTING -p tcp --dport 53 ! -d 10.0.0.10 -j DNAT --to 10.0.0.10
iptables -t nat -I PREROUTING -p udp --dport 53 ! -d 10.0.0.10 -j DNAT --to 10.0.0.10
iptables -t nat -I POSTROUTING -d 10.0.0.10 -j SNAT --to 10.0.0.1
iptables -t mangle -I PREROUTING -p tcp ! -s 10.0.0.10 -d 8.8.8.8 -j DROP
iptables -t mangle -I PREROUTING -p tcp ! -s 10.0.0.10 -d 8.8.4.4 -j DROP
iptables -t mangle -I PREROUTING -p udp ! -s 10.0.0.10 -d 8.8.8.8 -j DROP
iptables -t mangle -I PREROUTING -p udp ! -s 10.0.0.10 -d 8.8.4.4 -j DROP
Just remove the last 4 rules in mangle, they are the ones dropping the queries.
They will then reach the nat table and be redirected.
 
Those rules ensure that only my DNS server can reach Google’s DNS servers.

Can an exception be added for 53 udp/tcp??
 
Those rules ensure that only my DNS server can reach Google’s DNS servers.

Can an exception be added for 53 udp/tcp??
So are those:
Code:
iptables -t nat -I PREROUTING -p tcp --dport 53 ! -d 10.0.0.10 -j DNAT --to 10.0.0.10
iptables -t nat -I PREROUTING -p udp --dport 53 ! -d 10.0.0.10 -j DNAT --to 10.0.0.10
They mean anything that is going through TCP and UDP port 53 and is not going to 10.0.0.10 is redirected to 10.0.0.10, therefore including Google DNS…

You could change them to
Code:
iptables -t nat -I PREROUTING -p tcp --dport 53 ! -s 10.0.0.10 ! -d 10.0.0.10 -j DNAT --to 10.0.0.10
iptables -t nat -I PREROUTING -p udp --dport 53 ! -s 10.0.0.10 ! -d 10.0.0.10 -j DNAT --to 10.0.0.10

Or
Code:
iptables -t mangle -PREROUTING -s 10.0.0.10 -j ACCEPT
iptables -t nat -I PREROUTING -p tcp --dport 53 ! -d 10.0.0.10 -j DNAT --to 10.0.0.10
iptables -t nat -I PREROUTING -p udp --dport 53 ! -d 10.0.0.10 -j DNAT --to 10.0.0.10

To make sure 10.0.0.10 is not redirected to itself and is granted access to any outside DNS resolver you want.
 
Thanks! Is there a way to test rules and delete rules without the need to reboot the router?

You could change them to
I assume these rules are for the DNS redirection?

I was required to use a SNAT rule for it to actually succeed, as I was told here.

I use DNS-over-HTTPS on my DNS server, so that's the only client w/ port 443 that should be let through.

I changed the rules a bit to block DNS-over-HTTPS and DNS-over-TLS for LAN clients:

Code:
iptables -t mangle -I PREROUTING -p tcp --dport 443 ! -s 10.0.0.10 -d 8.8.8.8 -j DROP
iptables -t mangle -I PREROUTING -p tcp --dport 443 ! -s 10.0.0.10 -d 8.8.4.4 -j DROP
iptables -t mangle -I PREROUTING -p tcp --dport 853 ! -s 10.0.0.10 -d 8.8.8.8 -j DROP
iptables -t mangle -I PREROUTING -p tcp --dport 853 ! -s 10.0.0.10 -d 8.8.4.4 -j DROP

But I assume I cannot do something like this to exclude port 53 so that it "falls back" to the rules on top?

Code:
iptables -t nat -I PREROUTING -p tcp --dport 53 ! -s 10.0.0.10 ! -d 10.0.0.10 -j DNAT --to 10.0.0.10
iptables -t nat -I PREROUTING -p udp --dport 53 ! -s 10.0.0.10 ! -d 10.0.0.10 -j DNAT --to 10.0.0.10
iptables -t nat -I POSTROUTING -d 10.0.0.10 -j SNAT --to 10.0.0.1
iptables -t mangle -I PREROUTING -p tcp ! --dport 53 ! -s 10.0.0.10 -d 8.8.8.8 -j DROP
iptables -t mangle -I PREROUTING -p udp ! --dport 53 ! -s 10.0.0.10 -d 8.8.8.8 -j DROP
iptables -t mangle -I PREROUTING -p tcp ! --dport 53 ! -s 10.0.0.10 -d 8.8.4.4 -j DROP
iptables -t mangle -I PREROUTING -p udp ! --dport 53 ! -s 10.0.0.10 -d 8.8.4.4 -j DROP
 
Thanks! Is there a way to test rules and delete rules without the need to reboot the router?

You don't need to reboot the router at all. Once you set/change/remove a rule in iptables, it is instantly effective.
However, for these rules to survive a reboot or a call to "net-wall restart", you need to generate them from a specific script, but I assume you already know that.

I assume these rules are for the DNS redirection?

I was required to use a SNAT rule for it to actually succeed, as I was told here.

I use DNS-over-HTTPS on my DNS server, so that's the only client w/ port 443 that should be let through.

I changed the rules a bit to block DNS-over-HTTPS and DNS-over-TLS for LAN clients:

Code:
iptables -t mangle -I PREROUTING -p tcp --dport 443 ! -s 10.0.0.10 -d 8.8.8.8 -j DROP
iptables -t mangle -I PREROUTING -p tcp --dport 443 ! -s 10.0.0.10 -d 8.8.4.4 -j DROP
iptables -t mangle -I PREROUTING -p tcp --dport 853 ! -s 10.0.0.10 -d 8.8.8.8 -j DROP
iptables -t mangle -I PREROUTING -p tcp --dport 853 ! -s 10.0.0.10 -d 8.8.4.4 -j DROP

But I assume I cannot do something like this to exclude port 53 so that it "falls back" to the rules on top?

Code:
iptables -t nat -I PREROUTING -p tcp --dport 53 ! -s 10.0.0.10 ! -d 10.0.0.10 -j DNAT --to 10.0.0.10
iptables -t nat -I PREROUTING -p udp --dport 53 ! -s 10.0.0.10 ! -d 10.0.0.10 -j DNAT --to 10.0.0.10
iptables -t nat -I POSTROUTING -d 10.0.0.10 -j SNAT --to 10.0.0.1
iptables -t mangle -I PREROUTING -p tcp ! --dport 53 ! -s 10.0.0.10 -d 8.8.8.8 -j DROP
iptables -t mangle -I PREROUTING -p udp ! --dport 53 ! -s 10.0.0.10 -d 8.8.8.8 -j DROP
iptables -t mangle -I PREROUTING -p tcp ! --dport 53 ! -s 10.0.0.10 -d 8.8.4.4 -j DROP
iptables -t mangle -I PREROUTING -p udp ! --dport 53 ! -s 10.0.0.10 -d 8.8.4.4 -j DROP

So for redirection purpose all you need is this:
Code:
iptables -t nat -I PREROUTING -p tcp --dport 53 ! -d 10.0.0.10 -j DNAT --to 10.0.0.10
iptables -t nat -I PREROUTING -p udp --dport 53 ! -d 10.0.0.10 -j DNAT --to 10.0.0.10
It already takes care of preventing LAN clients to send anything on port 53 to 8.8.8.8 and 8.8.4.4 as any packets going to these adresses with port 53 are already rerouted to 10.0.0.10.

If you have any client on the LAN using their own DNS-over-HTTPS to use Google DNS resolvers, these rules will indeed block them, creating a timeout (no response).
Code:
iptables -t mangle -I PREROUTING -p tcp --dport 443 ! -s 10.0.0.10 -d 8.8.8.8 -j DROP
iptables -t mangle -I PREROUTING -p tcp --dport 443 ! -s 10.0.0.10 -d 8.8.4.4 -j DROP
No need for UDP as DoH uses TCP.

Also, if you have any client on the LAN using their own DNS-over-TLS to use Google DNS resolvers, you would need to add this to block them :
Code:
iptables -t mangle -I PREROUTING -p tcp --dport 853 ! -s 10.0.0.10 -d 8.8.8.8 -j DROP
iptables -t mangle -I PREROUTING -p tcp --dport 853 ! -s 10.0.0.10 -d 8.8.4.4 -j DROP

You can simplify the two DoH and DoT into one set of rules with multiports:
Code:
iptables -t mangle -I PREROUTING -p tcp -m multiport --dports 443,853 ! -s 10.0.0.10 -d 8.8.8.8 -j DROP
iptables -t mangle -I PREROUTING -p tcp -m multiport --dports 443,853 ! -s 10.0.0.10 -d 8.8.4.4 -j DROP

And as you were told in the post you refer too, this rule is needed or not depending on your LAN subnet:
Code:
iptables -t nat -I POSTROUTING -d 10.0.0.10 -j SNAT --to 10.0.0.1
 
Similar threads

Similar threads

Sign Up For SNBForums Daily Digest

Get an update of what's new every day delivered to your mailbox. Sign up here!
Top