Как использовать 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
Это немного излишне, но основная техника заключается в следующем:
Написать
RMIServerSocketFactory
который возвращает переопределениеServerSocket
чьяaccept()
метод переопределяется для делегированияServerSocket
который пришел из унаследованного канала.До этого
accept()
метод возвращает, обернуть принятыйSocket
вSSLSocket
, с помощьюSSLSocketFactory.createSocket(Socket, ...)
и позвонитеsetUseClientMode(false)
на этой розетке.
Вуаля! Ваш Реестр RMI теперь запускается xinetd и передает SSL вашим клиентам Реестра. Предполагая, что это то, что вы хотели, ваши клиенты теперь могут искать этот реестр, если они обращаются к нему через LocateRegistry.getRegistry(host, port, csf)
,
Точно так же ваши серверы могут связываться с ним, если они получают к нему одинаковый доступ.
Теперь создайте свои удаленные объекты, используя фабрики сокетов SslRMI*, и привяжите их к реестру, как обычно.
Готово.