HTTPS下CURL请求报403错误排查(GoDaddy跨主机场景)
场景
从独立IP主机的子域名yyy.xxx.com(sendfeed.php)向另一IP主机的主域名xxx.com(receivefeed.php)发起POST请求,receivefeed.php收到参数后需发送邮件。本地及自有生产服务器运行正常,但在GoDaddy服务器上出现异常。
代码实现
function curl2($url, $urlencoded) { $options = null; $headers = false; $cacert='/home/ooo/public_html/cacert.pem'; $vbh = fopen('php://temp', 'w+'); session_write_close(); /* Initialise curl request object */ $curl=curl_init(); if (parse_url($url, PHP_URL_SCHEME)=='https') { curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2); curl_setopt($curl, CURLOPT_CAINFO, $cacert); } /* Define standard options */ curl_setopt($curl, CURLOPT_POST, true); curl_setopt($curl, CURLOPT_POSTFIELDS, $urlencoded); curl_setopt($curl, CURLOPT_URL, trim($url)); curl_setopt($curl, CURLOPT_AUTOREFERER, true); curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); curl_setopt($curl, CURLOPT_FAILONERROR, true); curl_setopt($curl, CURLOPT_HEADER, false); curl_setopt($curl, CURLINFO_HEADER_OUT, false); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_BINARYTRANSFER, true); curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 20); curl_setopt($curl, CURLOPT_TIMEOUT, 60); curl_setopt($curl, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'); curl_setopt($curl, CURLOPT_MAXREDIRS, 10); curl_setopt($curl, CURLOPT_ENCODING, ''); curl_setopt($curl, CURLOPT_VERBOSE, true); curl_setopt($curl, CURLOPT_NOPROGRESS, true); curl_setopt($curl, CURLOPT_STDERR, $vbh); /* Assign runtime parameters as options */ if (isset($options) && is_array($options)) { foreach ($options as $param => $value) { curl_setopt($curl, $param, $value); } } if ($headers && is_array($headers)) { curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); } /* Execute the request and store responses */ $res=(object)array( 'response' => curl_exec($curl), 'info' => (object)curl_getinfo($curl), 'errors' => curl_error($curl) ); rewind($vbh); $res->verbose=stream_get_contents($vbh); fclose($vbh); curl_close($curl); return $res; } $vars = array( 'act'=>$_GET['act'] ); $urlencoded = http_build_query($vars); $res=curl2("https://www.example.com/test/receivefeed.php",$urlencoded); print_r($res->verbose);
错误响应(Verbose日志)
Trying xxx.xxx.xxx.108:443...
Connected to www.example.com (xxx.xxx.xxx.108) port 443 (#0)
ALPN: offers h2
ALPN: offers http/1.1
CAfile: /home/ooo/public_html/cacert.pem
CApath: none
SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
ALPN: server accepted h2
Server certificate:
subject: CN=example.com
start date: Apr 6 13:34:23 2023 GMT
expire date: Apr 6 13:34:23 2024 GMT
subjectAltName: host "www.example.com" matched cert's "www.example.com"
issuer: C=US; ST=Arizona; L=Scottsdale; O=GoDaddy.com, Inc.; OU=http://certs.godaddy.com/repository/; CN=Go Daddy Secure Certificate Authority - G2
SSL certificate verify ok.
Using HTTP2, server supports multiplexing
Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
h2h3 [:method: POST]
h2h3 [:path: /test/receivefeed.php]
h2h3 [:scheme: https]
h2h3 [:authority: www.example.com]
h2h3 [user-agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36]
h2h3 [accept: /]
h2h3 [accept-encoding: deflate, gzip]
h2h3 [content-length: 5]
h2h3 [content-type: application/x-www-form-urlencoded]
Using Stream ID: 1 (easy handle 0x2cefdd0)POST /test/receivefeed.php HTTP/2 Host: www.example.com user-agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 accept: / accept-encoding: deflate, gzip content-length: 5 content-type: application/x-www-form-urlencoded
We are completely uploaded and fine
old SSL session ID is stale, removing
Connection state changed (MAX_CONCURRENT_STREAMS == 128)! < HTTP/2 403 < server: nginx < date: Mon, 29 May 2023 12:48:39 GMT <
content-type: text/html < x-sucuri-id: 11008 < x-xss-protection: 1; mode=block < x-frame-options: SAMEORIGIN < x-content-type-options: nosniff < content-security-policy: upgrade-insecure-requests; <
x-sucuri-block: FBP007
The requested URL returned error: 403
当前问题
- HTTPS请求返回403,响应含
x-sucuri-block: FBP007标识 - HTTP请求返回200,但GoDaddy会将80端口请求重定向到443并转为GET,导致POST参数丢失
1. 处理Sucuri防火墙拦截
x-sucuri-block: FBP007是Sucuri防火墙的拦截规则,针对自动化流量或异常请求触发:
- 登录目标服务器的Sucuri控制台,将GoDaddy服务器的IP加入白名单
- 调整Sucuri防火墙规则,允许来自
yyy.xxx.com的POST请求
2. 优化CURL请求参数
调整请求特征,避免被防火墙识别为异常流量:
- 添加
Referer头,模拟正常浏览器跳转:curl_setopt($curl, CURLOPT_REFERER, 'https://yyy.xxx.com/sendfeed.php'); - 强制使用HTTP/1.1(部分防火墙对HTTP/2的兼容性处理存在问题):
curl_setopt($curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); - 指定明确的编码类型,替代空值配置:
curl_setopt($curl, CURLOPT_ENCODING, 'gzip, deflate');
3. 修复HTTP重定向丢失POST参数问题
若需使用HTTP请求,配置CURL保留重定向后的POST方法:
curl_setopt($curl, CURLOPT_POSTREDIR, 3); // 3表示所有重定向均保留POST方法
注:该参数需PHP 5.3.2+及CURL 7.19.1+版本支持
4. 修正SSL证书验证配置
当前代码禁用了SSL证书验证,存在安全风险且易被防火墙标记:
- 确保
cacert.pem路径正确且为最新版本 - 启用SSL证书验证:
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);
内容的提问来源于stack exchange,提问作者Apurva

