Клиент OpenSSL C ++ DTLS

Я пытаюсь установить соединение DTLS с помощью openssl (c ++).

Однако, несмотря на то, что на стороне сервера есть функция DTLSv1_listen(), я не могу найти никакого эквивалента на стороне клиента, чтобы фактически установить соединение UDP с сервером от клиента. Или отправьте что-нибудь на сервер DTLS. Может ли кто-нибудь помочь мне понять, как установить «соединение» с сервером DTLS (я знаю, что связь UDP и дейтаграммы должна быть без установления соединения, но под соединением я имею в виду такую ​​схему, как запрос DNS + ответ)?

Мне нужно отправить одно сообщение на сервер, а затем получить одно ответное сообщение. Зашифрованный. С проверкой сертификата. Как такая схема связи будет работать в мире DTLS?


person Lapsio    schedule 06.06.2017    source источник
comment
DTLS, как и UDP, работает и забывает. Вы не устанавливаете соединение. Это не протокол, ориентированный на соединение. Вы отправляете сообщение. Он может прийти, а может и нет. Вам решать, как вести бухгалтерский учет и повторять попытки, пока не придет сообщение. Как говорится, те, кто не использует TCP / IP, обязательно изобретут его заново.   -  person jww    schedule 06.06.2017
comment
да, но как мне на самом деле стрелять? Я не вижу такой функции openssl, как SSL_DTLSv1_sendto()   -  person Lapsio    schedule 06.06.2017
comment
Ознакомьтесь с dtlstest.c OpenSSL. Это ничем не отличается от TLS-соединения. Просто напишите или прочтите BIO. Возможно, вас заинтересует methods.c. Обратите внимание, что TLS и DTLS выглядят почти одинаково, когда вы получаете метод для создания контекста.   -  person jww    schedule 06.06.2017


Ответы (2)


Что вы используете для сигнализации. На самом деле вам не нужно использовать openssl для вашего сигнального уровня, вы можете использовать Memory Bio и читать и писать из него.

С DTLS у вас будет 2 стороны: клиент и сервер. Клиент будет инициировать действия с помощью приветствия клиента. Сервер, надеюсь, получает его, записывает в биографию, считывает сообщение Server Hello и отвечает через уровень сигнализации.

Чтобы действительно довести ваше приложение до реального мира, требуется много всего, поэтому я не буду описывать все.

Если у вас есть SSL-контекст и вы создали свой BIO. Чтобы запустить сервер:

SSL_set_accept_state(*sslContext)

и инициировать клиента:

SSL_set_connect_state(*sslContext);

Затем вы хотите начать рукопожатие на клиенте. Здесь очень много факторов, влияющих на то, как ваше приложение будет усердно работать, чтобы давать советы, но клиент должен позвонить:

SSL_do_handshake(*sslContext);

В зависимости от того, как вы все подключили, ваша программа может автоматически отправлять клиенту привет на этом этапе. Вы можете использовать Wireshark, захватить только UDP и сверху отфильтровать DTLS, чтобы увидеть его. В противном случае вам может потребоваться подать сигнал вручную.

Я сам написал следующую программу, чтобы проверить DLL OpenSSL, чтобы увидеть, есть ли какие-либо проблемы после их компиляции. Я не могу поделиться с вами всем кодом, но он показывает, как в памяти вы можете использовать одно консольное приложение для рукопожатия (без передачи через Интернет, чтобы увидеть, как это работает).

Примечания:

В этом случае BIO является памятью BIO.

Рукопожатие - это SSL_do_handshake

WriteCipherText - это вызов BIO_write

ReadCipherText - это вызов BIO_read

Вы должны сначала открыть его и выполнить другие основные настройки. В конце оба рукопожатия вернут 1 для успешного выполнения. Это просто как бы показывает вам, как выполнить базовое рукопожатие DTLS памяти с помощью openssl.

Console.WriteLine("[Client] Open: " + Client.Open("ECDHE-ECDSA-AES128-SHA:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:AES128-SHA:AES128-GCM-SHA256:AES128-SHA256", "SRTP_AES128_CM_SHA1_80"));
            Console.WriteLine("[Server] Open: " + Server.Open("ECDHE-ECDSA-AES128-SHA:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:AES128-SHA:AES128-GCM-SHA256:AES128-SHA256", "SRTP_AES128_CM_SHA1_80"));

            Console.WriteLine("[Client] Handshake" + Client.Handshake());
            Console.WriteLine("Client: [Read] Client Hello");
            var clientHello = Client.ReadCipherText();
            Console.WriteLine("[Server] Write Hello: " + Server.WriteCipherText(clientHello));
            Console.WriteLine("[Server] Handshake" + Server.Handshake());
            clientHello.Free();
            Console.WriteLine("[Server] Read Server Hello");
            var serverHello = Server.ReadCipherText();
            Console.WriteLine("[Client] Write Server Hello: " + Client.WriteCipherText(serverHello));
            Console.WriteLine("[Client] Handshake" + Client.Handshake());
            serverHello.Free();
            Console.WriteLine("[Client] Read Certificate");
            var clientCertificate = Client.ReadCipherText();
            Console.WriteLine("[Server] Write Certificate: " + Server.WriteCipherText(clientCertificate));
            Console.WriteLine("[Server] Handshake: " + Server.Handshake());
            clientCertificate.Free();
            Console.WriteLine("[Server] Read Change Cipher Spec");
            var serverChangeCipherSpec = Server.ReadCipherText();
            Console.WriteLine("[Client] Write Change Cipher Spec: " + Client.WriteCipherText(serverChangeCipherSpec));
            serverChangeCipherSpec.Free();
            Console.WriteLine("[Client] Handshake" + Client.Handshake());
            Console.WriteLine("[Server] Handshake" + Server.Handshake());
            Console.ReadLine();

Также есть много полезных ресурсов, на которые стоит обратить внимание: https://web.archive.org/web/20150814081716/http://sctp.fh-muenster.de/dtls-samples.html Эти действительно хорошие

http://chris-wood.github.io/2016/05/06/OpenSSL-DTLS.html https://wiki.openssl.org/index.php/SSL/TLS_Client

person Jake Steele    schedule 22.01.2019

На стороне клиента вы создаете UDP-socket, передаете его с BIO_new_dgram в контекст SSL и соединяете с connect() или BIO_ctrl(bio, BIO_CTRL_DGRAM_SET_CONNECTED, 0, &server_sockaddr). Соединение просто заставляет дескрипторы файлов всегда отправлять запись в server_sockaddr.

Теперь просто сделайте обычный SSL_connect, и он должен работать.

Для серверной части все немного сложнее. Я сделал сообщение и пример реализации

person Hopeanuoli    schedule 06.12.2018