OpenSSL C++ DTLS клиент

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

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

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

0 ответов

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

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

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

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

SSL_set_accept_state(*sslContext)

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

SSL_set_connect_state(*sslContext);

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

SSL_do_handshake(*sslContext);

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

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

Заметки:

В этом случае БИО - это БИО памяти.

Рукопожатие - это 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

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

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

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

Другие вопросы по тегам