使用OpenSSL BIO实现无阻塞I/O

Non-Blocking I/O With OpenSSL BIO

本文关键字:OpenSSL BIO 实现 使用      更新时间:2023-10-16

我在Linux上使用的是OpenSSL 1.0.0-fips。我遇到的问题是SSL_connect()返回-1,而SSL_get_error()返回SSL_ERROR_WANT_READ。然后,我将文件描述符放入select()中,timeval结构设置为10秒,select()刚好超时。

我启动了Wireshark,我看到"客户端你好"熄灭,我看到ServerHello回到客户端,但它从未在select()中"醒来"。它只是超时。

我的问题是:

  1. 是否必须使用BIO_new_socket()创建一个BIO对象,然后使用SSL_set_bio()将该BIO对象分配给我的SSL对象?SSL_set_fd()的手册页说它将自动创建一个BIO对象,这似乎意味着SSL_set_bio()是一个无用的函数,你永远不必真正调用它。

  2. 假设我们使用SSL_set_fd()并分配一个正在阻塞的连接TCP文件描述符。假设我们稍后使用fcntl()将该文件描述符更改为非阻塞。这是否会破坏SSL对象(或底层BIO对象)?

1)是否必须使用BIO_new_socket()创建一个BIO对象,然后使用SSL_set_BIO()将BIO对象分配给我的SSL对象?那个男人SSL_set_fd()的页面表示它将自动创建一个BIO对象所以这似乎意味着SSL_set_bio()有点无用函数,而您从未真正调用过该函数。

如果默认的BIO对象足以满足您的需要,那么您不必手动创建和安装自己的BIO。SSL_set_bio()调用就在那里,以防您想要创建/使用与SSL_set_fd()代表您创建的默认对象不同的bio对象。

2)假设我们使用SSL_set_fd()并分配一个连接的TCP文件正在阻塞的描述符。让我们说,我们以后会改变这一点使用fcntl()将文件描述符设置为非阻塞。这会破坏SSL吗对象(或底层BIO对象)?

是的,我相信它会坏掉的。非阻塞OpenSSL的调用模式与阻塞OpenSSL时使用的调用模式非常不同,我不相信您可以在运行中从一种模式来回切换到另一种模式。也就是说,我自己还没有尝试过,所以我可能错了,但我认为为了安全起见(并保持一致),你应该提前选择使用阻塞或非阻塞I/O,并在连接期间坚持使用它。

特别是,手册页中的这句话:

BIO和SSL引擎继承fd的行为。

。。。建议SSL设置调用将检查fd的状态,并根据fd的阻塞/非阻塞状态在BIO和SSL对象中设置私有变量。如果你"背着OpenSSL"改变fd的行为,OpenSSL的例程就不会预料到这一点,很可能会做错事,无法正常工作。