2010-12-06 2 views
5

Как я могу изящно завершить сеанс Java SSL без закрытия базового сокета?Выключение SSL без закрытия основного сокета?

Сценарий заключается в том, что клиент Java подключается к (не-java) серверу, настраивает SSL и безопасно отправляет на сервер учетные данные (имя пользователя &). Сервер настраивает среду, запущенную под этими учетными данными, порождает новый процесс в этой среде и передает ему дескриптор сокета, но уловка в том, что этот новый процесс не может повторно использовать существующее SSL-соединение (и не может использовать сеанс SSL возобновление) ... поэтому идея состоит в том, чтобы выключить SSL до того, как этот новый процесс будет создан, а затем повторно согласовать сеанс SSL с нуля с новым процессом.

Проблема заключается в том, что метод Java SSLSocket's1010 закрывает сокет в дополнение к завершению сеанса SSL (по sending the close_notify alert). Кажется, что не существует эквивалента функции OpenSSL SSL_shutdown(), которая позволяет оставить открытое гнездо открытым.

Я попробовал несколько вещей, чтобы обойти это:

  1. Использование SSLSocket.startHandshake() во второй раз, но автоматически пытается возобновить существующий кэшированные SSL сеанс (который терпит неудачу, так как этот процесс породил сервер не знать этот сеанс), и, хотя существует метод force resuming SSL sessions or die trying, нет способа аннулировать все кэшированные сеансы или отключить использование кэшированных сеансов.

  2. Создание SSLSocket поверх моей существующей розетки с использованием SSLSocketFactory.createSocket(), с autoClose установлено значение false. Это не останавливает метод close() от закрытия базового сокета, и я подозреваю, что параметр autoClose предотвращает закрытие сокета при первоначальном сбое связи.

  3. Создание SSLSocket поверх существующего сокета (как указано выше), а затем создать вторую SSLSocket использовать для SSL рукопожатия с порожденного процесса (от нового SSLContext). Это терпит неудачу, потому что когда сервер отправляет предупреждение close_notify (до появления подпроцесса), Java закрывает сокет.

Я слышал SSLEngine, но я также прочитал (хотя в настоящее время источник ускользает от меня), что много болезненных усилий, чтобы написать правильную реализацию SSL по TCP/IP, используя его, и похоже, слишком много, если мне нужно только иметь версию SSLSocket, чья close() не звонит super.Close().

Однако SSLSocket не появляется даже переопределить close() (в соответствии с Javadoc), так что я не уверен в том, как она перехватывает close() метод, когда не появляется, чтобы быть какой-либо поддержки для регистрации близких слушателей на Socket.

Политика компании определяет, что никакие сторонние библиотеки шифрования не могут использоваться, поэтому я не могу обратиться к альтернативной реализации SSL, например, к Bouncy Castle, чтобы решить эту проблему.

Если мы не сможем использовать текущую конструкцию с 1 гнездом, альтернативой является перезапись сервера клиента & для использования двух отдельных сокетов (что становится довольно беспорядочным с точки зрения необходимости противодействия отказу в обслуживании и man- в-середине атаки, и разве это не то, для чего должен использоваться SSL?).

Любой вход или мысли о путях решения этой проблемы были бы наиболее желанными.

+0

Вы пытались использовать обычную Socket в фоновом режиме? Что-то вроде: `Socket s = новый Socket (HOST, PORT); SSLSocket ssl = ...; ssl.connect (s.getRemoteSocketAddress()); ... `? (для меня, по крайней мере, он не закрывает «базовый» сокет. * Возможно, я делаю что-то неправильно * :)) – dacwe 2010-12-06 08:23:07

+0

dacwe, как можно ближе (игнорируя ... часть вашего фрагмента), делая ssl.connect() создаст второе соединение с хостом, и сокет `s` вообще не будет использоваться для связи SSL. – Caspar 2010-12-07 00:58:13

ответ

2

Это не останавливает метод близко() от закрытия Базового сокету

Да, это делает. Согласно документации.

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

Нет. Это предотвращает закрытие базовой розетки. Согласно документации.

Показать код.

+0

Моя ошибка, вы правы. `SSLSocket.close()` javadoc не может сказать ничего об отключении SSL-коммуникаций, а в представлении Outline Eclipse `SSLSocket` не отображается метод` close` (возможно, он не отображает переопределенные методы для скомпилированных классов без исходных вложений), но каким-то образом SSLSocket.close() `переопределяет функциональность` Socket.close() `. – Caspar 2010-12-07 01:07:09

2

Вы должны иметь возможность использовать простой базовый сокет (ваш # 3), поскольку это то, что делают реализации FTP с Clear Control Channel.

Имейте в виду, что то, что вы пытаетесь сделать, оставляет вас открытой для атаки «человек в середине» между двумя сеансами SSL, если вы не несете какой-либо секрет между ними, чтобы сигнализировать о том, что аутентификация по-прежнему действительна.

  1. Использовать сетевое naughtiness (отравление ARP?), Чтобы стать прокси-сервером между клиентом и сервером.
  2. Пересылка пакетов в обе стороны до завершения аутентификации и завершения сеанса SSL. (Любой SSL ALERT будет сигнализировать о завершении, нам не нужно расшифровывать содержимое).
  3. Закройте сокет клиенту, чтобы он выходил из строя.
  4. Выполняйте мои собственные SSL-переговоры с сервером.
  5. Приступить к работе с учетными данными клиента.
Смежные вопросы