LINUX.ORG.RU

(с++)ищется лучший способ обнаружить, что ssl соединение разорвано.

 


0

2

задача. две аппы общаются между собой по ssl соединению через tcp(OpenSSL). Общение идет по неблокирующему сокету, с таймаутами. одна аппа отваливается(неважно как, даже отрывом кабеля), другая должна красиво это понять. кондовый способ - при чтении из такого оборванного соединения, SSL_read функция возвратит соотв. ошибку и тут ее можно обработать.

но это пока не наш путь, в силу архитектуры аппы.

вопрос. можно ли не читая впрямую, понять из обьекта SSL(это дескриптор SSL соединения в OpenSSL), что низлежащий сокет находится в невалидном состоянии, не копаясь в самом сокете.

короче надо функцию bool ssl_connected(..).

ps. также есть понимание, что SSL_peak и анализ ошибки даст понимание о разорванности соединения. вопрос…кроме этого, можно чем нибудь еще воспользоваться?

★★

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

Это не «отваливается»: если приложения очень редко обмениваются сообщениями, можно отсоединить кабель, спустя несколько дней его подсоединить, и, вуаля, TCP-соединение всё ещё установлено и правильно работает.

Так что нужно проверять не столько соединение, сколько, отвечают ли на том конце с желаемой периодичностью. Т.е. keep-alive на уровне приложения. Не отвечают - исходить из того, что «соединение», скорее всего, оборвалось, и закрывать его.

gag ★★★★★ ()
Ответ на: комментарий от gag

keep-alive на уровне приложения

+1

можно отсоединить кабель, спустя несколько дней его подсоединить, и, вуаля, TCP-соединение всё ещё установлено и правильно работает

может все-таки минут?

t184256 ★★★★★ ()

Наверно надо включить so_keepalive на tcp сокете. Когда механизм поймёт, что соединение разорвалось, неблокирующийся сокет получит poll ивенты. Какие точно не знаю, наверное pollin pollout pollhup.

iliyap ★★★★★ ()
Последнее исправление: iliyap (всего исправлений: 1 )
Ответ на: комментарий от t184256

может все-таки минут?

С параметрами по-умолчанию пока ай-пишник не поменяется. Для динамических больше 24 часов не выйдет (за редкими исключениями, когда получаешь снова тот же адрес).

gag ★★★★★ ()
Ответ на: комментарий от gag

Так что нужно проверять не столько соединение, сколько, отвечают ли на том конце с желаемой периодичностью. Т.е. keep-alive на уровне приложения. Не отвечают - исходить из того, что «соединение», скорее всего, оборвалось, и закрывать его.

а где сказано что приложения «редко обмениваются»? задача не допустить чтения из ssl соединения, если оно физически разорвано, например за 1 миллисекунду до запроса на чтение.

ps. как я уже сказал - прочитать и в лоб проверить ошибку - это итак понятно. вопрос - как без чтения это сделать. это не вопрос по tcp, это вопрос по ssl.

alysnix ★★ ()
Последнее исправление: alysnix (всего исправлений: 1 )

Как уже заметили выше, нужно использовать keep-alive. Эта штука еще известна под другими названиями heartbeats и enquire-link. Все об одном и том же - как обнаружить обрыв соединения. Или этим сетевой стек TCP/IP, или собственно приложение будет заниматься - уже не так важно.

anonymous ()
Ответ на: комментарий от anonymous

Как уже заметили выше, нужно использовать keep-alive. Эта штука еще известна под другими названиями heartbeats и enquire-link. Все об одном и том же - как обнаружить обрыв соединения. Или этим сетевой стек TCP/IP, или собственно приложение будет заниматься - уже не так важно.

это тут вообще не причем. вопрос как через ssl абстракции обнаружить что соединение по сокету в данный момент разорвано. В ДАННЫЙ МОМЕНТ. потому что нужно по нему нечто прочитать. и это можно было бы прочитать, если б кабель не оборвали. как я уже сказал - это можно обнаружить по результату SSL_read. просто не хочется прокидывать этот низкоуровневый результат на функции выше.

но скорее всего придется.

добавление… дело в том что ssl соединение уже поняло, что по сокету чтение не проходит, из за предыдущих операций. вот вопрос в том, можно ли это понимание достать из него.

alysnix ★★ ()
Последнее исправление: alysnix (всего исправлений: 1 )
Ответ на: комментарий от alysnix

