I finally managed to accomplish this with ssh
only:
- start a local SOCKS proxy on your client machine (using
ssh -D
) EDIT: not necessary with SSH>7.6
- connect to remote server and setup a reverse port forwarding (
ssh -R
) to your local SOCKS proxy
- configure the server software to use the forwarded proxy
1. Start local socks proxy in the background
EDIT SSH>7.6 allow a simpler syntax to start the proxy. Skip this and continue with step 2!
Connect to localhost via SSH and open SOCKS proxy on port 54321.
$ ssh -f -N -D 54321 localhost
-f
runs SSH in the background.
Note: If you close the terminal where you started the command, the proxy process will be killed. Also remember to clean up after yourself by either closing the terminal window when you are done or by killing the process yourself!
2. connect to remote server and setup reverse port forwarding
Bind remote port 6666 to local port 54321. This makes your local socks proxy available to the remote site on port 6666.
$ ssh root@target -R6666:localhost:54321
EDIT SSH>7.6 allows a simpler syntax to start the proxy! Step 1 is not needed then:
$ ssh root@target -R6666:localhost
3. configure the server software to use the forwarded proxy
Just configure yum, apt, curl, wget or any other tool that supports SOCKS to use the proxy 127.0.0.1:6666
.
Voilá! Happy tunneling!
4. optional: install proxychains to make things easy
proxychains
installed on the target server enables any software to use the forwarded SOCKS proxy (even telnet
). It uses a LD_PRELOAD
trick to redirect TCP and DNS requests from arbitrary commands into a proxy and is really handy.
Setup /etc/proxychains.conf
to use the forwarded socks proxy:
[ProxyList]
# SSH reverse proxy
socks5 127.0.0.1 6666
Tunnel arbitrary tools (that use TCP) with proxychains
:
$ proxychains telnet google.com 80
$ proxychains yum update
$ proxychains apt-get update
Okay, turns out it's a "bug" in the latest version of Mac OS X Server. From what I was able to find, he IKE daemon racoon
won't accept connections if the source port is not UDP 4500. Most connections that go through NAT will randomize the source port, which means it won't connect. The old version of the daemon doesn't have this restriction. Connections from inside the network won't randomize the port if connecting directly to the server's IP, but loopback and external connections apparently will, leading to the failures.
The quick solution, then, was to replace the racoon
binary with an old version from OS 10.8, of course backing up the old one by naming it racoon.old
(or would racoon.new
be more correct? :D).
Apple do appear to be aware of the issue and hopefully they'll issue a fix; in the meantime, reverting the binary works.
Best Answer
Encapsulating Security Protocol (ESP) is IP protocol 50. It has a protocol number in its own right, just as ICMP, TCP and UDP do, and is arguably the right protocol to use for encrypted tunnels.
However, although TCP and UDP have both ip addresses and port numbers associated with both source and destination, ICMP and ESP don't. It's the combination of ports and addresses that make NAT and tunneling practical; without them, traffic is very difficult to handle.
The problem is that, when a tunneling (or NAT) device has two or more input UDP streams to pass on to a single endpoint, and the responses come back from that endpoint to the tunneling device, the source port numbers can be used to disambiguate the two streams. With ESP, there is no port number to serve as disambiguator, so it's hard for the tunneling endpoint to know which of several ESP sources that ESP response should be tunneled back to.
IPSec, which by default also uses ESP, some time ago codified the NAT-traversal extensions, which use UDP/4500 instead. I don't know that L2TP has such a mode, and without it, I fear you won't be able to do what you want to do.
I hope I'm wrong about that, and that someone else will come along and post a better answer. But in the absence of that, I thought I should at least try to explain what ESP is, and why it is a tunneling headache.