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
и это должно работать.
Для серверной стороны это немного сложнее. Я сделал пост и пример реализации