Java – spring: you cannot connect to JMX server from behind the firewall using RMI
My spring application runs on the machine behind the NAT firewall (pfsense) The internal IP of the machine is a.b.c.d and the NAT IP is w.x.y.z
The serviceurl configured by spring is set as my internal IP (a.b.c.d) on port 1100. 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
As shown above, I set - DJava rmi. server. Hostname = w.x.y.z to connect to the application through NAT I also opened the relevant port on the machine firewall and set the port from w.x.y.z: 1100 to a.b.c.d: 1100
When I tried to connect to the application from outside the network using jconsole on w.x.y.z: 1100, I got 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)
If I try to connect using jconsole on w.x.y.z: 1099, I will receive Java rmi. Connectexception How do I expose my JMX MBean outside the 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
Interestingly, I can use telnet to connect to two ports (1099 and 1100) on w.x.y.z
The relevant parts of my spring configuration are:
<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>
Note: I don't use any servlet containers
Editor: the first answer provides me with the basis to solve my specific problem, which can be seen in the second answer
Solution
Use COM sun. management. jmxremote. The initial port defined by port is called registry port and is only used to start negotiation and determine the next port for "real" communication Java RMI mechanism uses dynamically allocated ports, which is usually incompatible with firewalls
What port is used by Java RMI connection?
In other words, for JMX, it can be solved
a) Lock both ports using system properties (Java 7 required)
com.sun.management.jmxremote.port com.sun.management.jmxremote.rmi.port
b) Use custom code to request a specific port See jconsole over SSH local port forwarding
You can also see:
> Why Java opens 3 ports when JMX is configured? > http://realjenius.com/2012/11/21/java7-jmx-tunneling-freedom/