macOS packet filter (port forwarding)
I am trying to redirect the outbound traffic to destination port 80 to the local proxy port 127.0.0.1:8080 without success
/etc/pf.anchors/com.forwarding
rdr pass inet proto tcp from any to any port 80 -> 127.0.0.1 port 8080
/etc/pf.conf
scrub-anchor "com.apple/*"
nat-anchor "com.apple/*"
rdr-anchor "com.apple/*"
rdr-anchor "myproxy"
dummynet-anchor "com.apple/*"
anchor "com.apple/*"
load anchor "com.apple" from "/etc/pf.anchors/com.apple"
load anchor "myproxy" from "/etc/pf.anchors/com.forwarding"
Then:
sudo sysctl net.inet.ip.forwarding=1
sudo pfctl -ef /etc/pf.conf
The local traffic 127.0.0.1:80 is redirected to 127.0.0.1:8080, but not the external, the one towards internet.
You can only redirect incoming traffic. Any outgoing traffic to port 80 isn't affected by your rdr rule.
To redirect outgoing traffic to port 80 you have to re-route it first to lo0 then redirect it to the proxy port:
The order in the config file is necessarily rdr incomming packets, then filter packets (like pass), but chronologically the 2nd rule will hit first (on en0), which will then activate the first rule (on lo0).
# Step "2". redirect those same packets that were routed to lo0 below
rdr pass log on lo0 proto tcp from any to any port 80 -> 127.0.0.1 port 8080
# Step "1". Route new IPv4 TCP connections leaving en0 to lo0
pass out on en0 route-to lo0 proto tcp from en0 to any port 80 keep state
in pf.conf this would look like this:
...
scrub-anchor "com.apple/*"
nat-anchor "com.apple/*"
rdr-anchor "com.apple/*"
rdr pass log on lo0 proto tcp from any to any port 80 -> 127.0.0.1 port 8080
dummynet-anchor "com.apple/*"
anchor "com.apple/*"
load anchor "com.apple" from "/etc/pf.anchors/com.apple"
pass out on en0 route-to lo0 proto tcp from en0 to any port 80 keep state
In the above example I assume en0 is your only outbound en interface.
Unload your current pf.conf and stop pf: sudo pfctl -d
. Then add the two additional lines above. After modifying pf.conf check the syntax of the file with sudo pfctl -vnf /etc/pf.conf
which should result in the following output:
pfctl: Use of -f option, could result in flushing of rules
present in the main ruleset added by the system at startup.
See /etc/pf.conf for further details.
scrub-anchor "/*" all fragment reassemble
nat-anchor "/*" all
rdr-anchor "/*" all
rdr pass log on lo0 proto tcp from any to any port 80 -> 127.0.0.1 port 8080
anchor "/*" all
pass out on en0 route-to lo0 proto tcp from en0 to any port 80 flags S/SA keep state
dummynet-anchor "/*" all
and if successful load it with sudo pfctl -e -f /etc/pf.conf
.
A proper system and proxy configuration (and well-behaving apps) don't require such pf rules!