Iptables rule to allow DNS traffic on client

I’m struggling to come up with an iptables rule(s) to allow DNS traffic below from a client machine to my private DNS server on the same network. Any help is very much appreciated.

DNS server IP address: a.b.c.100
Client IP address: a.b.c.200

The message captured in client’s /var/log/messages after all the rules were processed :
IN= OUT=lo SRC=a.b.c.200 DST=a.b.c.200 LEN=106 TOS=0x00 PREC=0xC0 TTL=64 ID=57831 PROTO=ICMP TYPE=3 CODE=1 [SRC=a.b.c.200 DST=a.b.c.100 LEN=78 TOS=0x00 PREC=0x00 TTL=64 ID=3110 DF PROTO=UDP SPT=47963 DPT=53 LEN=58 ]

My default chain policies:

Since the default for OUTPUT chain is ‘accept’, I can’t wrap my head around what’s missing.
DNS server is not an issue, it works well with all other clients.



Whats the full output of: sudo iptables -S

Is firewalld disabled & masked?

Thanks Tom.

Hi Tom,

firewalld is disabled. I’m running iptables instead.
iptables -S output (after masking, and stripping down unrelated lines):

-A INPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG NONE -j DROP
-A INPUT -p tcp -m tcp --tcp-flags FIN,SYN FIN,SYN -j DROP
-A INPUT -p tcp -m tcp --tcp-flags SYN,RST SYN,RST -j DROP
-A INPUT -p tcp -m tcp --tcp-flags FIN,RST FIN,RST -j DROP
-A INPUT -p tcp -m tcp --tcp-flags FIN,ACK FIN -j DROP
-A INPUT -p tcp -m tcp --tcp-flags PSH,ACK PSH -j DROP
-A INPUT -p tcp -m tcp --tcp-flags ACK,URG URG -j DROP
-A INPUT -d -p igmp -j DROP
-A INPUT -p tcp -m conntrack --ctstate INVALID -j DROP
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -s a.b.c.100/32 -d a.b.c.200/32 -i enp1s0 -p udp -m udp --sport 53 -j ACCEPT
-A INPUT -s a.b.c.200/32 -d -p udp -m udp --sport 5353 --dport 5353 -j ACCEPT
-A INPUT -d -p udp -m udp --sport 5353 --dport 5353 -j DROP
-A INPUT -s a.b.c.100/32 -d a.b.c.200/32 -p udp -m udp --sport 5353 -j ACCEPT
-A INPUT -s a.b.c.100/32 -d a.b.c.200/32 -p icmp -m icmp --icmp-type 0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -d a.b.c.200/32 -i enp1s0 -p tcp -m multiport --sports 80,443 -m conntrack --ctstate ESTABLISHED -j ACCEPT
-A INPUT -d a.b.c.200/32 -i enp1s0 -p udp -m udp --sport 123 -m comment --comment ntp -j ACCEPT
-A INPUT -j LOG --log-prefix "** iptables-INP ** "
-A FORWARD -p tcp -m conntrack --ctstate INVALID -j DROP
-A FORWARD -p icmp -j ACCEPT
-A FORWARD -j LOG --log-prefix "** iptables-FWD ** "
-A OUTPUT -d -p igmp -j DROP
-A OUTPUT -s -d -o lo -j ACCEPT
-A OUTPUT -s a.b.c.200/32 -d a.b.c.100/32 -p udp -m udp --dport 53 -j ACCEPT
-A OUTPUT -s a.b.c.200/32 -d -p udp -m udp --sport 5353 --dport 5353 -j ACCEPT
-A OUTPUT -s a.b.c.200/32 -d a.b.c.100/32 -p icmp -m icmp --icmp-type 8 -m conntrack --ctstate NEW,RELATED,ESTABLISHED -j ACCEPT
-A OUTPUT -s a.b.c.200/32 -p tcp -m multiport --dports 80,443 -j ACCEPT
-A OUTPUT -s a.b.c.200/32 -p udp -m udp --dport 123 -m conntrack --ctstate NEW -m comment --comment ntp -j ACCEPT
-A OUTPUT -j LOG --log-prefix "** iptables-OUT ** "

Regarding masking firewalld, I’m not sure about that. All I usually do is:

systemctl stop firewalld
systemctl disable firewalld

Version: iptables-1.8.5


Does adding:

INPUT -i enp1s0 -m state --state RELATED,ESTABLISHED -j ACCEPT


Had a similar issue with vpn traffic, this resolved.

