3

I'm trying to redirect all outgoing traffic from my local machine on port 843, to go to my local service on port 1234.

So, when I make a request to e.g. 1.2.3.4:843, I want it to connect to 127.0.0.1:1234 instead (transparently to the requesting application).

I'm on OS X so I'm trying to achieve this using pf.

Here's what I have:

ext_if = "en0"
int_if = "lo0"

rdr on $ext_if inet proto tcp from self to any port 843 -> 127.0.0.1 port 1234

Now when I do telnet 1.2.3.4 843 I would expect a connection on my local service (running on port 1234).

However it doesn't seem to redirect properly. Using tcpdump I can see that the packets are put on the interface with the destination 1.2.3.4.

If I do localhost only rule, e.g.

rdr on $int_if inet proto tcp from self to any port 843 -> 127.0.0.1 port 1234

Then telnet localhost 843 works as expected and I get the response from my local service which is listening on port 1234.

I'm not sure what I'm doing wrong and now I'm at a loss of ideas. Any help/pointers is appreciated.

EDIT:

I've tested a bit more and it seems as with the last rule, any request that lands on the loopback interface works. So telnet 127.2.3.4 843 also correctly redirects.

I tried adding $ext_if to above

rdr on { $ext_if $int_if } proto tcp from any to any port 843 -> 10.0.1.10 port 1234

But without success. I also added sysctl forwarding. Did nothing.

sudo sysctl -w net.inet.ip.forwarding=1
sudo sysctl -w net.inet6.ip6.forwarding=1

1 Answers1

0

As the comment said, rdr only handles incoming traffic, so you should redirect your outgoing traffic to 'incoming' traffic, i.e. redirect out to lo0.

Another problem you will encounter immediately in the following is the outgoing traffic of your local proxy is also redirected to itself, whichi is a infinite loop.

Here's a demo solving these problems, which copy from https://docs.mitmproxy.org/stable/howto-transparent/#macos

#The ports to redirect to proxy
redir_ports = "{http, https}"

#The address the transparent proxy is listening on tproxy = "127.0.0.1 port 8080"

#The user the transparent proxy is running as tproxy_user = "nobody"

#The users whose connection must be redirected.

#This cannot involve the user which runs the #transparent proxy as that would cause an infinite loop.

rdr pass proto tcp from any to any port $redir_ports -> $tproxy pass out route-to (lo0 127.0.0.1) proto tcp from any to any port $redir_ports user { != $tproxy_user }

Some important notes:

  • MUST leave a trailing line after the last rule, or you'll get a syntax error by pfctl
  • Run the proxy by the tproxy_user user, to avoid loop

I tested it with mitmdump on macOS 13 and worked

leavez
  • 101