How to connect VisualVM to directly invisible server using single port

Situation

I would like to check JVM state on my server using VisualVM and JMX. But I can’t connect directly to it because is behind firewall or in inaccessible network. Luckily I can connect through SSH to machine which can access my server.

situation

Naïve setup

I need to enable JMX for my application on server. Add following parameters into java command line of application:

-Dcom.sun.management.jmxremote.port=9872 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false

Check that you can connect to your application with this setting when debugging on local computer using JMX:

localconn.

Naïve solution

OK, so it works locally, great! Now try to deploy your app to server and try to run ssh with port forwarding from your computer:

ssh -L 9872:192.168.11.52:9872 user@72.15.87.44

So try to redirect port 9872 on server through tunnel between my and mediator computer to my local port 9872. But when I try to connect to localhost 9872 I get message:

error

(“Cannot connect to localhost:9872 using service:jmx:rmi:////jndi/rmi://localhost:9872/jmxrmi”)

The Problem

Beside communication on JMX port (in my case 9872) VisualVM tries to communicate by random other port using RMI. But because only one port was redirected this fails.

rmi_fail

Working setup

So let’s try to add 2 more parameters that will fix interface for RMI to 127.0.0.1:9872. So only one port will be used:

-Djava.rmi.server.hostname=127.0.0.1 -Dcom.sun.management.jmxremote.rmi.port=9872 -Dcom.sun.management.jmxremote.port=9872 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false

I use 127.0.0.1 because that should work on all computers and therefore this setting is suitable for installation package. If you can use fixed IP address you can avoid nesting of SSH tunnel below. But usage of loopback interface is more secure because should not be visible from outside of machine.

Working solution

  So now lets try to do nested port forwarding, please check that port 9872 is available on both mediator and your computer. If not, choose different one. On my computer launch:

ssh -L 9872:localhost:9872 user@72.15.87.44

That will open tunnel between my computer and mediator. Then on mediator (you can use opened console from command above) execute:

ssh -L 9872:127.0.0.1:9872 user2@192.168.11.52

And that will open tunnel between mediator and server. Add JMX connection to localhost:9872:

localconn

And voilà:

result

Tags:  Java  VisualVM  SSH