Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to configure JMX to bind to localhost only?

Tags:

java

jmx

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

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:

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=true all ports should be bind to localhost only (::ffff:127.0.0.1 will appear before all ports).

How to configure JMX to bind to localhost only?

Added

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

like image 316
Michael Avatar asked Feb 12 '16 16:02

Michael


People also ask

How do I enable authentication on JMX?

To enable remote JMX connections, change the LOCAL_JMX setting in cassandra-env.sh. The default settings for Cassandra make JMX accessible only from localhost. If you want to enable remote JMX connections, change the LOCAL_JMX setting in cassandra-env.sh and enable authentication and/or ssl.

What is JMX remote port?

Using the Java Management Extensions (JMX) technology, the Java Virtual Machine (JVM) has built-in instrumentation that lets you set the port for the JMX RMI. These built-in management utilities are often referred to as out-of-the-box management tools for the JVM.


2 Answers

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 accept connections 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.LocalRMIServerSocketFactory you can see it is being done like this:

// 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.host binds the underlying RMI registry to the selected network interface. The value can be any string which is accepted by InetAddress.getByName(String).

Example:

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

see: JDK-6425769 for more information.

Links: Java 8u102 Release Notes

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

like image 173
peterh Avatar answered Sep 16 '22 14:09

peterh


As far as I understand this answer and read Oracle's docs about it, there seems to be no way to configure it without coding. This says in the chapter "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.

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

Correct me if I am wrong.

like image 31
Michael-O Avatar answered Sep 16 '22 14:09

Michael-O