Ограничение JMX до localhost

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

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

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

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

SQL Injection: Атаки в реальной жизни и как это вредит бизнесу
SQL Injection: Атаки в реальной жизни и как это вредит бизнесу
Один-единственный вредоносный запрос может нанести ущерб вашему бизнесу. Уязвимости вашего кода могут привести к:
5
0
8 665
4

Ответы 4

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

http://mx4j.sourceforge.net/

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

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

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

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

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

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

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

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

Если вы осуществляете доступ с локального хоста, то в этом случае можно делать то, что делают JConsole и JVisualVM, а именно использовать Attach API для поиска локального адреса сервера (что вы получите, если запустите с - 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

Другие вопросы по теме