如何将 JMX 配置为仅绑定到本地主机?

How to configure JMX to bind to localhost only?

I 运行 Tomcat8 在 Centos6 上使用 JDK8。 我使用以下选项启用 JMX:

CATALINA_OPTS="${CATALINA_OPTS} -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9123 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.local.only=true"

不幸的是,当我检查打开了哪些端口时,我发现这些端口侦听所有 IP:

netstat -plunt | grep java
Proto Recv-Q Send-Q Local Address               Foreign Address             State       PID/Program name
tcp        0      0 :::60555                            :::*                LISTEN      22752/java
tcp        0      0 ::ffff:127.0.0.1:8080               :::*                LISTEN      22752/java
tcp        0      0 :::9123                             :::*                LISTEN      22752/java
tcp        0      0 :::40867                            :::*                LISTEN      22752/java

我想如果我配置 -Dcom.sun.management.jmxremote.local.only=true 所有端口都应该只绑定到本地主机(::ffff:127.0.0.1 将出现在所有端口之前)。

如何配置 JMX 以仅绑定到本地主机?

已添加

我不创建 JMX 我使用 Tomcat JMX:https://tomcat.apache.org/tomcat-8.0-doc/monitoring.html

据我了解this answer and read Oracle's docs about it, there seems to be no way to configure it without coding. This在章节"Connector server attributes"中说:

When using the default JRMP transport, RMI socket factories can be specified using the attributes jmx.remote.rmi.client.socket.factory and jmx.remote.rmi.server.socket.factory in the environment given to the RMIConnectorServer constructor. The values of these attributes must be of type RMIClientSocketFactory and RMIServerSocketFactory, respectively. These factories are used when creating the RMI objects associated with the connector.

我看到的唯一选择是实现像 here 这样的自定义工厂,并将类名与类路径中的 JAR/class 一起传递给 属性。

如有错误请指正

你问的是不必要的。

com.sun.management.jmxremote.local.only=true(顺便说一句,这已经是默认设置)意味着它只会 接受来自本地主机的 连接。这并不意味着它只会像您假设的那样绑定到环回接口。不接受来自不在本地主机上的连接只是另一种方式。从 sun.management.jmxremote.LocalRMIServerSocketFactory 你可以看到它是这样完成的:

// Walk through the network interfaces to see
// if any of them matches the client's address.
// If true, then the client's address is local.
while (nis.hasMoreElements()) {
    NetworkInterface ni = nis.nextElement();
    Enumeration<InetAddress> addrs = ni.getInetAddresses();
    while (addrs.hasMoreElements()) {
        InetAddress localAddr = addrs.nextElement();
        if (localAddr.equals(remoteAddr)) {
            return socket;
        }
    }
}

为什么这样做而不是绑定到环回,我不知道。但我相信它同样安全。 (也许不是?)

但如果你真的想要,那么由于 Java 8u102 和 Java 7u131 系统 属性 com.sun.management.jmxremote.host 将底层 RMI 注册表绑定到选定的网络接口。该值可以是 InetAddress.getByName(String).

接受的任何字符串

示例:

-Dcom.sun.management.jmxremote.host=localhost

有关详细信息,请参阅:JDK-6425769

链接:Java 8u102 Release Notes

文档在任何地方都没有提到的是,即使设置了 com.sun.management.jmxremote.host,您仍然会看到一个绑定到所有网络接口的 JMX 端口。这是因为如果 com.sun.management.jmxremote.local.only=true 那么 sun.management.jmxremote.LocalRMIServerSocketFactory 的实例将被启动并且该实例不允许自定义,即它不遵守 com.sun.management.jmxremote.host 属性。如果那是错误、JDK-6425769 实施中的疏忽或故意的,我不知道。