[tproxy] Bad Interaction between NAT and TPROXY

Tim Burress hokousha2001@yahoo.com
Thu, 19 Aug 2004 21:53:11 -0700 (PDT)


We're seeing a problem when we combine NAT and TPROXY
1.2.1 on a firewall system with application-layer
proxies in the 2.4.26 kernel. Say the firewall system
has two interfaces, public ( and private
( There is an SMTP server ( on the
private network, and we have DNAT rules configured to
map --->

So then, in practice, the SMTP proxy on the firewall
receives a redirected SMTP connection from a client
( on the net. It then does its application
stuff, and sets up a connection to the server by:

(1) Binding a socket to a local address
(2) Setting up a TPROXY assignment from the local
address to
(3) Connect out to the server using the destination
address recovered by getsockopt(ORIGINAL_DST) on the
original incoming socket

This all works fine when there is no NAT (and the
private addresses are eliminated). In that case, what
the server sees is an incoming connection from But with NAT in the picture, what the server
sees is an incoming connection from

Working through the kernel code, it appears that when
CONFIG_IP_NF_NAT_LOCAL is enabled, there is a call to
do_extra_mangle() in ip_nat_core.c that is forcing the
source address of outgoing packets to be the preferred
source from the routing tables in the LOCAL_OUT hook,
so by the time the packet gets to POSTROUTING, the
outbound packet no longer matches the TPROXY rule that
we set up, so the source address goes out as-is.

Looking for a general solution, all I can think of at
the moment is to patch ip_nat_core.c so that the call
to do_extra_mangle.c is skipped if connection has been
assigned by TPROXY, on the theory that the code
setting up the TPROXY assignment knows what it wants
the final source or destination to be, and that this
should take priority over the extra mangling done by

Perhaps testing for IPS_TPROXY before the call to

If that would work (the code is still a jungle to me),
it seems like this would solve the problem and still
be relatively harmless, but I'm not sure. Actually I'm
not sure why the NAT code rewrites the source address
of a DNAT packet anyway (or the destination address of
an SNAT packet), so it makes me nervous.

What we do now as a workaround in simple networks is
manually force the proxy to bind the local socket to before the TPROXY assignment. It's ugly, but
it works, since it anticipates how the kernel will
mangle the packets. However it's obviously not a good
general solution, and would fail in complex networks
where routing to the destination is dynamic.

What's the best way to deal with this?



Do you Yahoo!?
Win 1 of 4,000 free domain names from Yahoo! Enter now.