我希望能够远程连接到暴露了 JMX 的 Java 服务,但是它被防火墙阻止了。我尝试使用 ssh 本地端口转发,但是连接失败。查看wireshark,似乎当您尝试与jconsole连接时,它希望在连接到端口9999后通过一些临时端口进行连接,这些端口被防火墙阻止。
有没有办法让 jconsole 只通过 9999 连接或使用代理?这篇文章仍然是最好的解决方案吗?或者,我错过了什么?
我希望能够远程连接到暴露了 JMX 的 Java 服务,但是它被防火墙阻止了。我尝试使用 ssh 本地端口转发,但是连接失败。查看wireshark,似乎当您尝试与jconsole连接时,它希望在连接到端口9999后通过一些临时端口进行连接,这些端口被防火墙阻止。
有没有办法让 jconsole 只通过 9999 连接或使用代理?这篇文章仍然是最好的解决方案吗?或者,我错过了什么?
由于 JConsole 支持 SOCKS,因此使用 SSH socks 隧道有更好的方法:
在某个空闲端口(例如 7777)上本地创建 SSH socks 代理:
ssh -fN -D 7777 用户@防火墙主机
通过指定 SOCKS 代理(例如 localhost:7777)和 JMX 服务器的地址(例如 localhost:2147)来运行 JConsole
jconsole -J-DsocksProxyHost=localhost -J-DsocksProxyPort=7777 服务:jmx:rmi:///jndi/rmi://localhost:2147/jmxrmi -J-DsocksNonProxyHosts=
如以下答案之一所述,从 JDK 8u60+ 开始,您还需要-J-DsocksNonProxyHosts=
选择才能使其正常工作。
对于几乎所有当前的 JDK 版本(7u25 或更高版本),现在可以很容易地通过 SSH 使用 JConsole 和 Visual JVM(因为现在您可以将 JMX 绑定到单端口)。
我使用以下 JVM 参数
-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
然后我启动 SSH 连接
ssh my.javaserver.domain -L 8090:127.0.0.1:8090
在我可以从 JConsole 连接之后
远程进程:-> localhost:8090
和 Java Visual VM
右键单击本地 -> 添加 JMX 连接 -> localhost:8090
有没有办法让 jconsole 只通过 9999 连接或使用代理?这篇文章仍然是最好的解决方案吗?或者,我错过了什么?
是的,那篇文章是对的。
当您在服务器上指定 JMX 端口 ( -Dcom.sun.management.jmxremote.port=####
) 时,实际上您只是指定了应用程序的注册表端口。当你连接它时,它会提供一个额外的服务器端口,jconsole 实际上会使用它来完成所有工作。要转发工作,您需要知道注册表和服务器端口。
在注册表和服务器端口都设置为 8000 的情况下,类似以下内容应该可以运行您的应用程序。有关详细信息,请参见此处。
-Dcom.sun.management.jmxremote.port=8000
-Dcom.sun.management.jmxremote.rmi.port=8000
-Djava.rmi.server.hostname=127.0.0.1
顺便说一句,我的SimpleJMX 库允许您轻松设置两个端口,并且您可以将它们都设置为同一个端口。
因此,一旦您知道需要转发的两个端口,您就可以设置您的ssh
命令。例如,如果您将注册表和服务器端口配置为 8000,您将执行以下操作:
ssh -L 8000:localhost:8000 remote-host
这将创建一个本地端口 8000,该端口转发到远程主机上的 localhost:8000。-L
如果需要转发多个端口,可以指定多个参数。然后你可以将你的 jconsole 连接到 localhost:8000 ,它将适当地连接到远程主机。
此外,如果您的服务器有多个接口,您可能需要将java.rmi.server.hostname
变量设置为绑定到正确的接口。
-Djava.rmi.server.hostname=10.1.2.3
继续使用 SSH socks 方法,使用较新的 java 版本(大约 8u66),您还需要将 socksNonProxyHosts 设置为空,从而导致:
jconsole -J-DsocksProxyHost=localhost -J-DsocksProxyPort=7777 -J-DsocksNonProxyHosts=