Transparent proxying leaves sockets with SYN_RCVD in MacOS X 10.6 Snow Leopard (and maybe FreeBSD)

ipfwmac-osxosx-snow-leopardsquidtransparent-proxy

I'm trying to create a transparent proxy on my MacOS machine in order to port the
sshuttle ssh-based transproxy VPN from Linux. I think I almost have it working, but sadly, almost is not 100%.

Short version is this. In one window, start something that listens on port 12300:

$ while :; do nc -l 12300; done

Now enable proxying:

# sysctl -w net.inet.ip.forwarding=1
# sysctl -w net.inet.ip.fw.enable=1
# ipfw add 1000 fwd 127.0.0.1,12300 log tcp from any to any

And now test it out:

$ telnet localhost 9999   # any port number will do
  # this works; type stuff and you'll see it in the nc window

$ telnet google.com 80    # any host/port will do
  # this *doesn't* work!

After the latter experiment, I see lines like this in netstat:

$ netstat -tn | grep ^tcp4
tcp4       0      0  66.249.91.104.80       192.168.1.130.61072    SYN_RCVD
tcp4       0      0  192.168.1.130.61072    66.249.91.104.80       SYN_SENT

The second socket belongs to my telnet program; the first is more suspicious. SYN_RCVD implies that my SYN packet was correctly captured by the firewall and taken in by the kernel, but apparently the SYNACK was never sent back to telnet, because it's still in SYN_SENT.

On the other hand, if I kill the nc server, I get this:

$ telnet google.com 80
Trying 66.249.81.104...
telnet: connect to address 66.249.81.104: Connection refused
telnet: Unable to connect to remote host

…which is as expected: my proxy server isn't running, so ipfw redirects my connection to port 12300, which has nobody listening on it, ie. connection refused.

My uname says this:

$ uname -a
Darwin mean.local 10.2.0 Darwin Kernel Version 10.2.0: Tue Nov  3 10:37:10 PST 2009; root:xnu-1486.2.11~1/RELEASE_I386 i386

Does anybody see any different results? (I'm especially interested in Snow Leopard vs Leopard results, as there seem to be some internet rumours that transproxy is broken in Snow Leopard version) Any advice for how to fix?

Best Answer

Got it! I'm not sure if it's a bug in Snow Leopard, or some new security feature. But someone posted to the sshuttle mailing list the fix to the problem, which is simply this:

sysctl -w net.inet.ip.scopedroute=0

Running that command makes the above set of commands (in the question posted above) work correctly as it did in MacOS 10.5. Thus, transparent proxying works again.