5

While there appears to some documentation on how to expose JMX through various firewall and tunneling schemes, I sort of want the opposite. I want to ensure that JMX is only accessible to local machine. Unfortunately it appears that the "out of the box" management options do not allow restricting the ports to a local interface and netstat shows them listening on any/all interfaces.

http://java.sun.com/javase/6/docs/technotes/guides/management/agent.html#gdevf

I have to admit I am bewildered by the layers of indirection in JMX, the RMI registry, connectors, adapters, etc.

I would like to just turn it on and then tunnel through SSH as opposed to exposing it to the world and then having to perform arduous and superfluous user management and security configuration. It would be nice to be able to use a built in RMI registry and not have to run an external one.

4

4 回答 4

3

如果您从本地主机访问,那么在这种情况下,可以执行 JConsole 和 JVisualVM 所做的事情,即使用 Attach API 来查找服务器的仅限本地地址(如果您使用 - Dcom.sun.management.jmxremote 但不是 -Dcom.sun.management.jmxremote.port=N) 并连接到它。在另一个答案中,Thraidh 说即使在这种情况下也打开了一个可远程访问的端口,这在早期版本中是正确的,但几年来一直没有。

Fredrik 的解决方案有效,但过于矫枉过正。您只需要定义一个 RMIServerSocketFactory,而不是一个 RMISocketFactory(它定义了客户端和服务器)。这消除了专门配置客户端的需要。http://vafer.org/blog/20061010091658上的代码对我来说是正确的。

使用诸如 -Dcom.sun.management.jmxremote 之类的命令行属性构建的“开箱即用”管理只能在您需要开始使用 JMX API 本身进行编程之前带您到此为止。我们通常不愿意让开箱即用的管理演变成一个完整的并行 API,这就是为什么有这样的问题是无法解决的。我们在这里解释如何从一个到另一个。

Éamonn McManus,JMX 规范负责人

于 2009-12-31T14:03:05.620 回答
2

答案有点晚了,但如果对您(或其他人)来说仍然是个问题,我认为这可以解决问题:

import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.net.*;
import java.rmi.registry.LocateRegistry;
import java.rmi.server.RMISocketFactory;

import javax.management.MBeanServer;
import javax.management.remote.*;

public class LocalJMXPort {
    public static void main(String[] args) {
        try {
            int port = 12468;
            // Create an instance of our own socket factory (see below)
            RMISocketFactory factory = new LocalHostSocketFactory();

            // Set it as default
            RMISocketFactory.setSocketFactory(factory);

            // Create our registry
            LocateRegistry.createRegistry(port);

          // Get the MBeanServer and setup a JMXConnectorServer
            MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
            JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://127.0.0.1:"+port+"/jndi/rmi://127.0.0.1:"+port+"/jmxrmi");
            JMXConnectorServer rmiServer = JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs);
            rmiServer.start();

            // Say something
            System.out.println("Connect your jconsole to localhost:"+port+". Press a key to exit");

            // Wait for a key press
            int in = System.in.read();
            //Exit
            System.out.println("Exiting");
            System.exit(0);
        } catch(Exception ex) {
            ex.printStackTrace();
        }
    }

    static private class LocalHostSocketFactory extends RMISocketFactory {
        public ServerSocket createServerSocket(int port) throws IOException {
            ServerSocket ret = new ServerSocket();
            ret.bind(new InetSocketAddress("localhost", port));
            return ret;
        }

        public Socket createSocket(String host, int port) throws IOException {
            return new Socket(host, port);
        }
    }
}

我只是把它放在一起,我可能做了一些非常愚蠢的事情,因为我唯一的目标是让它绑定到 localhost:port 而不是 *:port 并且这部分似乎有效。

如果有什么可以改进或只是愚蠢的,请随时发表评论。

于 2009-03-18T22:59:15.927 回答
1

Can't help with the sun way of doing it. Even after jmx adapters started coming with the jdk (6 i think?) I kept using mx4j for the least-effort adapter setup. It is trivial to start up an mx4j http adapter on 127.0.0.1 or an internal-only interface. Then SOP was to ssh in with port forwards or use scripts with wget commands.

http://mx4j.sourceforge.net/

于 2008-12-07T01:39:06.993 回答
1

不幸的是,目前没有办法做到这一点。

根据 Sun 文档,一个单独的 -Dcom.sun.management.jmxremote 应该只打开一个本地端口,而 -Dcom.sun.management.jmxremote.port= 打开一个可远程访问的端口。

两种方式都会打开一个额外的随机端口,可以从远程访问。

我见过 -Dcom.sun.management.jmxremote.host=,但这似乎没有任何效果。

我得出的结论是没有办法,并使用本地防火墙来屏蔽服务器。

于 2009-02-18T15:40:40.230 回答