大文件的 cURL SSL 错误
cURL SSL error with large file
我正在尝试对我的生产服务器进行一些备份,然后将备份压缩到 tar.gz 发送到另一台服务器。在将我的服务器更新为 php7.2-fpm(对于 HTTP2.0)之前,这工作正常。
我收到这个错误:
Fatal error: Uncaught Exception: SSL read: error:00000000:lib(0):func(0):reason(0), errno 104
这是我的两台服务器的配置:
- 生产服务器:
- 系统:Linux debian2 4.9.0-6-amd64 #1 SMP Debian 4.9.88-1+deb9u1 (2018-05-07) x86_64
- 阿帕奇:Apache/2.4.33
- Php:PHP 版本 7.2.5-1(使用 FPM api)
- 备份服务器:
- 系统:Linux debian2 3.16.0-4-amd64 #1 SMP Debian 3.16.51-3 (2017-12-13) x86_64
- 阿帕奇:Apache/2.4.10
- Php:PHP 版本 7.1.13-1(带有 Apache 2.0 处理程序)
备用服务器仍然使用HTTP1,生产服务器使用HTTP2协议。
因此,为了进行备份,我转到我的根文件夹并将其中的所有内容压缩为 .tar.gz。
发送文件到这里是我使用的代码:
/**
* @brief Sends a file.
* @param Array $data The data to send (backup file path, file name)
* @param String|string $action The action (platformBackup, databaseBackup)
* @return Array|boolean
*/
public static function sendFile(Array $data, String $action) : Array
{
$cFile = curl_file_create($data['file']);
$data['save'] = $cFile;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,SERVER_SAVE_URL.'/'.SERVER_SAVE_TOKEN.'/' . $action . '/'.PLATEFORM_ID);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_HTTPHEADER,array('Content-Type: multipart/form-data'));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$result = curl_exec($ch);
if ($result === false)
{
throw new Exception(curl_error($ch), curl_errno($ch));
}
$result = json_decode($result, true);
return $result;
}
这适用于小文件(小于 1Gb)。但不是更大的。
我的第一个想法是 Apache 和 php7.2-fpm 的配置不正确,因为之前一切正常。
但我认为这没问题,这是我在 php/7.2/fpm/php.ini 中更改的变量:
max_execution_time = 10800
memory_limit = 1024M
post_max_size = 10000M
upload_max_filesize = 10000M
我也尝试在 php/7.2/fpm/pool.d/www.conf 中强制使用它们,但没有任何改变。
在此先感谢您的帮助!
编辑:
我将备份服务器更新为 Apache 2.4.33 并使用 php7.2-fpm 启用 HTTP2.0 协议。当我尝试备份时,我在错误日志中收到一条消息:
[Tue Jun 12 13:10:34.829260 2018] [proxy_fcgi:error] [pid 9092:tid 140388941666048] (70008)Partial results are valid but processing is incomplete: [client XXX.XXX.XXX.XXX:XXX] AH01075: Error dispatching request to : (reading input brigade)
从 php7.1-fpm 服务器我得到
503 Service Unavailable
从 php7.2-fpm 我得到:
Fatal error: Uncaught Exception: SSL read:error:00000000:lib(0):func(0):reason(0), errno 104
因为 php 和 apache 没有任何效果我告诉自己问题出在其他地方,我观察我的文件系统是 ext4 所以大文件没有问题我尝试用 SCP 发送备份它工作也很棒。所以对我来说,问题只来自 PHP、Apache 或 cURL。
提醒一下,备份适用于小型服务器 (800mb) 但不适用于大型服务器 (3.4Gb)
编辑 1:
似乎 SSL 是问题所在,当我在备份服务器上禁用它时,一切正常。作为临时解决方案,我只是用带有生成密钥的 openssl 加密文件并将其发送到我的备份服务器。
编辑: 在这些其他主题中:
- Request Entity Too Large
- https://serverfault.com/questions/709646/apache-2-2-ssl-large-file-upload-fail
解释了如何在 apache 配置中增加 SSL 缓冲区大小(这可能是您的问题)。
<Directory /my/site/here>
...
# Set this to something big...
SSLRenegBufferSize 10486000
...
</Directory>
来源:@kongekrabben
**
我在我们公司的应用程序中看到了很多这样的问题,主要是因为网络服务器很旧,无法支持新的密码套件。
为了完全放弃 SSL,我会 运行 使用 openssl 进行以下测试:
测试 TLS1.2
openssl s_client -connect ${DoMain}:${port} -tls1_2
将 -tls1_2
更改为 tls1
或 tls1_1
或 ssl3
以测试其他密码套件。
上面将模拟 SSL 握手和传输,如果一切顺利,它应该以退出代码 0 结束。
要读取 bash 处的退出代码,只需 echo $?
执行上一个命令后
然后,nmap 扫描将列出服务器上所有可用的 SSL 密码,请注意这是一种侵入性测试,实际上可能会触发安全软件,从而导致请求者的 IP 被禁止。除非您确定自己在做什么,否则不要使用第二个测试:
nmap --script ssl-enum-ciphers ${DoMain}
希望这对您有所帮助。
然后,根据结果在您的 PHP libcurl 声明中设置:
curl_setopt($ch, CURLOPT_SSLVERSION, $int);
其中 $int
代表要使用的 SSL 密码套件:
- CURL_SSLVERSION_DEFAULT (0)
- CURL_SSLVERSION_TLSv1 (1)
- CURL_SSLVERSION_SSLv2 (2)
- CURL_SSLVERSION_SSLv3 (3)
- CURL_SSLVERSION_TLSv1_0 (4)
- CURL_SSLVERSION_TLSv1_1 (5)
- CURL_SSLVERSION_TLSv1_2 (6)
文档:http://php.net/manual/en/function.curl-setopt.php
@Whosebug 管理员: 很抱歉,我想发表评论,但积分不足。请编辑或 copy/paste 然后删除我的答案并在需要时将其放在评论中。
我正在尝试对我的生产服务器进行一些备份,然后将备份压缩到 tar.gz 发送到另一台服务器。在将我的服务器更新为 php7.2-fpm(对于 HTTP2.0)之前,这工作正常。
我收到这个错误:
Fatal error: Uncaught Exception: SSL read: error:00000000:lib(0):func(0):reason(0), errno 104
这是我的两台服务器的配置:
- 生产服务器:
- 系统:Linux debian2 4.9.0-6-amd64 #1 SMP Debian 4.9.88-1+deb9u1 (2018-05-07) x86_64
- 阿帕奇:Apache/2.4.33
- Php:PHP 版本 7.2.5-1(使用 FPM api)
- 备份服务器:
- 系统:Linux debian2 3.16.0-4-amd64 #1 SMP Debian 3.16.51-3 (2017-12-13) x86_64
- 阿帕奇:Apache/2.4.10
- Php:PHP 版本 7.1.13-1(带有 Apache 2.0 处理程序)
备用服务器仍然使用HTTP1,生产服务器使用HTTP2协议。
因此,为了进行备份,我转到我的根文件夹并将其中的所有内容压缩为 .tar.gz。
发送文件到这里是我使用的代码:
/**
* @brief Sends a file.
* @param Array $data The data to send (backup file path, file name)
* @param String|string $action The action (platformBackup, databaseBackup)
* @return Array|boolean
*/
public static function sendFile(Array $data, String $action) : Array
{
$cFile = curl_file_create($data['file']);
$data['save'] = $cFile;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,SERVER_SAVE_URL.'/'.SERVER_SAVE_TOKEN.'/' . $action . '/'.PLATEFORM_ID);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_HTTPHEADER,array('Content-Type: multipart/form-data'));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$result = curl_exec($ch);
if ($result === false)
{
throw new Exception(curl_error($ch), curl_errno($ch));
}
$result = json_decode($result, true);
return $result;
}
这适用于小文件(小于 1Gb)。但不是更大的。
我的第一个想法是 Apache 和 php7.2-fpm 的配置不正确,因为之前一切正常。
但我认为这没问题,这是我在 php/7.2/fpm/php.ini 中更改的变量:
max_execution_time = 10800
memory_limit = 1024M
post_max_size = 10000M
upload_max_filesize = 10000M
我也尝试在 php/7.2/fpm/pool.d/www.conf 中强制使用它们,但没有任何改变。
在此先感谢您的帮助!
编辑:
我将备份服务器更新为 Apache 2.4.33 并使用 php7.2-fpm 启用 HTTP2.0 协议。当我尝试备份时,我在错误日志中收到一条消息:
[Tue Jun 12 13:10:34.829260 2018] [proxy_fcgi:error] [pid 9092:tid 140388941666048] (70008)Partial results are valid but processing is incomplete: [client XXX.XXX.XXX.XXX:XXX] AH01075: Error dispatching request to : (reading input brigade)
从 php7.1-fpm 服务器我得到
503 Service Unavailable
从 php7.2-fpm 我得到:
Fatal error: Uncaught Exception: SSL read:error:00000000:lib(0):func(0):reason(0), errno 104
因为 php 和 apache 没有任何效果我告诉自己问题出在其他地方,我观察我的文件系统是 ext4 所以大文件没有问题我尝试用 SCP 发送备份它工作也很棒。所以对我来说,问题只来自 PHP、Apache 或 cURL。
提醒一下,备份适用于小型服务器 (800mb) 但不适用于大型服务器 (3.4Gb)
编辑 1:
似乎 SSL 是问题所在,当我在备份服务器上禁用它时,一切正常。作为临时解决方案,我只是用带有生成密钥的 openssl 加密文件并将其发送到我的备份服务器。
编辑: 在这些其他主题中:
- Request Entity Too Large
- https://serverfault.com/questions/709646/apache-2-2-ssl-large-file-upload-fail
解释了如何在 apache 配置中增加 SSL 缓冲区大小(这可能是您的问题)。
<Directory /my/site/here>
...
# Set this to something big...
SSLRenegBufferSize 10486000
...
</Directory>
来源:@kongekrabben
**
我在我们公司的应用程序中看到了很多这样的问题,主要是因为网络服务器很旧,无法支持新的密码套件。
为了完全放弃 SSL,我会 运行 使用 openssl 进行以下测试:
测试 TLS1.2
openssl s_client -connect ${DoMain}:${port} -tls1_2
将 -tls1_2
更改为 tls1
或 tls1_1
或 ssl3
以测试其他密码套件。
上面将模拟 SSL 握手和传输,如果一切顺利,它应该以退出代码 0 结束。
要读取 bash 处的退出代码,只需 echo $?
执行上一个命令后
然后,nmap 扫描将列出服务器上所有可用的 SSL 密码,请注意这是一种侵入性测试,实际上可能会触发安全软件,从而导致请求者的 IP 被禁止。除非您确定自己在做什么,否则不要使用第二个测试:
nmap --script ssl-enum-ciphers ${DoMain}
希望这对您有所帮助。
然后,根据结果在您的 PHP libcurl 声明中设置:
curl_setopt($ch, CURLOPT_SSLVERSION, $int);
其中 $int
代表要使用的 SSL 密码套件:
- CURL_SSLVERSION_DEFAULT (0)
- CURL_SSLVERSION_TLSv1 (1)
- CURL_SSLVERSION_SSLv2 (2)
- CURL_SSLVERSION_SSLv3 (3)
- CURL_SSLVERSION_TLSv1_0 (4)
- CURL_SSLVERSION_TLSv1_1 (5)
- CURL_SSLVERSION_TLSv1_2 (6)
文档:http://php.net/manual/en/function.curl-setopt.php
@Whosebug 管理员: 很抱歉,我想发表评论,但积分不足。请编辑或 copy/paste 然后删除我的答案并在需要时将其放在评论中。