How to use JProfiler over two-hop SSH tunnel - java

I'm trying to connect JProfiler to a JVM running on a server that I'll call remote. This server is only accessible from my workstation (local) via another server that I'll call middle. My plan for connecting JProfiler to remote was this:
Install the JProfiler instrumentation on remote
Establish SSH tunnel from local, through middle, to remote:
ssh -v -N -L 8849:[remote's private address (192.168... etc)]:8849 [middle]
Establish a new JProfiler session on localhost:8849, choosing "Startup immediately, connect later with JProfiler GUI"
However, I end up getting an error:
Connection error
Either an old version of the native library is used or another
application is listening on port 8849. Please check your
DYLD_LIBRARY_PATH environment variable and your port configuration
I don't have any other programs bound to local port 8849, aside from my SSH tunnel, and I have confirmed that the SSH tunnel itself should be working correctly - I'm able to forward connections for a test HTTP server from remote to local via a similarly configured tunnel.
I found this similar question, but no solution was provided.
What am I missing from my configuration?

A direct tunnel is established with
ssh -t user#remote -L [localPort]:localhost:[remotePort] -N
A 2-hop tunnel is built with chained ssh commands:
ssh -t user#middle -L [localPort]:localhost:[remotePort] \
ssh -t user#remote -L [remotePort]:localhost:[remotePort] -N
where localPort is the port you want to use locally, and remotePort is the port that the profiling agent is listening on. All of this is executed in a single command on your local machine. More hops can be added with additional ssh calls like in the first line. There must by exactly one trailing -N for the entire command.
This approach works with JProfiler.
If the tunnels fails or if the profiling agent is not listening, you will get the message that you mentioned because of the way that the connection fails in the case of an SSH tunnel.

Related

Need help in java Port forwarding in socket (AWS CISCO router with AWS Server)

I am having a aws server(10.10.10.1) which will act as a CISCO Router and it will port forward to another aws server(10.10.10.2). Now I am connecting a server in ssh using the following command.
ssh -i server.pem ec2-user#10.10.10.1 -p 2222
Then it will connect to the Server 10.10.10.2.
Now I need to run a socket program there and I need a client(Which will run in local) program to connect that.
I tried in many ways but I am not able to connect that.
I am new in socket programming please help me to sort out.
Below Answer Result:
I have tried to connect through the SSH tunnel and the tunnel is working for the router and it is not going to the aws server
Please see my tunnel command,
ssh -i server.pem -L 9080:10.10.10.2:8090 ec2-user#10.10.10.1
I also ran a Socket server code in 10.10.10.2 and the client code in my local machine.
Please help me to sort it out
This is your layout
DEV ---ssh---> PIVOT ---ssh---> SERVER
There's an SSH feature called port forwarding that allows the user to open a listening (server) socket on one end of the connection (-L for local, -R for remote) and proxy all socket reads and writes to another machine reachable from that end.
Since PIVOT can connect to SERVER you simply need a proxy on your DEV machine:
me#dev$ ssh -L 9005:server:80 pivot
And then when you talk to localhost:9005 on the development machine you are in fact talking to server:80 via the SSH channel.
Note: if host A can't directly connect to the server and you use it to ssh into B that can, you actually have to setup two forwards, one for each SSH bridge.

JProfiler, connecting to a machine behind a firewall

I am trying to use JProfiler on my MAC to connect to a machine remotely that is behind a firewall and only accessible via a Linux machine.
I have set up a direct SSH tunnel as follows:
ssh -L 8849:remote:8849 forwardingmachine
And start Jprofiler with
java -agentpath:/path/jprofiler8/bin/linux-x64/libjprofilerti.so=port=8849 ..."
I systematically get the error:
Connection error
Either an old version of the native library is used or another
application is listening on port 8849. Please check your
DYLD_LIBRARY_PATH environment variable and your port configuration
Online there are solutions for using a 2 hop SSH tunnel, but I can't do that due to the second machine only being accessible to forwardingmachine.
Any ideas of how to get around this?
(The remote machine uses Java 1.7, whereas my Mac uses Java 1.8). Both machines are using jprofiler8
A direct tunnel to remote is set up with the command
ssh -t user#remote -L [localPort]:localhost:[remotePort] -N

Run JConsole from server over SSH

I deployed a Java app to server and need to run Jconsole for profiling. I connected to server over SSH and run jconsole, however I got an error
No X11 DISPLAY variable was set, but this program performed an operation which requires it.
How can I run JConsole over SSH on my client machine?
when connection to the server, enable X forwarding with ssh -X $servername

JConsole over ssh local port forwarding

I'd like to be able to remotely connect to a Java service that has JMX exposed, however it is blocked by a firewall. I have tried to use ssh local port forwarding, however the connection fails. Looking at wireshark, it appears that when you try to connect with jconsole, it wants to connect via some ephemeral ports after connecting to port 9999, which are blocked by the firewall.
Is there any way to make jconsole only connect through 9999 or use a proxy? Is this article still the best solution? Or, am I missing something?
There's an even nicer way to do this using an SSH socks tunnel, since JConsole supports SOCKS:
Create the SSH socks proxy locally on some free port (e.g. 7777):
ssh -fN -D 7777 user#firewalled-host
Run JConsole by specifying the SOCKS proxy (e.g. localhost:7777) and the address for the JMX server (e.g. localhost:2147)
jconsole -J-DsocksProxyHost=localhost -J-DsocksProxyPort=7777 service:jmx:rmi:///jndi/rmi://localhost:2147/jmxrmi -J-DsocksNonProxyHosts=
As mentioned in one of the answers below, from JDK 8u60+ you also need to have the -J-DsocksNonProxyHosts= option in order to get it working.
With almost all current JDK versions (7u25 or later) it's now possible to use JConsole and Visual JVM over SSH quite easily (because now you can bind JMX to single port).
I use the following JVM parameters
-Dcom.sun.management.jmxremote.port=8090
-Dcom.sun.management.jmxremote.rmi.port=8090
-Djava.rmi.server.hostname=127.0.0.1
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
Then I launch SSH connection
ssh my.javaserver.domain -L 8090:127.0.0.1:8090
After I can connect from JConsole
Remote Process: -> localhost:8090
And Java Visual VM
Right Click on Local -> Add JMX Connection -> localhost:8090
Is there any way to make jconsole only connect through 9999 or use a proxy? Is this article still the best solution? Or, am I missing something?
Yes, that article is about right.
When you specify the JMX port on your server (-Dcom.sun.management.jmxremote.port=####), you are actually specifying just the registry-port for the application. When you connect it provides an additional server-port that the jconsole actually does all of its work with. To get forwarded to work, you need to know both the registry and server ports.
Something like the following should work to run your application with both the registry and server ports set to 8000. See here for more details.
-Dcom.sun.management.jmxremote.port=8000
-Dcom.sun.management.jmxremote.rmi.port=8000
-Djava.rmi.server.hostname=127.0.0.1
As an aside, my SimpleJMX library allows you to set both ports easily and you can set them both to be the same port.
So, once you know both the port(s) you need to forward, you can set up your ssh command. For example, if you configure the registry and server ports as 8000, you would do:
ssh -L 8000:localhost:8000 remote-host
This creates a local port 8000 which forwards to localhost:8000 on the remote-host. You can specify multiple -L arguments if you need to forward multiple ports. Then you can connect your jconsole to localhost:8000 and it will connect to the remote-host appropriately.
Also, if your server has multiple interfaces, you may need to set the java.rmi.server.hostname variable to bind to the right interface.
-Djava.rmi.server.hostname=10.1.2.3
Continuing the SSH socks method, with newer java versions (around 8u66) you also need to set socksNonProxyHosts empty resulting in:
jconsole -J-DsocksProxyHost=localhost -J-DsocksProxyPort=7777 -J-DsocksNonProxyHosts=

Java exec or runtime not working with ssh

I'm trying to ssh into ubuntu using exec, but for some reason when I execute from the code I get the error
port 22: Connection refused
In the code I use concat to put the strings together, but I know they're put together properly because I print them out and if I copy and paste them into the command line then it will ssh properly.
My code tries:
p1= Runtime.getRuntime().exec(run1);
p1.waitfor();
where
run1 = "ssh -o StrictHostKeyChecking=no -v -i key " + "ubuntu#"+ DNS + " sudo mke2fs -F -j "+device;
Any ideas?
You are initiating the connection, so for it to be refused it means that the machine you are attempting to ssh into is denying you ssh access.
Log into that machine by whatever means you have and verify that the ssh server is running. If it is, then verify that the firewall is not blocking port 22; because, sometimes the ssh server is running but the firewall won't allow network access to the ssh server due to a port blocking rule.
--- Edited after question in comments ---
Is there a difference between ssh in the command line and using exec? Because I can
connect to the server through the command line, which I assume is still using port 22.
So if I can ssh that way does that mean port 22 is working?
There are a few possibilities. Java comes with a Security Manager which only serves to deny programs access to machine resources. This is why it is possible to safely run applet code, which is downloaded from remote servers, as the Security Manager denies permission to access the hard drive or make connections to other machines. In the applet sandbox, it does allow connections back to the originating web server (to download more code and images).
However, the lack of a security exception directs the suspicion away from the Security Manager. The fact that the message uses the words "Connection refused" is a strong indicator that the SSH server you are connecting to won't accept a connection from you.
Perhaps by operating on the command line, the ssh command is using a different environment or configuration. I would see if the command is aliased, of if the ssh connection makes some assumption about key pairs. If nothing seems to be out of line with the command, I would check that your program is connection with ssh version 2 (version 1 is not allowed by many due to a security hole).
Then I would also hunt around for possible differences in name resolution. You might be resolving the hostname in the command line differently than you are resolving it from the Java program. This could mean that the Java program is attempting connection to a different machine, one which doesn't have a secure shell server running.
Either way, it seems that you'll have to do a bit of debugging to isolate if it is a true coding problem or an environmental issue.
If you are getting Connection refused, the SSHD is not running or you are being blocked by Firewall (or similiar).

Categories

Resources