Можно ли изменить простой сокет на SSLSocket? - PullRequest
10 голосов
/ 03 июля 2011

Существует простой сервер сокетов, прослушивающий порт 12345;

ServerSocket s = new ServerSocket(12345);

Что я хочу знать, так это то, что:

  1. Если клиент отправляет запрос http, сервер обрабатывает запрос напрямую,
  2. Если клиент отправит запрос https, сервер изменит клиентский сокет на SSLSocket?

Спасибо

Ответы [ 4 ]

20 голосов
/ 03 июля 2011

Можно ли заменить обычную розетку в SSLSocket?

Да, это так. На стороне сервера работает следующее:

ServerSocketFactory ssf = ServerSocketFactory.getDefault();
ServerSocket serverSocket = ssf.createServerSocket(12345);

// I've initialised an sslContext with a keystore, as you normally would.
Socket socket = serverSocket.accept();
SSLSocketFactory sslSf = sslContext.getSocketFactory();
// The host name doesn't really matter, since we're turning it into a server socket
// (No need to match the host name to the certificate on this side).
SSLSocket sslSocket = (SSLSocket) sslSf.createSocket(socket, null,
    socket.getPort(), false);
sslSocket.setUseClientMode(false);

// Use the sslSocket InputStream/OutputStream as usual.

SSLSocketFactory.createSocket(Socket, ...) по умолчанию преобразует существующий Socket в клиентский режим SSLSocket. Так как рукопожатие начинается только тогда, когда вы начинаете чтение / запись с потоками ввода / вывода, еще есть время изменить режим с помощью setUseClientMode(false).

По остальной части вопроса:

Я хочу знать, что это возможно, что:

  • Если клиент отправляет запрос http, сервер обрабатывает запрос непосредственно,
  • Если клиент отправляет запрос https, клиент смены сервера сокет к SSLSocket?

Опять да, это возможно. Иногда его называют « объединение портов », и он реализован в Grizzly и, таким образом, Glassfish .

Это работает, потому что и HTTP, и TLS (по которым работает HTTPS) являются протоколами, по которым клиент должен говорить первым. Следовательно, сервер может определить, является ли то, что клиент первоначально отправляет, сообщением TLS ClientHello (в этом случае он должен попытаться продолжить квитирование TLS) или простым HTTP-запросом (например, GET / HTTP/1.1 ...).

Я подозреваю, что объединение портов "проще" сделать с помощью SSLEngine, в противном случае может быть сложно реализовать упреждающее чтение на обычном сокете, которое вы все равно сможете преобразовать с помощью SSLSocketFactory.createSocket(Socket, ...).

Обратите внимание, что это все же довольно необычно.

3 голосов
/ 03 июля 2011

Невозможно обслуживать http и https на одном и том же порту. Однако теоретически должно быть возможно обновить существующее http-соединение для использования TLS, если его поддерживают и клиент, и сервер, см. RFC 2817 . Класс SSLSocketFactory имеет функцию createSocket (), которую можно использовать для обновления существующего сокета до SSL / TLS.

Отказ от ответственности: я не пытался сделать это, и реализация RFC 2817, скорее всего, нетривиальна.

Редактировать: Очевидно, я был неправ, как Бруно написал, что можно обслуживать http и https на одном и том же порту, используя технологию, называемую объединением портов, которая использует первые несколько байтов, полученных для обнаружения протокола. пример этого включен в инфраструктуру Netty (JBoss).

1 голос
/ 03 июля 2011

Интерфейс Socket / SSLSocket не позволяет здесь удобно распознавать контент - когда вы начинаете читать из сокета и видите, что это всего лишь мусор (не простой HTTP), вы не можете передать эти данные в новый SSLSocket, обернутый вокругобычный.

Вы можете использовать Socket (или SocketChannel) и посмотреть на данные, а затем (если это не начало простого HTTP-запроса) передать те же данные объекту SSLEngine для расшифровки/ шифрования.Это означает, что вы должны обрабатывать все вызовы шифрования / дешифрования самостоятельно, что не совсем тривиально (по крайней мере, это намного сложнее, чем просто использовать SSLSocket с двумя потоками - я сделал это один раз).

Конечно, если вы сделаете это, вам, вероятно, лучше реализовать интерфейс RFC 2817, вместо того, чтобы пытаться автоматически анализировать содержимое.

0 голосов
/ 03 июля 2011

Я думаю, что это не по обоим пунктам, в зависимости от того, что вы опубликовали.

  1. Если слушатель на ServerSocket не интерпретирует запрос как HTTP, то нет волшебства, которое сделает это так.
  2. Если слушатель на ServerSocket не расшифровывает зашифрованный запрос, то нет волшебства, которое сделает это так.

Вы написали код, который слушает на ServerSocket? Если да, вы можете ответить на свой вопрос, посмотрев код.

Кто-то еще написал код, который слушает на ServerSocket? Если да, вам придется спросить их. Вам дали какую-либо информацию об ожидаемом протоколе?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...