Ограничение JMX локальным хостом - PullRequest
5 голосов
/ 07 декабря 2008

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

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

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

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

Ответы [ 4 ]

3 голосов
/ 31 декабря 2009

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

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

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

Éamonn McManus, JMX Spec Lead

2 голосов
/ 19 марта 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, и эта часть, кажется, работает.

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

1 голос
/ 18 февраля 2009

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

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

В обоих случаях открывается дополнительный случайный порт, доступ к которому можно получить удаленно.

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

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

1 голос
/ 07 декабря 2008

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

http://mx4j.sourceforge.net/

...