Как позже изменить соединение socat tcp4 на соединение SSL (с использованием протокола XMPP)

Я рассматриваю создание очень простого прокси-сервера XMPP. Протокол XMPP начинается с простого текста, а затем преобразует сокет в SSL, если он поддерживается, и продолжает работу.

Вот пример сеанса XMPP, я сократил его до основных частей: Проверка функций:

(11:49:48) jabber: Sending (chris@localhost): <?xml version='1.0' ?>
(11:49:48) jabber: Sending (chris@localhost): <stream:stream to='localhost' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0'>
(11:49:48) jabber: Recv (358): <?xml version='1.0'?><stream:stream xmlns:stream='http://etherx.jabber.org/streams' version='1.0' from='localhost' id='5dea6b36-2da5-485a-8bed-16884e56d6f3' xml:lang='en' xmlns='jabber:client'><stream:features><starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'><required/></starttls><register xmlns='http://jabber.org/features/iq-register'/></stream:features>

Указание серверу начать общение в SSL и обменяться ключами:

(11:49:48) jabber: Sending (chris@localhost): <starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>
(11:49:48) jabber: Recv (50): <proceed xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>
(11:49:48) nss: SSL version 3.3 using 256-bit AES with 256-bit SHA256 MAC
Server Auth: 2048-bit RSA, Key Exchange: 2048-bit RSA, Compression: NULL
Cipher Suite Name: TLS_RSA_WITH_AES_256_CBC_SHA256
(11:49:48) certificate: Successfully verified certificate for localhost

Теперь мы находимся в сеансе SSL:

(11:49:48) jabber: Sending (ssl) (chris@localhost): <stream:stream to='localhost' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0'>
(11:49:48) jabber: Recv (ssl)(447): <?xml version='1.0'?><stream:stream xmlns:stream='http://etherx.jabber.org/streams' version='1.0' from='localhost' id='74a00818-e037-4405-ada1-02bb3dbfe023' xml:lang='en' xmlns='jabber:client'>

Когда я пытаюсь создать «сервер» socat SSL и подключиться к нему с помощью Pidgin, я получаю неизвестный протокол:

$ socat openssl-listen:5222,reuseaddr,cert=$HOME/server.pem,cafile=$HOME/client.crt,fork -
2016/01/13 14:00:59 socat[28586] E SSL_accept(): error:140760FC:SSL routines:SSL23_GET_CLIENT_HELLO:unknown protocol

Я попробовал то же самое с «сервером» socat без SSL, и он работал до тех пор, пока не потребовалось перейти на SSL (я добавил «Клиент:» и «Сервер:» в этот вывод для удобства чтения. Все «Сервер: " строки были вставлены мной в терминал):

$ socat tcp4-listen:5222,reuseaddr,fork -
Client: <?xml version='1.0' ?><stream:stream to='localhost' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0'>
Server: <?xml version='1.0'?><stream:stream xmlns:stream='http://etherx.jabber.org/streams' version='1.0' from='localhost' id='5dea6b36-2da5-485a-8bed-16884e56d6f3' xml:lang='en' xmlns='jabber:client'><stream:features><starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'><required/></starttls><register xmlns='http://jabber.org/features/iq-register'/></stream:features>
Client: <starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>
Server: <proceed xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>
Client: tp�C?�f�Q��|_pV��j���=�^(�32g98kf�/<5=

В последней строке клиент теперь пытается поговорить с нами в SSL, поэтому мне нужен способ сказать socat переключиться на SSL в этот момент. Очевидно, что Socat ничего не знает о протоколе XMPP, поэтому он не знает, когда переключиться. Можно ли сказать socat, чтобы он динамически переключался, или мне следует искать другие способы сделать это?

Изменить: я провел дополнительное исследование.
Многие протоколы, например HTTPS, используют «всегда зашифрованные» соединения.
XMPP использует starttls, что в основном означает незашифрованное соединение, пока клиент и сервер не согласятся на обновление. подключение к зашифрованному.

Редактировать: я только что посмотрел на openssl, и у него есть -starttls для s_client, но не для s_server, что указывает мне на то, что это проблема архитектуры, сложно узнать или сказать, когда и как обновить соединение до зашифрованного.

Итак, я думаю, мой реальный вопрос заключается в том, может ли socat обрабатывать протоколы, которые используют starttls с некоторым ручным вмешательством или без него, чтобы сказать ему, когда переключаться? Я не думаю, что openssl может. Есть ли какой-то другой инструмент, который может это сделать, или я должен, конечно, просто написать свой собственный, используя библиотеку SSL?


person pilkch    schedule 13.01.2016    source источник
comment
Вас все еще интересует решение с использованием socat? Должна быть возможность добиться этого с помощью вспомогательного сценария оболочки, который порождает дочерний ssl socat...   -  person vlp    schedule 21.01.2016
comment
@vlp Я использую XMPP и обнаружил, что у него есть устаревший режим SSL, который является обычным SSL, поэтому я только что включил его, и мне не нужно беспокоиться о более сложном поведении STARTTLS. Так что мне это больше не нужно. Но не стесняйтесь попробовать, если хотите. Я попробую любые решения.   -  person pilkch    schedule 28.01.2016


Ответы (1)


Существует два способа использования SSL/TLS:
XMPP использует STARTTLS, когда клиент и сервер обсуждают свои функции безопасности, а затем клиент запрашивает преобразование сокета в TLS в произвольной точке связи.
HTTPS и другие используют два сокета, один для обсуждения функций безопасности, а затем связь переключается на настройку второго сокета исключительно для зашифрованной связи.

socat:
Не поддерживает STARTTLS.

openssl:
Поддерживает STARTTLS на стороне клиента:

openssl s_client -starttls ...

На стороне сервера, насколько я могу судить, для каждой ситуации требуется собственный код. Я нашел этот полезный скрипт Python.

person pilkch    schedule 18.01.2016