5

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.

migrated from superuser.com Oct 8 '18 at 8:17

This question came from our site for computer enthusiasts and power users.

  • 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 Sep 30 '18 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 Sep 30 '18 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 Sep 30 '18 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 Sep 30 '18 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 Sep 30 '18 at 20:03
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

Hey, 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 Ill 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

  • 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 Oct 19 '18 at 21:33
  • I actually was unable to see the cloned packets with tcpdump. Is that expected @AntonioP? – returneax Oct 23 '18 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 Apr 22 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.

  • 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. – grawity Sep 28 '18 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 Sep 28 '18 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 Sep 29 '18 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 Oct 17 '18 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 :

  • 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 Sep 30 '18 at 10:18
  • Daemonlogger may still be useful in your case. – harrymc Oct 2 '18 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 Oct 2 '18 at 18:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.