Redirect local traffic to proxy port with iptables
I have a Ubuntu 12.04 host that has a squid proxy on it running on port 8080. I want to proxy all the web traffic from the host through squid using iptables. Is the correct method:
iptables -t nat -I OUTPUT -p tcp -d 127.0.0.1 --dport 80 -j REDIRECT --to-ports 8080
This is not working. When I browse to a page it appears normally, even when the proxy is disabled. Any suggestions appreciated.
Solution 1:
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
In your rule, IPTables will only redirect traffic destined for localhost to the proxy. This rule will redirect any traffic destined for port 80. In your rule, change -d to -s and it shall work.
Solution 2:
tl;dr Your command is very close. You need to remove the -d 127.0.0.1
fragment and ensure you run your proxy process as a different user and exclude that user from the filter with -m owner ! --uid-owner <other-username>
so the proxy doesn't have its traffic redirected to itself.
More detail
I found that most of the suggestions for configuring iptables
for transparent
proxy make the assumption that the proxy machine is on a separate host from the
clients. I want to proxy traffic that originates from my machine (and I also
run the proxy on the same machine).
The way I read your questions makes me think you want the same thing.
This blog post mentions the fix:
localhost too
If you want to run the client on the same machine as the server (you’re in a coffee shop on your laptop; have a pastry for me), we can’t use the PREROUTING table, because it only applies to packets coming from outside. What we can do is modify the destination port on packets OUTPUT by our client process. The catch is that it will also affect packets output by mitmproxy, and we’ll get into a routing loop.
There are probably several ways to solve this, but the one that worked for me was running mitmproxy as root, and making the iptables rule not apply to root-owned processes.
sudo iptables -t nat -A OUTPUT -p tcp -m owner ! --uid-owner root --dport 443 -j REDIRECT --to-port 8080
- -m owner: Load the owner module.
- ! –uid-owner root: Rule does not apply to root-owned processes
Remember that in this case you’ll run mitmproxy as root. This will also log all your https web browser traffic. Add
-m multiport
and replace--dport
with--dports
to intercept multiple ports (or just repeat the line with a different port).
And this mitmproxy forum thread has a solution so you don't have to run as root. You create a separate user specifically to run mitmproxy and then exclude that user's uid in the iptables filter.
I found that the thread linked in the comment by @keerthi isn't quite right because that is about forwarding a single port on localhost, whereas I think you want to forward all traffic.