Spring:无法从防火墙后面使用RMI连接到JMX Server [英] Spring: Cannot connect to a JMX Server using RMI from behind a firewall

查看:518
本文介绍了Spring:无法从防火墙后面使用RMI连接到JMX Server的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

My Spring应用程序在NAT防火墙(pfSense)后面的机器上运行。机器的内部IP是 abcd ,NAT IP是 wxyz

My Spring application is running on a machine that is behind a NAT firewall (pfSense). The machine's internal IP is a.b.c.d, and the NAT IP is w.x.y.z

Spring配置的serviceUrl在端口 1100 上设置为我的内部IP( abcd ),当我启动应用程序,我提供以下开关:

The Spring configuration's serviceUrl is set to my internal IP (a.b.c.d) on port 1100, and when I start the application, I provide the following switches:

 -Dcom.sun.management.jmxremote -Djava.rmi.server.hostname=w.x.y.z -Dcom.sun.management.jmxremote.port=1099 -Dcom.sun.management.jmxremote.local.only=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false

如上所示,我设置了 -Djava.rmi.server。 hostname = wxyz ,以便通过NAT连接到应用程序。我还打开了机器防火墙上的相关端口,并设置了一个从 wxyz:1100 abcd:1100

As shown above, I set -Djava.rmi.server.hostname=w.x.y.z in order to make it possible to connect to the application through the NAT. I have also opened up the relevant ports on the machine's firewall, and set up a port forward from w.x.y.z:1100 to a.b.c.d:1100

当我尝试使用 wxyz:1100 上的jconsole从网络外部连接到应用程序时,我得到一个 java.io.IOException:jmxrmi

When I then try to connect to the app from outside the network using jconsole on w.x.y.z:1100, I get a java.io.IOException: jmxrmi

 java.io.IOException: jmxrmi
at sun.tools.jconsole.ProxyClient.checkSslConfig(ProxyClient.java:236)
at sun.tools.jconsole.ProxyClient.<init>(ProxyClient.java:127)
at sun.tools.jconsole.ProxyClient.getProxyClient(ProxyClient.java:483)
at sun.tools.jconsole.JConsole$3.run(JConsole.java:524)
 Caused by: java.rmi.NotBoundException: jmxrmi
at sun.rmi.registry.RegistryImpl.lookup(RegistryImpl.java:136)
at sun.rmi.registry.RegistryImpl_Skel.dispatch(Unknown Source)
at sun.rmi.server.UnicastServerRef.oldDispatch(UnicastServerRef.java:409)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:267)
at sun.rmi.transport.Transport$1.run(Transport.java:177)
at sun.rmi.transport.Transport$1.run(Transport.java:174)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Transport.java:173)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:556)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:811)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:670)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:275)
at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:252)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:378)
at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknown Source)
at sun.tools.jconsole.ProxyClient.checkSslConfig(ProxyClient.java:234)

如果我尝试在 wxyz:1099 上使用jconsole连接,我得到 java.rmi.ConnectException(连接被拒绝)。如何在NATted防火墙之外公开我的JMX MBean?

If I try to connect using jconsole on w.x.y.z:1099, I get a java.rmi.ConnectException (Connection refused). How can I expose my JMX MBeans outside my NATted firewall?

 java.rmi.ConnectException: Connection refused to host: w.x.y.z; nested exception is: 
