Ограничение JMX для локального хоста

Несмотря на то, что есть некоторая документация о том, как выставить JMX через различные схемы брандмауэра и туннелирования, я как бы хочу противоположного. Я хочу убедиться, что JMX доступен только для локальной машины. К сожалению, похоже, что параметры управления «из коробки» не позволяют ограничить порты локальным интерфейсом, а netstat показывает, что они прослушиваются на любом/всех интерфейсах.

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

Должен признаться, я сбит с толку уровнями косвенности в JMX, реестром RMI, соединителями, адаптерами и т. д.

Я хотел бы просто включить его, а затем туннелировать через SSH, а не выставлять его миру, а затем выполнять трудоемкое и лишнее управление пользователями и настройку безопасности. Было бы неплохо иметь возможность использовать встроенный реестр RMI и не запускать внешний.


person Community    schedule 07.12.2008    source источник


Ответы (4)


Если вы обращаетесь с локального хоста, то можно сделать то, что в этом случае делают JConsole и JVisualVM, а именно использовать API-интерфейс Attach для поиска только локального адреса сервера (что вы получите, если запустите - Dcom.sun.management.jmxremote, но не -Dcom.sun.management.jmxremote.port=N) и подключитесь к нему. В другом ответе Трайд говорит, что даже в этом случае открывается удаленно доступный порт, что было верно в более ранних версиях, но не было так уже пару лет.

Решение Фредрика работает, но излишне. Вам нужно только определить RMIServerSocketFactory, а не RMISocketFactory (который определяет и клиент, и сервер). Это устраняет необходимость специальной настройки клиента. Код на http://vafer.org/blog/20061010091658 мне кажется правильным.

Управление «из коробки», созданное с помощью свойств командной строки, таких как -Dcom.sun.management.jmxremote, может дать вам только то, что вам нужно, прежде чем вам нужно будет начать программирование с самим JMX API. Как правило, мы не хотели, чтобы стандартное управление превратилось в полноценный параллельный API, поэтому существуют проблемы, подобные этой, которые находятся вне его досягаемости. Мы объясняем, как перейти от одного к другому здесь.

Эймонн Макманус, руководитель спецификации JMX

person Eamonn McManus    schedule 31.12.2009

Немного запоздалый ответ, но если это все еще проблема для вас (или кого-то еще), я думаю, что это поможет:

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, и эта часть, кажется, работает.

Не стесняйтесь комментировать, если есть вещи, которые можно было бы улучшить, или это просто глупо.

person Fredrik    schedule 18.03.2009

Не могу помочь с солнечным способом сделать это. Даже после того, как адаптеры jmx начали поставляться с jdk (я думаю, 6?), я продолжал использовать mx4j для настройки адаптера с наименьшими усилиями. Запустить http-адаптер mx4j на 127.0.0.1 или только для внутреннего интерфейса несложно. Затем SOP заключался в том, чтобы использовать ssh с переадресацией портов или использовать сценарии с командами wget.

http://mx4j.sourceforge.net/

person navicore    schedule 07.12.2008

К сожалению, в настоящее время нет возможности сделать это.

Согласно документации Sun единственный -Dcom.sun.management.jmxremote должен открывать только локальный порт, а -Dcom.sun.management.jmxremote.port= открывает удаленно доступный порт.

Оба способа открывают дополнительный случайный порт, доступный удаленно.

Я видел -Dcom.sun.management.jmxremote.host=, но это, похоже, не имеет никакого эффекта.

Я пришел к выводу, что это невозможно, и использовал локальный брандмауэр для защиты сервера.

person Community    schedule 18.02.2009