java 如何配置 JMX 以仅绑定到 localhost?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/35367232/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 00:04:18  来源:igfitidea点击:

How to configure JMX to bind to localhost only?

javajmx

提问by Michael

I run Tomcat8 using JDK8 on Centos6. I enable JMX using the following options:

我在 Centos6 上使用 JDK8 运行 Tomcat8。我使用以下选项启用 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"

Unfortunately, when I check what ports are opened I discover that these ports listen to all IP:

不幸的是,当我检查打开了哪些端口时,我发现这些端口侦听所有 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

I suppose that if I configure -Dcom.sun.management.jmxremote.local.only=trueall ports should be bind to localhost only (::ffff:127.0.0.1will appear before all ports).

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

How to configure JMX to bind to localhost only?

如何配置 JMX 以仅绑定到 localhost?

Added

添加

I do not create JMX I use Tomcat JMX: https://tomcat.apache.org/tomcat-8.0-doc/monitoring.html.

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

采纳答案by Michael-O

As far as I understand thisanswer and read Oracle's docs about it, there seems to be noway to configure it without coding. Thissays in the chapter "Connector server attributes":

据我了解这个答案并阅读了有关它的 Oracle 文档,似乎没有办法在没有编码的情况下配置它。在“连接器服务器属性”一章中说:

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

使用默认的 JRMP 传输时,可以使用属性指定 RMI 套接字工厂,jmx.remote.rmi.client.socket.factoryjmx.remote.rmi.server.socket.factory在给定RMIConnectorServer构造函数的环境中指定。这些属性的值的类型必须是RMIClientSocketFactoryRMIServerSocketFactory分别。这些工厂在创建与连接器关联的 RMI 对象时使用。

The only option I see is to implement a custom factory like hereand pass the classname to the property along with the JAR/class in classpath.

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

Correct me if I am wrong.

如果我错了,请纠正我。

回答by peterh

What you ask for is unnecessary.

你所要求的是不必要的。

com.sun.management.jmxremote.local.only=true(which by the way is already the default) means it will only acceptconnections from localhost. It doesn't mean it will only bind to the loopback interface as you assume. Not accepting connections from something not on the local host is just another way of doing it. From sun.management.jmxremote.LocalRMIServerSocketFactoryyou can see it is being done like this:

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;
        }
    }
}

Why it was done like this rather than binding to loopback, I don't know. But I believe it is just as secure. (or maybe not?)

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

But if you really want to, then since Java 8u102 and Java 7u131 system property com.sun.management.jmxremote.hostbinds the underlying RMI registry to the selected network interface. The value can be any string which is accepted by InetAddress.getByName(String).

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

Example:

例子:

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

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

see: JDK-6425769for more information.

有关更多信息,请参阅:JDK-6425769

Links: Java 8u102 Release Notes

链接:Java 8u102 发行说明

What the docs doesn't mention anywhere is that even when setting com.sun.management.jmxremote.hostyou'll still see one JMX port which is bound to all network interfaces. This is because if com.sun.management.jmxremote.local.only=truethen an instance of sun.management.jmxremote.LocalRMIServerSocketFactorywill be started and that one doesn't allow customization, i.e. it doesn't respect com.sun.management.jmxremote.hostproperty. If that is a bug, an oversight in the JDK-6425769implementation or intentional, I do not know.

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