A long time ago, while reading the OpenWRT wiki, I discovered that it is possible to hijack DNS traffic and force it to redirect to a private DNS server.
I wanted to achieve a similar setup on my laptop. The main difference is that this laptop does not use UCI (Unified Configuration Interface) to configure the system, so I need to use firewalld instead.
The objective is to redirect all outbound DNS traffic from my laptop to a CoreDNS service running locally on 127.0.0.1:5454. This makes it much easier to inspect DNS logs and forward queries to a DNS over TLS (DoT) server for better privacy.
First, I verified that CoreDNS is listening on the correct port:
$ sudo ss -tulpn | grep coredns
udp UNCONN 0 0 127.0.0.1:5454 0.0.0.0:* users:(("coredns",pid=1454,fd=6))
tcp LISTEN 0 4096 127.0.0.1:5454 0.0.0.0:* users:(("coredns",pid=1454,fd=3))
To perform the redirection, I used firewall-cmd to add direct rules to the nat table. These rules intercept both UDP and TCP traffic on port 53.
Note: I added a condition (! -d 127.0.0.1) to exclude traffic already destined for localhost, which prevents infinite routing loops.
# Redirect UDP+TCP DNS traffic
sudo firewall-cmd --permanent --direct --add-rule ipv4 nat OUTPUT 0 -p udp ! -d 127.0.0.1 --dport 53 -j DNAT --to-destination 127.0.0.1:5454
sudo firewall-cmd --permanent --direct --add-rule ipv4 nat OUTPUT 0 -p tcp ! -d 127.0.0.1 --dport 53 -j DNAT --to-destination 127.0.0.1:5454
# Reload firewalld to apply the changes
sudo firewall-cmd --reload
Cool, let see the logs:
$ dig @1.1.1.1 sumarsono.com
; <<>> DiG 9.20.15-1~deb13u1-Debian <<>> @1.1.1.1 sumarsono.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 21760
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: b84181da1f3c8c46 (echoed)
;; QUESTION SECTION:
;sumarsono.com. IN A
;; ANSWER SECTION:
sumarsono.com. 300 IN A 104.21.39.176
sumarsono.com. 300 IN A 172.67.147.103
;; Query time: 112 msec
;; SERVER: 1.1.1.1#53(1.1.1.1) (UDP)
;; WHEN: Thu Dec 25 14:49:26 WIB 2025
;; MSG SIZE rcvd: 112
# CoreDNS logs
Dec 25 14:49:26 l490 coredns[1454]: [INFO] 10.12.171.200:52666 - 21760 "A IN sumarsono.com. udp 54 false 1232" NOERROR qr,rd,ra,ad 89 0.113530217s