如何配置JMX仅绑定到localhost?

Mic*_*ael 1 java jmx

我在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"
Run Code Online (Sandbox Code Playgroud)

不幸的是,当我检查打开了哪些端口时,我发现这些端口会监听所有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
Run Code Online (Sandbox Code Playgroud)

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

如何配置JMX仅绑定到localhost?

添加

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

pet*_*erh 15

你要求的是不必要的.

com.sun.management.jmxremote.local.only=true (顺便说一下,它已经是默认值)意味着它只接受来自localhost的连接.这并不意味着它只会像您假设的那样绑定到环回接口.不接受来自不在本地主机上的东西的连接只是另一种方式.从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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

例:

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

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

链接:Java 8u102发行说明

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

  • 进行地址检查不一定与绑定到 localhost 一样安全。如果您只绑定到 localhost,那么无论如何,攻击者都无法与您交谈并说服您做一些您不应该做的事情。如果您接受网络连接,攻击者可能能够在远程地址检查发生之前利用某些漏洞。可能还有其他实现细节使其“同样安全”,但原则上,最好绑定到 localhost。 (2认同)
  • 当然,他们可能有充分的理由,比如,很难以"正确"的方式做到这一点,所以他们这样做了.或者他们可能根本没有充分的理由,也许这是多年前人们不认为安全问题时所做的.最重要的是,除非有其他缓解因素,否则它并非"安全".添加绑定到特定接口的功能表明没有,尽管我不知道这一点. (2认同)
  • 即使配置了 `local.only=true`,我也能够成功地从另一台主机创建连接:`tcp6 0 0 192.168.100.20:7091 192.168.100.34:54737 ESTABLISHED` `.20` 正在托管 RMX,` .34` 是我的客户。这不应该是可能的,不是吗? (2认同)
  • 此外,通过设置 `-Dcom.sun.management.jmxremote.host=localhost`,我实际上只看到 127.0.0.1 上有一个正在监听,并且我无法像以前一样连接到我的客户端。`tcp6 0 0 127.0.0.1:7091 :::* LISTEN` 所以看来事情同时发生了变化,我在 UB 16.04 LTS 服务器上使用 `openjdk version "1.8.0_191"`。 (2认同)

Mic*_*l-O 4

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

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

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

如果我错了请纠正我。

  • @Michael:你可能不明白。没有 Tomcat JMX。Tomcat 使用 VM 提供的普通 JMX 实现。没什么特别的。你应该尝试一下。 (3认同)