OpenSSL C ++ DTLS客户端

时间:2017-06-06 04:13:20

标签: c++ openssl udp dtls

我正在尝试使用openssl(c ++)建立DTLS连接。

然而,虽然服务器端有DTLSv1_listen()函数,但我找不到任何客户端等效于实际建立从客户端到服务器的UDP连接。或者向DTLS服务器发送内容。有人可以帮我理解如何建立与DTLS服务器的“连接”(我知道UDP和数据报通信的要点是无连接但是连接我的意思是像DNS请求+响应这样的方案)?

我需要向服务器发送单个消息,然后接收1个响应消息。加密。有证书验证。这种通信方案如何在DTLS世界中发挥作用?

2 个答案:

答案 0 :(得分:0)

您正在使用什么信号。实际上,您不必在信号层中使用openssl,您可以使用Memory Bio并从中读取和写入。

使用DTLS,您将在此处有两个方面,一个客户端和一个服务器。客户端将与客户端Hello进行交互。服务器希望收到它,将其写入生物,回读服务器Hello并通过信令层做出响应。

要真正完成您的应用程序需要很多工作,所以我不会介绍所有内容。

如果您具有SSL上下文,并且已经创建了BIO。要启动服务器:

SSL_set_accept_state(*sslContext)

并启动客户端:

SSL_set_connect_state(*sslContext);

然后,您要在客户端上开始握手。关于您的应用程序将如何工作的困难因素很多,但是客户应该致电:

SSL_do_handshake(*sslContext);

根据您如何连接所有内容,程序可能会在此时自动发送客户端问候。您可以使用Wireshark,仅获取UDP,并在顶部的过滤器DTLS中查看它。如果没有,您可能需要手动发信号。

我自己编写了以下程序来测试OpenSSL dll,以查看编译后是否存在任何问题。我无法与您共享所有代码,但是它显示了如何在内存中使用单个控制台应用程序进行握手(仅通过互联网进行传输即可查看其工作原理)。

注意:

在这种情况下,BIO是内存BIO。

握手是SSL_do_handshake

WriteCipherText是对BIO_write的调用

ReadCipherText是对BIO_read的调用

您必须先打开它并执行其他基本设置状态。最后,两次握手都会成功返回1。这类方法向您展示了如何使用openssl进行基本的内存DTLS握手。

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

答案 1 :(得分:-1)

在客户端上创建UDP-socket,将其与BIO_new_dgram传递到SSL上下文,并将其与connect()BIO_ctrl(bio, BIO_CTRL_DGRAM_SET_CONNECTED, 0, &server_sockaddr)连接。连接只是强制将文件描述符写入始终发送到server_sockaddr

现在只需执行常规的SSL_connect,它应该可以工作。

对于服务器端,它要复杂一些。我做了一个post和一个example implementation