java.net.ConnectException: Operation timed out
at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:619)
at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:216)
at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:202)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:129)
at javax.management.remote.rmi.RMIServerImpl_Stub.newClient(Unknown Source)
at javax.management.remote.rmi.RMIConnector.getConnection(RMIConnector.java:2373)
at javax.management.remote.rmi.RMIConnector.connect(RMIConnector.java:297)
at sun.tools.jconsole.ProxyClient.tryConnect(ProxyClient.java:355)
at sun.tools.jconsole.ProxyClient.connect(ProxyClient.java:313)
at sun.tools.jconsole.VMPanel$2.run(VMPanel.java:292)
Caused by: java.net.ConnectException: Operation timed out
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:579)
at java.net.Socket.connect(Socket.java:528)
at java.net.Socket.<init>(Socket.java:425)
at java.net.Socket.<init>(Socket.java:208)
at sun.rmi.transport.proxy.RMIDirectSocketFactory.createSocket(RMIDirectSocketFactory.java:40)
at sun.rmi.transport.proxy.RMIMasterSocketFactory.createSocket(RMIMasterSocketFactory.java:147)
at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:613)
... 9 more

有趣的是,我可以连接到 wxyz上的两个端口( 1099 1100 使用 telnet

Interestingly enough, I can connect to both ports (1099 and 1100) on w.x.y.z using telnet.

我的Spring配置的相关部分是:

The relevant portion of my Spring configuration is:

<bean id="registry" class="org.springframework.remoting.rmi.RmiRegistryFactoryBean">
    <property name="port" value="1100" />
</bean>
<bean id="serverConnector" class="org.springframework.jmx.support.ConnectorServerFactoryBean" depends-on="registry">
    <property name="server" ref="mbeanServer" />
    <property name="objectName" value="connector:name=rmi" />
    <property name="serviceUrl" value="service:jmx:rmi://a.b.c.d:1100/jndi/rmi://a.b.c.d:1100/server" />
    <property name="environment">
        <props>
            <prop key="jmx.remote.jndi.rebind">true</prop>
        </props>
    </property>
</bean>
<bean id="mbeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBean">
    <!-- indicate to first look for a server -->
    <property name="locateExistingServerIfPossible" value="true"/>
</bean>

注意:我没有使用任何servlet容器。

Note: I am not using any servlet containers.

编辑:第一个答案为我提供了解决我的具体问题的基础,可以在第二个答案中看到。

EDIT: The first answer provided me with the basis for the solution to my specific problem, which can be seen in the second answer.

推荐答案

详细说明我使用链接和指针识别的解决方案 anttix 给了我答案。

Elaborating on the solution I identified using the links and pointers anttix gave me in his answer.

因此,如上面的答案所述,使用系统属性 com.sun.management.jmxremote.port com.sun.management.jmxremote.rmi.port 是解决方案的基础。

So, as mentioned in the answer above, using the system properties com.sun.management.jmxremote.port and com.sun.management.jmxremote.rmi.port is the basis for the solution.

我更改了我的Spring配置以删除注册表 serverConnector bean,因为这不允许我注册端口 1099 PermissionExceptions 导致我无法绑定到port 1099 ),并使用平台mbean服务器。

I changed my Spring config to remove the registry and serverConnector beans, as this was not allowing me to register port 1099 (PermissionExceptions resulted in my being unable to bind to port 1099), and used the platform mbean server.

我使用的Spring配置就是这样:

The Spring config I used was just this:

 <bean id="mbeanServer" class="java.lang.management.ManagementFactory" factory-method="getPlatformMBeanServer"/>

然后,我使用以下开关启动了应用程序:

Then, I started the application using the following switches:

 -Dcom.sun.management.jmxremote -Djava.rmi.server.hostname=w.x.y.z -Dcom.sun.management.jmxremote.port=1099 -Dcom.sun.management.jmxremote.rmi.port=1099 -Dcom.sun.management.jmxremote.local.only=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false

java.rmi.server.hostname 设置为NAT VIP wxyz 非常重要,因为我们需要能够从网络外部对本地创建的远程对象执行远程操作。

Setting the java.rmi.server.hostname to the NAT VIP w.x.y.z is critical as we need to be able to execute remote operations on locally created remote objects from outwith the network.

注意:此解决方案仅适用于Java 7u4或更高版本。

Note: This solution will only work on Java 7u4 or higher.

这篇关于Spring:无法从防火墙后面使用RMI连接到JMX Server的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