5

I need to hack the OS X pf to redirect all ssh connections from an user to this machine. I want, when doing

$ ssh google.com

to get the same results as with

$ ssh localhost

ie a connection to my locally running sshd.

Under a recent Linux, this would simply be:

# iptables -t nat -A OUTPUT -p tcp --dport 22 -m owner --uid-owner theuser -j REDIRECT

Under OS X 10.8, there appear to be 2 methods - ipfw and pf. Neither works. Ipfw:

# ipfw flush
# ipfw add 50 fwd 127.0.0.1,22 tcp from any to any 22 uid theuser

If I drop the uid theuser part, the redirect works, minus the user thingie. If I leave the uid directive there, the network stack dies and the system shortly becomes unusable; no more ipfw, no more ps, no more kill.

According to the man pages, ipfw is deprecated, so packet filter should be used instead:

# sysctl -w net.inet.ip.forwarding=1

Then I added

anchor "910.Custom/*"
load anchor "910.Custom" from "/etc/pf.anchors/910.Custom"

in /etc/pf.anchors/com.apple and

rdr on en1 proto TCP from any to any port 22 -> 127.0.0.1 port 22

in /etc/pf.anchors/910.Custom (notice how I'm not mentioning anything about a user here, since the pf docs don't list such an option for rdr rules).

After I run # pfctl -ef /etc/pf.anchors/com.apple nothing happens. If I add garbage to /etc/pf.anchors/910.Custom or even if I dare add user theuser after the rdr rule, the firewall fitfully complains of the bad syntax.

Can the OS X kernel even perform NAT routing anymore, or did Apple yank out that functionality? If it can, am I missing anything?

LE. fixed iptables syntax

foxx1337
  • 169

1 Answers1

10

You can do it with PF as well. However, rdr only accepts incoming packets. Thus, you have to first route those packets to lo0, then add a rdr-rule there (which will catch them as they will be routed in from "somewhere") to send them to your local SSH-server.

The order is necessarily: rdr stuff, then filter stuff (like pass), but chronologically the 2nd rule will hit first (on $Out), which will then activate the first rule (on lo0).

# Output interface
Out = en0

# A macro to shorten rules below
Packets = "proto tcp from" $Out "to any port 22"

# Rule 1: Redirect those connections _after_ they were routed to lo0 below
rdr pass log on lo0 $Packets -> 127.0.0.1

# Rule 2: Route _first_ new IPv4 TCP connections leaving $Out to lo0
pass out on $Out route-to lo0 inet $Packets
poige
  • 9,730
  • 3
  • 28
  • 53
Dan
  • 351