Thanks Tom.

nope, unfortunately it’s all the same. I can’t figure out how to interpret that message in the first place. On one hand it shows the icmp traffic on the local interface’ OUTPUT chain, on the other hand – the DNS traffic between client and the server wrapped up in brackets… this is beyond my understanding of the iptables…


Yeah on the wrong track with that one. I think its the forwarding policy:

Forwarded from local interface to enp1s0. For testing you try changing the forwarding policy to accept.

Thanks Tom.

Thanks Tom. I took your advise (FORWARD ACCEPT), but saw no change. I’m chasing some other leads in meanwhile, and will update the post with any findings.


I’ve just tried the original iptables rules you posted and dns requests to local server are working fine. Are you sure the issue is related to iptables? Does it work after issuing:

iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT`
iptables -F  

Thanks Tom.

Thanks again. This didn’t work either. But you’ve mentioned the vpn traffic before. And this is my vpn server machine, so I think I should do some more digging.
One thing I’ve noticed is nslookup uses for dns server, while the real dns server is on a separate host on the network. I think vpn setup has to do something with this…
It will take me a while to figure this all out.


What VPN protocal are you using, is it openvpn?

If so its possibly the configuration, I suggest posting the contents of the vpn conf (without any usernames and passwords).

Thanks Tom.

the host is running openvpn with pretty standard config:

port 1234
proto udp
dev tun
ca ca.crt
cert issued/server.crt
key private/server.key
dh dh.pem
topology subnet
server 10.xxx.yyy.zzz 255.255.255.mmm <<-- server ip & mask
ifconfig-pool-persist ipp.txt
push “redirect-gateway def1 bypass-dhcp”
push “dhcp-option DNS 192.168.aaa.bbb” <<-- router ip address
keepalive 10 120
tls-auth ta.key 0
cipher AES-256-GCM
user nobody
group nobody
status /var/log/openvpn/openvpn-status.log
log-append /var/log/openvpn/openvpn.log
verb 3
explicit-exit-notify 1
auth SHA512



push “redirect-gateway def1 bypass-dhcp”

I believe this options forces all traffic (including dns) via the vpn tunnel. Can the vpn sever access the local dns server?

Thanks Tom.

1 Like

Hi there, I’m not certain how iptables under uptodate Fedora still works.
→ iptables has been replaced by nftables.
So it is recommended to use nftables instead.

There are tools to convert iptables rules to nftables, see here:

As as side note, dns also uses tcp, so better open udp and tcp for port 53.

Since those rules are processed in a way which can be called “first match wins”, you may reconsider to put some of the DROP rules after the ACCEPT targets.

If you want to see what effectively is happening, you’d better use iptables -nvL. There you can see where traffic succeeds and where it is dropped.

However, I do not know how it collides with nftables.
Occasionally nftables may not see everything.

Fedora now uses a systemd-resolve.service.
systemctl status systemd-resolved.service

To see its config:

If you would open your outgoing traffic anyway, you can use firewalld as well.
Of cause, there is more control using own rulesets, but also a bigger chance of misconfiguration, such as forgetting to configure ip6tables at all and so on. However using firewalld with firewall-cmd can be very secure and practical. There also is a way to define “rich rules” that are way more specific. So breaking with old habits can be rewarding. Or in case one just starts with writing firewalls, then better start with nftables or firewalld rather than iptables.




1 Like

Note that iptables is virtually deprecated and should be replaced with nftables.
In addition, it is much easier to generate a safe and working configuration with firewalld.
So, it is best not to disable firewalld, but rather utilize it for a high-level firewall setup.

True, it does force all traffic via vpn. And that is intentional.
The long story short, the current setup does its job reasonably well (as a vpn server) when machine is connected on dmz side of the network. My problem was that dnf upgrade wouldn’t work. So whenever I wanted to upgrade I’d connect the machine to the internal network and run dnf upgrade.
Unfortunately, it stopped working even from within at some point. And I don’t have much time to look into this. It’s my home project anyway.

What’s concerning me, is the transition from iptables to nftables. Not sure how much of an effort is to convert all the scripts from one to another, but I’ll have to come back to it sooner or later.



Just out of interest, could this been have with the update to fedora 33. Fedora switched to systemd-resolved at this point for dns.

Does disconnecting from vpn, when in the internal network; allow you to update?

Thanks Tom.

Yes, one needs to configure the systemd-resolver separately, or disabling it.

The command resolvectl should shed light on it.

1 Like