I have set up a local, transparent TCP proxy on localhost. I want to redirect ALL TCP traffic to this proxy, so it can handle it and nothing "leaks out," circumventing the proxy. I need to use IPTables to redirect the traffic. I thought about using TPROXY, but that requires application support and only the REDIRECT target is supported at the moment.

I have used the following IPTables rules:

iptables -t nat -A OUTPUT -o lo -j RETURN
iptables -t nat -A OUTPUT -d -j RETURN
iptables -t nat -A OUTPUT -d -j RETURN
iptables -t nat -A OUTPUT -m owner --uid-owner proxy-owner -j RETURN
iptables -t nat -A OUTPUT -p tcp --syn -j REDIRECT --to-ports $PROXY_PORT

iptables -A OUTPUT -o lo -j ACCEPT
iptables -A OUTPUT -d -j ACCEPT
iptables -A OUTPUT -m owner --uid-owner proxy-owner -j ACCEPT
iptables -A OUTPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A OUTPUT -j LOG
iptables -P OUTPUT DROP

They seem to work fine, however I'm confused as to why.

Here are two questions that I still don't know the answer to:

1) Regarding the last rule in the NAT table, why do I only want to redirect SYN packets to the local proxy port (--syn)? I want to redirect ALL TCP packets. In the current configuration it seems like only the SYN packet is redirected to the local proxy, and all other packets are allowed to directly flow to the destination, leading (in theory) to a total mess (or all except SYN being blocked by the filter table). However, if I drop the --syn option and redirect ALL packets to the local proxy, the proxy does not work at all. Why?

2) Regarding the 4th rule in the filter table, why do I need to explicitly allow outgoing established connections? The proxy is the only application that is allowed to send packets to non-localhost destinations anyway, and it already is allowed to do so (rule 3), so what do I need the 4th rule for? It seems like it allows non-proxy connections to circumvent the proxy.

Thank you!

3 Answers 3



  1. The reason you only want to match SYNs is twofold. First, all subsequent established packets will get passed by conntrack (the second line you asked about). Anything that is not matched by conntrack and is also not a SYN is an unestablished packet and doesn't belong. It is therefore ignored at this point and then finally gets dropped finally by the last rule in your filter table. This is a way of protecting your proxy process from the activity of your users. E.g., some forms of network probes start sending with ACK or FIN just to see how the remote will react, and some applications die horribly when they receive malformed/unexpected packets.

  2. Why explicitly allow the conntrack-ed traffic? Because the last line indiscriminately drops everything. Leaving the drop and removing the conntrack would drop packets from your proxy talking back to clients. There is a very fine distinction here. The lines that match based on uid owner only match packets generated by the proxy owner. Incoming packets from clients that are delivered to the proxy are not owned by the proxy.

Consider the following diagram:

[ client ] <---traffic---> [ proxy ] <---traffic---> [ target ]

The traffic on the left between the client and proxy is not owned by the proxy (it was created by an untrusted source outside the system), and thus does not match filter line 3, which means without filter line 4 it will get dropped by filter line six.

The traffic on the right between the proxy and target is owned by the proxy (it was created by a process running under a local UID), and thus is always permitted by nat line 4 and filter line 3.

In your case specifically, since it's all running locally this might not be quite the best approach. There are myriad ways that you can roll the iptables rules. What it really comes down to is that this should still work for you. If you learn more about iptables you can massage the rules, but you can leave it as is and be fine too.

I hope this helps. It is a rather complex topic.


Both parts of your question are linked.

Part (1) captures a SYN packet and redirects it as you suggest. From this point conntrack (2) takes over and recognises that each subsequent packet in that stream is part of the same connection and redirects it in the same way as the original SYN packet.

An overview of Connection Tracking can be found at http://en.wikipedia.org/wiki/Netfilter#Connection_Tracking


I need to use iptables to redirect the traffic

No - you just set up your network so this is the only host with access to the internet and tell everything else to use it as the router.

The other stuff you need is just NAT/masquerading - trying to make it behave as a proxy is just silly.

  • I don't understand your answer at all. This is NOT a network, it's a single computer, so your first sentence is moot. The second sentence does not make sense to me, either. Why is making a proxy behave as a proxy "just silly"?
    – BlueShirm
    Sep 26, 2011 at 15:49
  • By the way, I have seen this configuration proposed a lot on different websites, so I think it's pretty common.
    – BlueShirm
    Sep 26, 2011 at 15:51

You must log in to answer this question.

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