6

EDIT: the tldr: I want to use TEE and NAT to clone UDP traffic. I'm not worried about handling responses. I ideally don't want to install new software. I am using TEE to send to local segment (127.0.0.2) successfully, then I want to NAT that traffic out to the WAN.

I have bind9 listening on port 53 on my Debian server. I have an external client making DNS requests to said server. All of this is working fine. I would like to copy the incoming DNS requests on port 53 and send them off to, say, 8.8.8.8. Note the word copy.

From much googling and reading on SU, I have found the most often advised method is to use iptables TEE and NAT. I have TEE working pretty well, here's my command:

iptables -t mangle -A POSTROUTING -p udp -d 127.0.0.1 --dport 53 -j TEE --gateway 127.0.0.2

I verified I receive a copy of the DNS request at 127.0.0.2:53 with netcat. So far so good.

Now, I need to change the destination IP. I attempt to accomplish this with:

iptables -t nat -A PREROUTING -p udp -d 127.0.0.2 --dport 53 -j DNAT --to 8.8.8.8

I used tcpdump to monitor for outgoing traffic to 8.8.8.8. Nothing. I wondered: maybe I need to change the source IP address so that the kernel doesn't drop this packet, since it's arriving at 127.0.0.2, but the source IP is set to that of my external DNS client. Why not?

iptables -t nat -A POSTROUTING -p udp -d 127.0.0.2 --dport 53 -j SNAT --to DNS_SERVERS_PUBLIC_IP

Still, tcpdump shows nothing.

I have IP forwarding on:

$ sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1

I am pretty much out of ideas and would appreciate any and all help. Thank you.

10
  • 3
    Your question does not seem very clear to me - What are you trying to achieve? I can't understand why you would both answer the DNS request in bind and ask Google for it without going through Bind.
    – davidgo
    Commented Sep 30, 2018 at 9:31
  • Unrelatedly, your solution needs to handle port 53 UDP as well as port 53 TCP - the latter is often overlooked, but important and becoming more-so with larger queries.
    – davidgo
    Commented Sep 30, 2018 at 9:32
  • Google is just for example. My goal is to send a copy of all DNS requests to a DNS logging tool will alert for dangerous domains as well as keep a forensic trail of all DNS requests made production wide.
    – returneax
    Commented Sep 30, 2018 at 10:15
  • 1
    In that case, why not go all in and implement an IDS like SNORT ? (You might also want to look at github.com/dnlongen/Snort-DNS). Of-course, you probably don't need anything that complex - you can simply use something like wireshark - see superuser.com/questions/383391/…
    – davidgo
    Commented Sep 30, 2018 at 19:57
  • 3
    You can also handle this by getting BIND to log the queries - cyberciti.biz/faq/howto-enable-dns-linux-unix-server-logging floriancrouzat.net/2011/09/…
    – davidgo
    Commented Sep 30, 2018 at 20:03

3 Answers 3

2
+50

Nothing is impossible, with iptables.

# iptables -t nat -L -v --line-numbers -n
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1        5   281 MARK       udp  --  docker0 *       0.0.0.0/0            172.17.0.1           udp dpt:53 MARK set 0xc0fe
2        5   281 TEE        udp  --  docker0 *       0.0.0.0/0            172.17.0.1           udp dpt:53 TEE gw:127.1.2.3
3        3   167 DNAT       udp  --  *      *       0.0.0.0/0            0.0.0.0/0            mark match 0xc0fe to:1.1.1.1:53

I was testing this with docker, since its easier to play with its interface. Notice I placed these rules before any other rules in nat prerouting table.

What you do is, mark the packet you are interested in, then TEE (copy) that packet, and now you can DNAT that packet to 1.1.1.1.

Mark them up, here you should use your eth0 or eno1, not docker0.

iptables -t nat -I PREROUTING 1 -i docker0 -p udp -d 172.17.0.1 --dport 53 -j MARK --set-mark 0xc0fe

Copy/tee it, over to localhost, the rule can be like this

iptables -t nat -I PREROUTING 2 -i docker0 -p udp --dst 172.17.0.1 --dport 53 -j TEE --gateway 127.1.2.3

But it can also be like this iptables -t nat -I PREROUTING 3 -p udp -m mark --mark 0xc0fe -j TEE --gateway 127.1.2.3

Finally

