I was recently in a situation where I had a client experiencing a problem in a Java app that I couldn’t recreate on my machine. The only solution was to do some remote debugging. Unfortunately both he and I were behind NAT firewalls, circumstances that neither one of us could change.
Fortunately SSH provides a solution through port forwarding, providing you have some publicly accessible host to serve as an intermediate. The process is made a bit more complicated as my intermediate host only allows incoming connections on particular ports. So I needed to set up a two sets of port-forwarding. As I always end up confusing myself with the meanings of SSH’s “-L” and “-R”, I thought I’d write up the recipe (mostly for my own benefit).
In the following I’ll use “C” to refer to the client’s remote machine, “L” to refer to my own machine, and “I” for the publicly-accessible host. Basically I needed to forward a port (C) from the remote machine to the intermediate (Ip), and then a port from the intermediate (Ip) to my local machine (Lp). The client’s app was configured to connect to Cp, and my debugger configured to wait for an incoming connection on port Lp. In my case I used Lp = Cp = 8000 and Ip = 6789 to avoid as much confusion as possible!
- On L (my dev machine): start a debugging session listening on port Cp (8000). In Eclipse, this means setting the Connection Type to “Standard (Socket Listen)”.
- On C (client’s machine): cause connections to the port Cp (8000) on the client’s machine to be forwarded to Ipon the intermediate:
$ ssh -L 8000:localhost:6789 account@intermediate sleep 3000
- On L (my dev machine): cause connections to port Ip (6789) on the intermediate to be forwarded to Lp(8000) on my local dev machine:
$ ssh -R 6789:localhost:8000 account@intermediate sleep 3000
- On C (client’s machine): start the app; if you want it to suspend immediately on start, change the “
suspend=n” to “
$ java -Xdebug -Xnoagent \ -Xrunjdwp:transport=dt_socket,address=8000,server=n,suspend=n \ …appargs…
or for Eclipse deployed apps:
$ rcplauncher …appargs… \ -vmargs -Xdebug -Xnoagent \ -Xrunjdwp:transport=dt_socket,address=8000,server=n,suspend=n
Plink from the PuTTY distribution is a great SSH implementation for Windows machines.