Как использовать JRMP (RMI) как с шифрованием (ssl), так и с xinetd?

Итак, я использую собственный сервер приложений на основе Java (потому что Glassfish и др. Не для приложений, не основанных на веб-технологиях), и, конечно же, шифрование абсолютно необходимо. Итак, я написал базовое решение для ssl, используя стандарт SslRMIClientSocketFactory, а также SSLRMIServerSocketFactory, Все идет нормально. У меня есть некоторые другие проблемы, такие как разрешение, но не обязательное использование клиентских сертификатов (как, например, когда вы входите в систему через ssh), но я готов рассмотреть это упражнение на следующий день.

Тем не менее, по дороге я заметил, что с 2005 года или около того с появлением "Java 5.0", у нас, очевидно, есть некоторая помощь в использовании xinetd на основе решений 'nix. Мне кажется, что "новая" помощь в этом заключается в возможности получить информацию о сокете, "унаследованную" от более низкого уровня, например xinetd, через System.inheritedChannel,

Я подумал, что мне нужен пример совместного использования шифрования и xinetd в решении RMI, и нашел здесь отличную рецензию . Новый RMI - или, по крайней мере, было бы здорово, если бы не тот пример кода, который должен сопровождать это. статья пропала. Немного гнили, наверное. (У кого-нибудь есть копия?!) Пример, видимый в статье, слишком неполный, и текст опирается на тот факт, что у вас есть пример кода. Ну что ж. Просто я не совсем понимаю - используя System.inheritedChannel очевидно, не так просто, как просто подключить его к существующему коду реестра RMI - вам, очевидно, нужно создать фабрику сокетов, или, может быть, я просто не понимаю - следовательно, ищу пример.

Итак, я пошел на охоту. Я обнаружил, что люди Apache сделали нечто подобное, и это описано здесь, RMI Service Exporter, однако, он использует технологию, которой я бы предпочел избегать - SpringBeans, если хотите. И, как это нетривиальный пример, честно говоря, я немного растерялся, как бы я использовал этот тип решения в моей работе.

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

Создает и экспортирует реестр (используя унаследованный канал, если таковой имеется, как указано ниже) и привязывает указанное имя к указанному прокси в этом реестре.

Мои проблемы здесь - язык. В частности, я не использую прокси, и даже если бы я был, я не знаю, почему это было бы важно. И я думал, что я привязываю объекты к Реестру RMI, а не только имена. Возможно, если кто-то может просто выяснить, что они делают, это прекрасный пример...

Наконец, я наткнулся на ОТЛИЧНЫЙ ответ - один из самых потрясающих за всю историю - прямо здесь, на Stackru, рассказывая о Java RMI, SSL и сжатии. Сжатие не играет на моих потребностях, но это интересная дискуссия. Тем не менее, я не понимаю, как это помогает мне понять, как использовать RMI с SSL и xinetd одновременно...

Спасибо.

ОБНОВИТЬ:

В ответ на предложенный ответ EJP (за что я благодарен) я начал с InitializeRegistry.java пример, приведенный выше. Я обновил метод accept() следующим образом:

      .
      .
      .
      /* Here we wrapper our socket with SSLSocketFactory.createSocket()

         Some open questions I have are whether the arguments to createSocket()
         are all _inbound_ in nature. Here's the basic call:

            SSLSocketFactory.createSocket(socket, host, port, auto-close);

         I PRESUME args are for the REMOTE host, not "us?"

            REMOTE: serverSocket.getInetAddress()
            LOCAL:  serverSocket.getLocalAddress()

            REMOTE: serverSocket.getPort()
            LOCAL:  serverSocket.getLocalPort()

         Who Knows about auto-close?! I'll try it and see if it works OK.
      */

      boolean autoClose = true;

      return (Socket)SSLSocketFactory.createSocket(serverSocket.accept(),
       serverSocket.getInetAddress().getHostAddress(),
       serverSocket.getLocalPort(),
       autoClose).accept();

      //return serverSocket.accept();
   }

Однако этот код не компилируется, жалуясь, что:

  • createSocket() не может быть вызван из статического контекста - и я не мог найти никакого решения для этого
  • он не мог найти "символ" " .accept() "- второе из двух.

Удаление финала .accept() сводит счетчик ошибок к невозможности использовать "нестатический метод" createSocket() "Из статического контекста этого кода. Но когда я пытаюсь удалить" статический "из класса, он падает повсюду, не в состоянии использовать вездесущий" this Ссылка. ОТО, я не уверен, как сделать SSLSocketFactory.createSocket() Статическая!

... Можно ли предположить, что один accept() используется для получения доступа к переданному сокету (!!) достаточно, и что следующий, который я пытался включить, не нужен? Хммм...

Я был бы счастлив попробовать это и посмотреть, смогу ли я сделать это так.

Кстати, я бы предположил, что я должен использовать setUseClientMode(false) на более позднем этапе... Да?

ДУМАЮ ДАЛЬШЕ....

Я понял что возможно InitializeRegistry.java был плохой отправной точкой, и вернулся к "первым принципам", обнаружил, что, возможно, он сбился с пути, когда он впервые принимает channel это было дано через System.inheritedChannel и превращает его в ServerSocket так что идея переопределения ServerSocketFactory это, ну, "много работы". И тут меня осенило:

Весь смысл в том, чтобы попытаться обеспечить, чтобы незапрошенный запрос на подключение достиг цели, которая прослушивает. Но более того, в реестре должен быть объект, чтобы он был полезен, и для этого нужно все, что создает, тоже. Следовательно, было бы так же легко и просто обеспечить, чтобы код, создающий объект, выполнялся как СЕРВИСНАЯ СЛУЖБА, а не беспокоился о решении этой проблемы как СЕТЕВАЯ СЛУЖБА.

Итак, я разбираюсь.... Кажется, стыдно удалять вопрос, поскольку это может служить руководством для кого-то другого - это ЕДИНСТВЕННЫЙ запрос во всем Stackru, который затрагивает эту тему.

Еще раз спасибо.

1 ответ

Я не вижу смысла DelayedAcceptServerSocketFactoryЭто немного излишне, но основная техника заключается в следующем:

  1. Написать RMIServerSocketFactory который возвращает переопределение ServerSocket чья accept() метод переопределяется для делегирования ServerSocket который пришел из унаследованного канала.

  2. До этого accept() метод возвращает, обернуть принятый Socket в SSLSocket, с помощью SSLSocketFactory.createSocket(Socket, ...)и позвоните setUseClientMode(false) на этой розетке.

Вуаля! Ваш Реестр RMI теперь запускается xinetd и передает SSL вашим клиентам Реестра. Предполагая, что это то, что вы хотели, ваши клиенты теперь могут искать этот реестр, если они обращаются к нему через LocateRegistry.getRegistry(host, port, csf),

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

Теперь создайте свои удаленные объекты, используя фабрики сокетов SslRMI*, и привяжите их к реестру, как обычно.

Готово.

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