IPFW Redirect udp traffic based on port for any destination address

Hi,

I'm looking at a solution to redirect traffic using IPFW and Kernel NAT (libalias) so I can reproduce the behavior of the following iptable rule:
Code:
iptables -t nat -A PREROUTING  ! -d 127.0.0.1/32 -p udp -m udp --dport 53 -j DNAT --to-destination 127.0.0.1:53

I was thinking (from my reading of "man ipfw(8)") that I could use the following:
Code:
ipfw nat 1 config log reset redirect_addr 127.0.0.1 0.0.0.0

ipfw add 1 nat 1 log udp from any to not 127.0.0.1 dst-port 53 in via em0
ipfw add 2 nat 1 log udp from 127.0.0.1 53 to not 127.0.0.1 out via em0
ipfw add 3 allow ip from any to any

This, unfortunately, doesn't work, while the following works perfectly well for a specific IP address:
Code:
ipfw nat 1 config log reset redirect_addr 127.0.0.1 8.8.8.8

ipfw add 1 nat 1 log udp from any to not 127.0.0.1 dst-port 53 in via em0
ipfw add 2 nat 1 log udp from 127.0.0.1 53 to not 127.0.0.1 out via em0
ipfw add 3 allow ip from any to any

From the code (https://svnweb.freebsd.org/base/head/sys/netpfil/ipfw/ip_fw_nat.c?view=markup) I can see this comment:
Code:
520 /*
521 * XXX - what if this rule doesn't nat any ip and just
522 * redirect?
523 * do we set aliasaddress to 0.0.0.0?
524 */

I understand that this might not already be implemented. That would explain the strange behavior I face with packets being dropped during the NAT process. Could anyone confirm ?

If so, what would be the best option ? I thinking about reverting to natd, but I'm afraid the performances will suffer from this.

Thanks in advance for your help.

Regards
 
Hello,

I did not found any solution, but for others that might be interested in this, one option is described here.

It work only with Unbound, not bind, but it's a start.

Regards
 
With PF this is quite easy:

Code:
rdr pass on $lan proto { udp , tcp } from any to any port domain -> <lan-nameservers> port domain

The same can be done with ntp. This way all clients trying to make name-resolution with some external server will get redirected to the local nameserver(s) instead. This is especially useful with Laptops as you don't have to rely on them accepting the name- and timeserver options from your DHCP or can even set your manually set resolv.conf as immutable.
This simple rule also effectively disturbs some windows-malware that uses DNS-tunneling for its c&c connections and you can catch such attempts on your DNS as these attempts trigger a bunch of error log messages on a normal DNS server and hence are relatively easy to grep for.
 
Thanks for you advice.

Indeed, with PF, this should work pretty well, unfortunately, in my case, I'm stuck with IPFW for legacy reasons.
 
I am not sure if the following does work, however, I think it might be worth to give it a try:

Code:
ipfw nat 1 config if WAN_IF unreg_only reset redirect_port udp 127.0.0.1:53 53

ipfw add nat 1 udp from not me to any 53 via WAN_IF
...

You would need to rename WAN_IF to the actual device descriptor of your public interface.

PS:

I am almost sure that you need to set the following sysctl variable to zero:
sysctl net.inet.ip.fw.one_pass=0

In addition beware of the following statement in ipfw(8):
Due to the architecture of libalias(3), ipfw nat is not compatible with the TCP segmentation offloading (TSO). Thus, to reliably nat your network traffic, please disable TSO on your NICs using ifconfig(8).
 
Try ipfw fwd:
ipfw add 1001 fwd 127.0.0.1,53 udp from any to any 53 in

libalias can't alias address to any destination, the local address must be set.
 
Back
Top