21

我们已经使用 openssl 实现了 tls。从服务器下载较大数据时SSL_ERROR_SYSCALL收到一些数据后出现错误。对于较小的文件,我没有收到此错误,可以毫无错误地下载。对于较大的文件,ERR_get_error() 显示为零。

我们正在使用 linux 和 c++ 框架。如何寻找失败的原因?失败的原因可能是什么?请提供您的建议。

4

6 回答 6

13

SSL_ERROR_SYSCALL 表示底层 I/O 发生了一些问题(在这种情况下应该是 TCP)。因此,您可以尝试使用 errno 进行检查。

OpenSSL 帮助说:

SSL_ERROR_SYSCALL

发生了一些 I/O 错误。OpenSSL 错误队列可能包含有关错误的更多信息。如果错误队列为空(即 ERR_get_error() 返回 0),则可以使用 ret 来查找有关错误的更多信息:如果 ret == 0,则观察到违反协议的 EOF。如果 ret == -1,则底层 BIO 报告 I/O 错误(对于 Unix 系统上的套接字 I/O,请参阅 errno 了解详细信息)。

于 2012-12-03T15:49:00.837 回答
5

如果您查看源代码,SSL_get_error()您会看到,SSL_ERROR_SYSCALL只要不确定到底发生了什么,它就会返回。它基本上是“未知”情况的默认返回码。

例如,在我的情况下(使用 BIO 进行非阻塞 IO):

int buf;
const int n = SSL_read(ssl, &buf, 0);
const int err = SSL_get_error(ssl, n);
const int st = ERR_get_error();

n为 0 时,errSSL_ERROR_SYSCALL只是因为。但是st仍然为 0,表示没有真正的错误。SSL_read刚刚返回 0,因为 0 字节被写入buf.

但是,请在调用后查找errno/WSAGetLastError()值以获取更多详细信息。

于 2015-02-24T20:16:46.447 回答
4

检查是否调用了缓冲区大小为 0 的 SSL_read()。我使用 SSL_pending() 犯了以下错误:

int waitForReadFd = nBuf < bufSize;

if (waitForReadFd)
    FD_SET(fd, &rfds);

// ...
// select

int doReadFd = FD_ISSET(fd, &rfds) || SSL_pending(ssl);

if (doReadFd)
    n = SSL_read(ssl, buf, bufSize - nBuf);

如果nBuf == bufSizeSSL_read() 将以 0 的缓冲区大小调用,则会导致 errno == 0 的 SSL_ERROR_SYSCALL。

更改 doReadFd 检查将避免此问题:

int doReadFd = FD_ISSET(fd, &rfds) || nBuf < bufSize && SSL_pending(ssl);
于 2015-05-04T09:35:51.653 回答
4

我发现问题是我公司的防火墙阻止了请求。回家吧,它应该工作

于 2018-10-12T22:05:44.903 回答
2

该问题是由于网络连接被切断和服务器重新设置引起的。

在下载数据之前确保连接正常。

使用 vagrant 时也可以看到类似的问题。

https://github.com/hashicorp/vagrant/issues/9612

于 2018-05-29T16:44:43.340 回答
0

我们在 Go 应用程序中遇到了这个错误。我们使用第三方库从 Go 连接到底层的 openssl 库。在读取数据时,第三方库正在将要读取的缓冲区/数据的长度转换为 32 位的 C.int。对于 >= 2GB 的大数据,这会导致溢出并将负值传递给 C.SSL_read 函数。在这种情况下,它引发了 SSL_ERROR_SYSCALL 错误。

于 2020-07-10T11:10:09.807 回答