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.
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:
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
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
--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.