I want to intercept all UDP traffic leaving tap1. And possibly reply to e.g. DNS-requests. To accomplish this I wrote some python code listening to localhost and use iptables with a rule-set like this:
Chain PREROUTING (policy ACCEPT 2 packets, 333 bytes) pkts bytes target prot opt in out source destination 0 0 DIVERT udp -- tap1 any anywhere anywhere socket 0 0 TPROXY udp -- tap1 any anywhere anywhere TPROXY redirect 127.0.0.1:5001 mark 0x1/0x1 Chain DIVERT (1 references) pkts bytes target prot opt in out source destination 0 0 MARK udp -- any any anywhere anywhere MARK set 0x1 0 0 ACCEPT udp -- any any anywhere anywhere
Policy routing is done with:
ip rule add fwmark 1 lookup 100 ip route add local 0.0.0.0/0 dev lo table 100
This setup was adapted from the kernel's Documentation/networking/tproxy.txt. This works flawlessly for a TCP socket opened with the IP_TRANSPARENT option.
Unfortunately UDP sockets don't seem to be able to handle connections. For example if I do a
ncat -u localhost 1234 the socket will receive data but cannot send anything back. Wireshark will show exactly three packets for:
- the incoming ncat packet (to localhost:1234)
- the outgoing packet of my software (to :5001)
- an ICMP Port unreachable (of course)
For arbitrary ports to work I guess it's not feasable to set up proper (S)NATting rules.
So, what's the necessary setup to make this work for arbitrary incoming ports?