Blocking DNS Tunneling attacks or data leaks

Hi there.

While looking at some traffic on my router with tcpdump, I came across a weird discovery: some applications can pass through my outbound firewall with a method I've discovered recently : DNS tunneling
(For the record, I block all outbound traffic except some specifics ports, and I use a proxy)
More infos on theses methods:

I wonder if anyone have a idea of how to prevent this huge security issue from happening by blocking this tcp over dns traffic ??

1 Like

"Application proxy" is generally how this kind of thing is handled, without getting into "deep-packet inspection". Basically, you force all the clients to use your DNS server and block forwarding of port 53 (UDP and TCP both) across your perimeter.

Of course, the best is to remove any such "stealth" applications, as who knows what else they are doing!

Edit: Deep-packet inspection is the "more professional" way to handle this, but all-in-one routers don't have the computational resources to manage it at any meaningful rate.

thanks you jeff

I'm not "worried much" by this application in particular since it's a paid commercial app, but more on the fact that this kind of technique could be used by any application on my network to bypass outbound firewall.

When you say " use your DNS server and block forwarding of port 53" I'm already using the integrated dnsmasq of openwrt which listen on local network port 53 and dns requests in dns lan are passing through it and then forwarded to an internet DNS server; So I'm not sure how to accomplish what your saying, can you give an example please ?

PS: my router is an x86-64 pc, not a consumer device

Have a look at this.

Would it really help when the tunnel uses the DNS protocol? I.e. it isn't an openvpn or wireguard tunnel using port 53.

BTW when using an application proxy, such as a http proxy, you shouldn't need to use DNS anyway (unless it's a transparent proxy). Which mean you could block traffic to port 53 from the clients completely.

It is covering the case that someone tries to access the NS directly, unless I misunderstood something.

I see, though you don't need to access the iodine server directly since it supports DNS relays.

Client side:
All the setup is done, just start iodine. It takes one or two arguments, the
first is the local relaying DNS server (optional) and the second is the domain
you used ( If you don't specify the first argument, the
system's current DNS setting will be consulted.

1 Like

If a rogue application makes a DNS request for "", then (no mater what filters or proxies you put in between), the DNS at "" will receive a request for host "somedata".

unfortunately, we are not talking of the same thing. My network is not leaking dns because outbound connections are already blocked. A lan client which use he's own dns settings couldn't reach the net.

To "prevent" this kind of thing, you need to inspect every DNS request/response.

Blocking all except A and AAAA requests and their expected responses is a start. (You might need MX as well, if you're running an MTA.)

Then you need to additionally somehow filter out "good" from "bad" request/responses. Some public DNS services filter out a list of domains that they manage that they believe to be "unsafe". Also, while you might make an A request, you might get back much more "data" than you expect.

These in-protocol kinds of back channels are difficult to close down. That is why IDS systems like suricata and snort (as well as commercial ones) are used. Unfortunately, comprehensive deep-packet inspection is far beyond the capabilities of all-in-one routers that struggle just to route and NAT at the rates now available to SOHO consumers.

1 Like

thanks again jeff, you seem's to have valuable knowlege on this. On my case, I observed that TXT records where used with multiples sub domains, each one sending back crypted data to a computer in my lan where the app is installed.
Could you tell us if openwrt is able to block all EXCEPT A records from dns responses or many limit the size of responses ? if yes could you please give us an example of what to do, which config may need tweaking ?
As crazy as it sound, I've found many topics on the web telling us how dangerous this could be but nobody could offer a practical way to protect a conventional linux os from it.

With dnsmasq, I would doubt it.

It might be possible with unbound through advanced configuration, though I haven't looked into it in great detail. I didn't see anything obvious in unbound.conf in a quick read of it. As I recall, but have not used it, unbound has hooks to Python and that would likely be the way I'd approach it.

See, for examples

Edit: Installing Python and a reasonably complete set of standard libraries on an all-in-one router with a 16 MB flash is close to impossible, even building from source. Even if you have enough flash, I'd recommend a VM or Pi-class device for this, running your choice of desktop/server OSes. This is driven by both potential RAM issues, as well as that OpenWrt can't easily install "unpackaged" Python modules that require on-device compilation. If you get it running there, then you might try bringing it back to a mid- or high-end all-in-one router.

thanks, I'm not concerned by flash size or memory footprint since openwrt is running on x86 hardware

I may look into unbound although I don't know where to start regarding this particular topic. Or may be install opnsense instead of openwrt since it has build in outbound and surricata ?

Personally, I run my DNS and DHCP "off router". I would start by spinning up a VM and installing an OS of your choice to "play" with unbound. That way your OpenWrt install stays clean and functional. Solving a connectivity problem always seems to involve looking on the Internet for an answer!

for sure! thats whats I'm actually doing, installing opnsense in a vm to play with outbound. But I'm doubtfull about being able to block this easily. Thanks you very much anyway for yours suggestions!

I've found that unbound is able to block some specifics domains and sub domains. There is a custom option like :
local-zone: "" inform_deny
this will block dns data. Tried it with (on windows) nslookup -q=TXT OR dig -t txt on linux
With dnsmasq, there seems to be an option like address=/
but I've not found how to add this via luci, and cannot do it to the file /etc/dnsmasq.conf

You can log into openwrt device via ssh/putty, and then directly edit /etc/dnsmasq.conf to include "address= ...".
BTW: How big are the "bad" DNS packets you discovered ? Might be possible to block them using iptables. Or to also include " edns-packet-max=... " in dnsmasq.conf.

not sure, because it changed over time, last time I checked I think it was about 330 Bytes but from severals sub domains in a row, certainly by design to have better chances of passing through because big data packets flow in dns could be suspicious even if not many people check this on their firewall.
the edns-packet-max option is interesting for a global protection but I guess legit usage will be impacted according to this :
Iptables could be a good way, but I've not looked into it yet. I'm open to suggestions :wink:

The main purpose of a malicious DNS tunnel is to exfiltrate data from a network without being detected since DNS egress traffic over port 53 is usually considered benign.

Assuming that port 53 is not open/forwarded on the WAN for DNS ingress traffic it would require an app on the router or router client to open up (initiate) egress traffic over port 53.

If you deploy on the router

and thus force egress DNS traffic to the local stub resolver the DNS tunnel with an external (malicious) server will not be established since the stub resolver will only resolve queries with the upstream server specified in the setting of the local stub resolver but egress (exfiltrate) traffic to an external (malicious) server is not happening (by design of the stub resolver it does not egress traffic other than querying specified upstream servers) , unless the stub resolver and/or firewall rules on the router is/are compromised.

Additionally if the domains suspected for exfiltrating (egress) traffic over port 53 are known such can be defined as a DNS sinkhole with the local stub resolver.

If the app in question however leverages DoT over port 443 or 853 it would be a different ballgame, particularly with port 443. Latter would require a deep packet inspection engine that decrypts the TLS traffic for inspection prior passing it on (if begin) or blocking it (if malicious). Port 853 is more distinctive however and could be handled with a firewall rule.

If the app in question however leverages DoH over port 443 it would require a deep packet inspection engine again.

It is not so clear what exactly been discovered - ingress or egress DNS traffic (port 53 ?)

Whilst that sounds rather shady (app design) it could serve a legitimate purpose for the app, depending of what the app in question is leveraging those TXT records for > Command & Control ? (secondary purpose of (ingress) DNS tunnel)