2008-12-07 11 views
5

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

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

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

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

ответ

1

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

http://mx4j.sourceforge.net/

1

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

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

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

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

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

2

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

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

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

3

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

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

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

Éamonn McManus, JMX Spec Lead