iptables -t nat -I PREROUTING 3 -p udp  -m mark --mark 0xc0fe -j DNAT --to-destination 1.1.1.1:53

So you were were much on the right path, except using TEE in the mangle table, here I am using both TEE and DNAT on nat table, and the MARK is not needed except for easier debugging, and handling rule-changes. Also another mistake you had was letting the DNAT rule act on the dst of what you believed the TEE should go to, but instead TEE and DNAT should act on same conditions. But I'll leave the mark rules here, just to have fun with cargo-cultists.

In shorter form:

iptables -t nat -I PREROUTING 1 -i eth0 -p udp --dst 172.17.0.1 --dport 53 -j TEE --gateway 127.3.3.3
iptables -t nat -I PREROUTING 2 -i eth0 -p udp --dst 172.17.0.1 --dport 53 -j DNAT --to-destination 1.1.1.1:53
3
  • I have a similar question which I actually care about more here: unix.stackexchange.com/questions/474377/… Im sure it would be easy for you to answer. the difference is that I want to copy outgoing packets in that one.
    – returneax
    Commented Oct 19, 2018 at 21:33
  • I actually was unable to see the cloned packets with tcpdump. Is that expected @AntonioP?
    – returneax
    Commented Oct 23, 2018 at 19:53
  • and how could be possible to duplicate incoming packets on port 53 on the same machine and port let's say 5353 ? so that when a dns packet arrives is also sent to a different port (of the same machine) for monitoring/processing
    – Zibri
    Commented Apr 22, 2019 at 23:12
4

The documentation says

The TEE target will clone a packet and redirect this clone to another machine on the local network segment. In other words, the nexthop must be the target, or you will have to configure the nexthop to forward it further if so desired.

I don't know about the reason for this restriction, but it seems it can't be overcome with iptables NAT, which makes sense, because if the underlying implementation supports external targets, then why restrict the target range of TEE. I suspect that the TEE is done below the NAT level.

It wouldn't work anyway because the response would arrive with the wrong source address.

4
  • The TEE target doesn't actually perform NAT. It works practically the same way as routing tables do: sends the unaltered IP packet to the chosen nexthop's MAC address. Commented Sep 28, 2018 at 5:34
  • I am actually sending it to the local segment though. I even tried creating another network interface and sending it to the local IP associated with that one. I actually don't care about the response in this case @RalfFriedl, Im logging DNS requests made on an external host for forensics.
    – returneax
    Commented Sep 28, 2018 at 6:05
  • To be clear, Im trying to combine TEE with NAT which is a technique I've read about in multiple places. I don't see why iptables would care if it sees a fresh packet, created by TEE coming in.
    – returneax
    Commented Sep 29, 2018 at 22:49
  • To overcome this limitation, use DNAT for the same rule as for TEE, TEE will give you 2 copies of a packet, it doesnt matter if it cant go to 1.1.1.1, when DNAT will do that for you, and the other packet will be handled as usual. To not make mistakes in having DNAT and TEE targets act on different rules, its easier to MARK the packet with the rule you are interested in and let TEE and DNAT act on those marked packes. That lets you also change the rule by deleting/creating only 1 MARK rule.
    – AntonioP
    Commented Oct 17, 2018 at 11:20
1

As TEE can only be used in the same subnet, you might be able to use the tool of Daemonlogger, also available on github (where it seems fresher?).

Daemonlogger is a packet logger and soft tap developed by Martin Roesch. The libpcap-based program has two runtime modes:

  1. It sniffs packets and spools them straight to the disk and can daemonize itself for background packet logging. By default the file rolls over when 2 GB of data is logged.
  2. It sniffs packets and rewrites them to a second interface, essentially acting as a soft tap. It can also do this in daemon mode. These two runtime modes are mutually exclusive, if the program is placed in tap mode (using the -I switch) then logging to disk is disabled.

Some writeups :

3
  • 0 down vote accept Thanks for the suggestion. I'm actually logging to localhost in this case so the subnet restriction should not be an issue.
    – returneax
    Commented Sep 30, 2018 at 10:18
  • Daemonlogger may still be useful in your case.
    – harrymc
    Commented Oct 2, 2018 at 5:29
  • +1, I'm wary of installing/supporting a new project in production, so ideally I'd like an iptables solution, but I'll keep this in mind, thanks.
    – returneax
    Commented Oct 2, 2018 at 18:03

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .