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

pol*_*lux 6 sockets ssl client openssl nonblocking

我是openSSL的新手,我试图找出在使用非阻塞套接字时创建https连接的最佳/最佳解决方案,以及libevent,libev或libuv等库与内存BIO的组合.

我正在试图弄清楚如何管理openSSL调用/数据和应用程序数据.总之,我对ssl客户端应用程序应该如何工作的理解是这样的:

  • 创建SSL_CTX
  • 创建一个新的套接字连接(例如我正在使用libuv)
  • 创建两个内存BIO:
    • 一个充满了我从服务器收到的数据(readBio)
    • 另一个用于在应用程序代码中读取.(writeBio)
  • 创建SSL*并将状态设置为SSL_connect_state
  • 使用SSL_do_handshake启动握手过程
  • [loop]接收/发送数据

因为我正在使用libuv(但这可能是任何其他异步/非阻塞库),我有一个读取回调,在套接字上收到数据时会调用它.当我有必须写入套接字的数据时,我将这些数据传递 给库的写入函数(在此uv_write()),但在此之间我需要将调用放到SSL中.

因此,在调用SSL_do_handshake(...)之后,SSL会将一些数据存储到writeBIO中,我必须将其读入并传递到套接字中.我正在考虑的一个问题是,我如何知道SSL将数据存储到此BIO中,其次我如何知道何时应该通过套接字发送数据.

在查看了一些代码后,我发现在调用SSL_do_handshake()之后我必须从writeBIO中消耗掉.但接下来的步骤对我来说并不清楚.在结束握手的第一个字节之后,libuv的'event'循环将所有内容都设置为运动; 当新数据到达套接字时,我的' onread()回调被调用.但是我如何处理这些传入的数据呢?(例如,我自己保持SSL状态(< - 某些人建议我不要做的事情)).

虽然我已经看到很多使用阻塞套接字和核心SSL函数来建立连接的例子但我没有找到一个很好的干净/简约示例,它展示了如何将内存BIO用作客户端.

我已经粘贴了一些我用来测试openSSL的代码:https://gist.github.com/3989091

有谁可以描述使用SSL的异步/非阻塞套接字和内存BIO的过程?

谢谢R

Dar*_*ith 6

我还整理了一个使用内存 BIO 与非阻塞套接字和基于轮询的事件循环的基本示例。

ssl_server_nonblock.c

我认为在这里发布该示例的所有源代码是有意义的。但这里是示例代码的概述。

加密和未加密字节流

该图显示了读取和写入内存 BIO(rbio 和 wbio)如何分别与套接字读取和写入相关联。在入站流(数据进入程序)中,从套接字读取字节并通过 BIO_write 复制到 rbio 中。这表示将加密数据传输到 SSL 对象中。然后通过调用SSL_read获取未加密的数据。相反的情况发生在出站流上,将未加密的用户数据传送到加密数据的套接字写入中。

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

          |                                  |       |                     |
          |<-------------------------------->|       |<------------------->|
          |         encrypted bytes          |       |  unencrypted bytes  |
Run Code Online (Sandbox Code Playgroud)

  • @保罗。这个问题没有其他答案,我提供的链接提供了一个有据可查的代码示例,它准确地回答了这个问题。事实上,我开发了示例代码,因为我有同样的问题,并且在堆栈溢出的任何地方都没有得到解答。虽然我不能保证该链接将永远存在(在 github 上),但它确实存在,但它提供了价值。我不认为在这里发布几组文件是可行的或最有帮助的。此外,由于其他贡献者的原因,示例代码已经得到了发展,因此最好放在 github 等地方。 (3认同)