Если ты хотел прочитать в буфер N байт, а прочитал меньше или ноль, значит разрыв на той стороне. Ну или оно ошибку вернёт — отрицательное значение, для каждого из которых есть дефайлы/енумы кода возврата.

deep-purple ★★★★★ ()
Ответ на: комментарий от alysnix

задача не допустить чтения из ssl соединения, если оно физически разорвано

Т.к. TCP-соединения (и, соответственно, те, что поверх их) не физические, а логические, то нет возможности мгновенно узнать, разорваны они (случайно) или нет. Не говоря уже о том

например за 1 миллисекунду до запроса на чтение.

чтобы узнать это акаузально: т.е. заранее.

gag ★★★★★ ()
Ответ на: комментарий от alysnix

это можно обнаружить по результату SSL_read. просто не хочется прокидывать этот низкоуровневый результат на функции выше.

На том низком уровне можно завести переменную bool is_ssl_connected, которая будет обновляться при необходимости после каждого вызова SSL_read. К этой переменной можно обеспечить высокоуровневый доступ с помощью упомянутой вами функции ssl_connected().

gag ★★★★★ ()
Ответ на: комментарий от deep-purple

Если ты хотел прочитать в буфер N байт, а прочитал меньше или ноль, значит разрыв на той стороне. Ну или оно ошибку вернёт — отрицательное значение, для каждого из которых есть дефайлы/енумы кода возврата.

это итак понятно. это случай если использовать SSL_read.

alysnix ★★ ()
Ответ на: комментарий от alysnix

И в чем проблема проверить по факту получилось прочитать или нет? Ну, более высокоуровнево, интерпретируй это как успех или не успех записи в буфер.

deep-purple ★★★★★ ()
Последнее исправление: deep-purple (всего исправлений: 1 )

SSL_read функция возвратит соотв. ошибку и тут ее можно обработать.

Это единственно правильный путь, а архитектура у тебя кривая. Можно ещё сокет в select()/poll() или аналогичное передавать и по результатам определять разрыв. В структуру SSL лазить не нужно, ибо она может меняться между релизами OpenSSL и не является публичным API

Harald ★★★★★ ()
Ответ на: комментарий от gag

На том низком уровне можно завести переменную bool is_ssl_connected, которая будет обновляться при необходимости после каждого вызова SSL_read. К этой переменной можно обеспечить высокоуровневый доступ с помощью упомянутой вами функции ssl_connected().

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

alysnix ★★ ()
Ответ на: комментарий от Harald

Это единственно правильный путь, а архитектура у тебя кривая.

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

о чем я и думал.

alysnix ★★ ()
Последнее исправление: alysnix (всего исправлений: 1 )
Ответ на: комментарий от alysnix

а если соединение восстановилось, понять это уже нельзя(без чтения).

Т.к. соединение не физическое, то (при сомнениях) проверить, есть оно или нет, можно только через передачу сообщения и проверку, ответят ли.

gag ★★★★★ ()
Ответ на: комментарий от t184256

Если ip не менялся и сбрасывающих пакетов не было то дней. На предыдущем провайдере со статикой я поднимал однажды ssh через месяц бездействия и он был жив

mittorn ★★★★★ ()
Ответ на: комментарий от t184256

Ну там один нюанс был - клиент был этот месяц в спящем режиме. Но факт что подключение сохранилось и сервер его не дропнул.
сейчас той клиентской системы уже нет, но собрана она была до 2015 года. Может быть тогда дефолты другие были или даже я что-то менял сам в конфигах
P.S вероятно, TCPKeepAlive на сервере был отключен или не реализован вообще

mittorn ★★★★★ ()
Последнее исправление: mittorn (всего исправлений: 1 )
Ответ на: комментарий от alysnix

Единственный способ точно проверить keep-alive на уровне приложения. На TCP уровне у тебя может быть half closed соединение, на SSL может быть недостаточно вычитанных байт из сети для расшифровки сообщения. Чтобы учесть все состояния придется создать сложную стейт машину.

xpahos ★★★★★ ()

очевидно проблема архитектуры

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

anonymous ()
Ответ на: комментарий от xpahos

Единственный способ точно проверить keep-alive на уровне приложения.

Кстати, а есть стандартная библиотека для такого? Чтобы на сервере можно было сказать типa keepalive_accept(), а на клиенте keepalive_connect, а пакеты оно само бы в фоновом режиме кидало?

monk ★★★★★ ()
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.