Как использовать JRMP (RMI) как с шифрованием (ssl), так и с xinetd? - PullRequest
1 голос
/ 28 февраля 2012

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

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

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

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

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

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

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

Наконец, я наткнулся на БОЛЬШОЙ ответ - один из самых потрясающих за всю историю - прямо здесь, на StackOverflow, говоря о 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()" - второй из двух.

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

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

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

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

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

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

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

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

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

1 Ответ

2 голосов
/ 28 февраля 2012

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

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

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

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

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

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

Готово.

...