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?
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:
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.
I've run into all sorts of weird issues with ipfw while doing things like this, and usually the reason is related to the fact that things pass through the same rule in both directions, when you really only meant one. divert rules + natd can be especially tricky to get right.
I don't have time to play with it for now, but you might want to try making a ruleset that causes packets from telnet -> {everything} to hit the fwd rule, but not the nc -> telnet packets.
The only thing I can do is guess here, just prying on a bit :P
So, my guess is that Avery's 10.2 is not yet patched for the bug: http://www.freebsd.org/cgi/query-pr.cgi?pr=kern/133732
Also described at kerneltrap.org/mailarchive/freebsd-current/2007/11/20/431855
While 10.5 already is. Makes sense to me given the release dates for Darwin. I guess we'll find out when emaste runs it on some older version too. Anyway, I do not run a BSD or Darwin, just got into this from Avery's blog post :P