简体   繁体   English

如何将OpenSSL与内存BIO和非阻塞套接字一起使用

[英]How to use openSSL with memory BIOs and non blocking sockets

I'm new to openSSL and I trying to figure out what the best / good solution is to create a https connection when using non blocking sockets, and libraries such as libevent, libev or libuv in combination with memory BIOs. 我是openSSL的新手,我试图找出使用非阻塞套接字以及将libevent,libev或libuv之类的库与内存BIO结合使用时创建https连接的最佳/良好解决方案是什么。

I'm trying to figure out how to manage openSSL calls/data and application data. 我试图弄清楚如何管理openSSL调用/数据和应用程序数据。 In short my understanding of how a ssl client application should work is something like this: 简而言之,我对ssl客户端应用程序应如何工作的理解是这样的:

  • create SSL_CTX 创建SSL_CTX
  • create a new socket connection (eg I'm using libuv) 创建一个新的套接字连接(例如,我正在使用libuv)
  • create two memory BIOs: 创建两个内存BIO:
    • one is filled with data I receive from the server (readBio) 一个充满了我从服务器(readBio)收到的数据
    • the other one is used to in the application code to read from. 另一个用于在应用程序代码中读取。 (writeBio) (writeBio)
  • create a SSL* and set state to SSL_connect_state 创建一个SSL *并将状态设置为SSL_connect_state
  • start the handshake process with SSL_do_handshake 使用SSL_do_handshake开始握手过程
  • [loop] receive / send data [循环]接收/发送数据

As I'm using libuv (but this could be any other async/non-blocking library), I have a read callback that gets called when data is received on the socket. 当我使用libuv时(但这可以是任何其他异步/非阻塞库),我有一个读取回调,当在套接字上接收到数据时会调用该回调。 When I have data which must be written to the socket, I pass this data into a write function of the library (in this uv_write() ), but in between this I need to put the calls to SSL. 当我有必须写入套接字的数据时,我会将这些数据传递到库的write函数中(在uv_write() ),但是在这之间,我需要将调用转移到SSL。

So after calling SSL_do_handshake(...), SSL stores some data into the writeBIO which I must read and pass into the socket. 因此,在调用SSL_do_handshake(...)之后,SSL将一些数据存储到writeBIO中,我必须读取该数据并将其传递到套接字中。 One question I was thinking about, how do I know that SSL stores data into this BIO, and secondly how do I know when I should send this over the socket. 我正在思考的一个问题是,我如何知道SSL将数据存储到此BIO中,其次我如何知道何时应该通过套接字发送此数据。

After looking at some code, I figured out that I had to consume from the writeBIO after calling SSL_do_handshake(). 看了一些代码之后,我发现调用SSL_do_handshake()后必须从writeBIO中使用。 But the next steps are not clear to me. 但是下一步对我来说并不明确。 After s ending the first bytes from the handshake the 'event' loop of libuv sets everything in motion; 从握手结束第一个字节后,libuv的“事件”循环使所有动作都开始进行。 when new data arrives on the socket my ' onread() callback is called. 当新数据到达套接字时,将调用我的onread()回调。 But how do I handle this incoming data? 但是,如何处理这些传入数据? (eg do I keep SSL state myself (<-- something which some people have advised me not do to)). (例如,我是否自己保持SSL状态(<-有些人建议我要这样做))。

Although I've seen lots of examples which use blocking sockets and the core SSL functions to make a connection I haven't found a good clean/minimalistic example which shows how to use memory BIOs as a client. 尽管我看过很多使用阻塞套接字和SSL核心功能建立连接的示例,但我还没有找到一个很好的简洁示例,该示例展示了如何将内存BIO用作客户端。

I've pasted some code I'm using to test openSSL here: https://gist.github.com/3989091 我在此处粘贴了一些用于测试openSSL的代码: https ://gist.github.com/3989091

Someone around who can describe the process of using async/non-blocking sockets and memory BIOs with SSL? 周围有人可以描述使用SSL的异步/非阻塞套接字和内存BIO的过程吗?

Thanks R 谢谢R

I've also put together a basic example of using memory BIO's with non-blocking sockets and a poll based event loop. 我还整理了一个将内存BIO与非阻塞套接字和基于轮询的事件循环一起使用的基本示例。

ssl_server_nonblock.c ssl_server_nonblock.c

I don' think it makes sense to post all the source code of that example here. 我认为在此处发布该示例的所有源代码是没有道理的。 But here is the outline of what the example code does. 但是这里是示例代码的概述。

Flow of encrypted & unencrypted bytes 加密和未加密字节流

This diagram shows how the read and write memory BIO's (rbio & wbio) are associated with the socket read and write respectively. 该图显示了读写存储器BIO(rbio和wbio)如何分别与套接字读写相关联。 On the inbound flow (data into the program) bytes are read from the socket and copied into the rbio via BIO_write. 在入站流(程序中的数据)上,从套接字读取字节,然后通过BIO_write将其复制到rbio中。 This represents the the transfer of encrypted data into the SSL object. 这表示将加密数据传输到SSL对象。 The unencrypted data is then obtained through calling SSL_read. 然后,通过调用SSL_read获得未加密的数据。 The reverse happens on the outbound flow to convey unencrypted user data into a socket write of encrypted data. 在出站流上发生相反的情况,以将未加密的用户数据传送到加密数据的套接字写入中。

  +------+                                    +-----+
  |......|--> read(fd) --> BIO_write(rbio) -->|.....|--> SSL_read(ssl)  --> IN
  |......|                                    |.....|
  |.sock.|                                    |.SSL.|
  |......|                                    |.....|
  |......|<-- write(fd) <-- BIO_read(wbio) <--|.....|<-- SSL_write(ssl) <-- OUT
  +------+                                    +-----+

          |                                  |       |                     |
          |<-------------------------------->|       |<------------------->|
          |         encrypted bytes          |       |  unencrypted bytes  |

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM