Медленное рукопожатие DTLS в случае потери пакета - PullRequest
0 голосов
/ 30 марта 2020

Я реализовал DTLS-сервер, используя openssl. (У меня есть сокет udp, и я использую био памяти для связи с openssl.) Однако, если есть потеря пакета, рукопожатие DTLS может занять 1-2 секунды, что много в моем случае.

нормальный поток, когда нет потери пакетов: (несколько миллисекунд)

Client Hello ------------------------->
             <------------------------- Server Hello
Rest of the handshake ---------------->
                      <---------------- Rest of the handshake

Поток, который я испытываю: (несколько секунд)

Client Hello ------------------------->
             <-------(lost)------------ Server Hello
Client Hello ------------------------->
Client Hello ------------------------->
Client Hello ------------------------->
             <------------------------- Server Hello
Rest of the handshake ---------------->
                      <---------------- Rest of the handshake

Я могу легко воспроизвести его даже в локальной среде прямое удаление первого сервера Hello.

Мне любопытно, почему сервер не отвечает на несколько предстоящих приветствий клиента. Если он ответит, что рукопожатие может завершиться значительно менее чем за 1 секунду, но таким образом это займет 1-2 секунды, когда он, наконец, ответит снова для последующих приветствий клиента.

Как я могу сделать так, чтобы рукопожатие DTLS завершалось быстрее? (например, путем включения ответа для всех клиентов Hello), есть ли способ?)

1 Ответ

0 голосов
/ 30 марта 2020

В OpenSSL установленный по умолчанию таймер передачи DTLS начинается с 1 секунды и периодически удваивается, если он не получил ответ. В вашем случае сервер отправил свой ServerHello (и предположительно ServerHelloDone и, возможно, другие сообщения - но вы этого не показываете) и теперь ожидает сообщения ClientKeyExchange. Предполагается, что любые последующие ClientHellos, полученные от того же однорангового узла, являются устаревшими повторными передачами и игнорируются.

Вы можете заставить сервер работать без сохранения состояния, используя DTLSv1_listen (), что означает, что сервер будет прослушивать соединения от любого однорангового узла и принимать любые ClientHello приходит от нового партнера и немедленно отвечает на него - хотя в этом случае он добавляет дополнительный прием туда и обратно, потому что все ClientHello должны иметь «cook ie» в них. Это также не решило бы никаких проблем с потерей пакетов позже в рукопожатии - так что это действительно не поможет вашей проблеме здесь.

В OpenSSL 1.1.1 вы можете использовать собственный обратный вызов таймера DTLS для управления тайм-аутами по таймеру через DTLS_set_timer_cb ():

https://www.openssl.org/docs/man1.1.1/man3/DTLS_set_timer_cb.html

Вот пример, который устанавливает начальный таймер равным 50 мс и периодически удваивает его (50 мс, вероятно, слишком короткий для реализации на основе сети - но этот конкретный пример является тестом «в памяти»):

https://github.com/openssl/openssl/blob/20c98cd45399423f760dbd75d8912769c6b7b10e/test/dtlstest.c#L45 -L53

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

...