文章目录

  • 场景
  • 期望
  • 问题
  • 解决思路
    • 考虑超时重试情况;
    • 考虑DNS缓存;
    • 输出curl_error($ch);
  • 最终结果
  • 扩展链接
  • 其他错误解决方法:
    • SSL: no alternative certificate subject name matches target host name
    • curl: (60) SSL certificate problem: unable to get local issuer certificate
    • Empty reply from server

场景

function httpGetWebInfo($url, $iptype = 6, $resolve = [], $timeout = 120)
{// $header = ["Cache-Control: no-cache"];$data = [];$ch = curl_init();curl_setopt($ch, CURLOPT_URL, $url);curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET'); //post方式提交curl_setopt($ch, CURLOPT_NOSIGNAL, true); // 为true,会导致DNS解析不受时间控制curl_setopt($ch, CURLOPT_CONNECTTIMEOUT_MS, 1000 * $timeout);curl_setopt($ch, CURLOPT_TIMEOUT_MS, 1000 * $timeout);curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);curl_setopt($ch, CURLOPT_HEADER, false); // 不需要输出头部信息 -Icurl_setopt($ch, CURLOPT_NOBODY, true); // 不输出内容curl_setopt($ch, CURLOPT_IPRESOLVE, 4 == $iptype ? CURL_IPRESOLVE_V4 : CURL_IPRESOLVE_V6);curl_setopt($ch, CURLOPT_RETURNTRANSFER, false); //设置是否将响应结果存入变量,1是存入,0是直接echo出;curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); //抓取跳转 -L --location// curl_setopt($ch, CURLOPT_HTTPHEADER, $header); // HTTP 头字段的数组// curl_setopt($ch, CURLOPT_FRESH_CONNECT, true); // 强制获取一个新的连接,而不是缓存中的连接// curl_setopt($ch, CURLOPT_DNS_CACHE_TIMEOUT, 0); // 禁用DNS缓存 if (!empty($resolve)) {// curl -L -I -6 www.a.com --resolve www.a.com:80:<ipaddr>curl_setopt($ch, CURLOPT_RESOLVE, $resolve);curl_setopt($ch, CURLOPT_DNS_USE_GLOBAL_CACHE, false); //禁用DNS全局缓存}curl_exec($ch);if (!curl_errno($ch)) {$data = curl_getinfo($ch);}curl_close($ch);return $data;
}# 调用
$domainIPAddr = ['www.b.com' => '1.1.1.1','www.b.com' => '240c::2',
];foreach ($domainIPAddr as $domain => $ipaddr) {var_dump(getDnsRecord($domain, DNS_AAAA));$iptype = 判断ipaddr 类型 ? 4 : 6;$curl = httpGetWebInfo($domain, $iptype, ["{$domain}:80:{$ipaddr}"]);var_dump($curl);$state = empty($curl ) ? 0 : $curl ['http_code'];var_dump([$domain=>$state]);
}##  问题:
当打印出resolve IPv6时的 curl 缺总是显示 IPv4的信息解决方式:
添加curl_setopt($ch, CURLOPT_DNS_USE_GLOBAL_CACHE, false);

期望

使用IPv6解析DNS,并返回状态码

问题

通过CURLOPT_IPRESOLVE 控制使用IPv4解析域名还是IPv6解析,

但是当解析的域名不存在IPv6时,仍旧返回200的状态码,

curl_setopt($ch, CURLOPT_NOSIGNAL, true);
curl_setopt($ch, CURLOPT_IPRESOLVE, 4 == $iptype ? CURL_IPRESOLVE_V4 : CURL_IPRESOLVE_V6);

解决思路

考虑超时重试情况;

因为 curl在请求时,会默认请求域名解析的ipv6地址,如果ipv6地址请求失败,会timeout秒后请求正常的ipv4地址,所以这个时候,我们强制设置curl请求时,用ipv4地址

后经过排查返回的是结果是使用IPv4地址解析的,所以一直报200;
是因为 curl_setopt($ch, CURLOPT_NOSIGNAL, true); 导致DNS解析不受超时限制,会自动解析IPv4;
开启 CURLOPT_NOSIGNAL 导致DNS解析不受超时限制

考虑DNS缓存;

所以找如何清理DNS缓存;

无法从PHP手动清除DNS缓存。但是你可以使用 CURLOPT_DNS_CACHE_TIMEOUT,您可以将选项设置为0,以用于下一个请求以强制刷新curl的DNS缓存

Pass a long, this sets the timeout in seconds. Name resolves will be kept in memory and used for this number of seconds. Set to zero to completely disable caching, or set to -1 to make the cached entries remain forever. By default, libcurl caches this info for 60 seconds.

curl_setopt($ch, CURLOPT_DNS_CACHE_TIMEOUT, 0); // 禁用DNS缓存    无效
curl_setopt($ch, CURLOPT_DNS_USE_GLOBAL_CACHE, false); //禁用DNS全局缓存   有效另补充:禁用链接缓存
curl_setopt($ch, CURLOPT_HTTPHEADER, $header); // HTTP 头字段的数组
curl_setopt($ch, CURLOPT_FRESH_CONNECT, true); // 强制获取一个新的连接,而不是缓存中的连接

输出curl_error($ch);

报错信息:curl(7) xxxx permission denied
然后tcpdump 抓包,发现从 私网IPv6 出发的只有发包没有回包,也就是说进不到私网地址
所以考虑 在ip6tables上创建转发规则 ip6tables -I FORWARD -d <私网IPv6> -j ACCEPT

最终结果

ip6tables -I FORWARD -d <私网IPv6> -j ACCEPT

function httpGetWebInfo($url, $iptype = 6, $resolve = [], $timeout = 10)
{$data = [];$ch = curl_init();curl_setopt($ch, CURLOPT_URL, $url);curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET'); //post方式提交curl_setopt($ch, CURLOPT_NOSIGNAL, FALSE); // 如何为true,会导致DNS解析不受时间控制,导致程序一直pendingcurl_setopt($ch, CURLOPT_CONNECTTIMEOUT_MS, 1000 * $timeout);curl_setopt($ch, CURLOPT_TIMEOUT_MS, 1000 * $timeout);curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);curl_setopt($ch, CURLOPT_HEADER, true); // 不需要输出头部信息 -Icurl_setopt($ch, CURLOPT_NOBODY, true); // 不输出内容curl_setopt($ch, CURLOPT_IPRESOLVE, 4 == $iptype ? CURL_IPRESOLVE_V4 : CURL_IPRESOLVE_V6);curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); //设置是否将响应结果存入变量,1是存入,0是直接echo出;curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); //抓取跳转 -L --locationif (!empty($resolve)) {// curl -L -I -6 www.a.com --resolve www.a.com:80:<ipaddr>curl_setopt($ch, CURLOPT_RESOLVE, $resolve);curl_setopt($ch, CURLOPT_DNS_USE_GLOBAL_CACHE, false); //禁用DNS全局缓存   关键}curl_exec($ch);if (!curl_errno($ch)) {$data = curl_getinfo($ch);}curl_close($ch);return $data;
}

扩展链接

【PHP】 获取网站信息

如果要支持毫秒级别的超时设置必须加CURLOPT_NOSIGNAL, 否则直接返回超时,
当设置了小于1000ms的超时以后, curl不会发起任何请求,而直接返回超时错误(Timeout reached 28)】,这是PHP的坑,参考: http://www.laruence.com/2014/01/21/2939.html
timeout支持毫秒数在cURL 7.16.2中被加入,从PHP 5.2.3起可使用。

其他错误解决方法:

SSL: no alternative certificate subject name matches target host name

curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);

参考:https://www.php.net/manual/zh/function.curl-setopt.php#75711

curl: (60) SSL certificate problem: unable to get local issuer certificate

curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE); // false 禁止 cURL 验证对等证书(peer's certificate)

参考:https://stackoverflow.com/questions/24611640/curl-60-ssl-certificate-problem-unable-to-get-local-issuer-certificate

Empty reply from server

1、检查你的代理服务器是否正常。可能当前代理服务器无法正常访问
2、增加超时时间,每次请求接口时间略长一些就会产生这个错误

【PHP】curl_init() 如何排错????相关推荐

  1. Kubernetes 网络排错指南

    本文介绍各种常见的网络问题以及排错方法,包括 Pod 访问异常.Service 访问异常以及网络安全策略异常等. 说到 Kubernetes 的网络,其实无非就是以下三种情况之一 Pod 访问容器外部 ...

  2. php7 curl_init(),php7.3-curl_init获取301、302跳转后的数据

    最近在做一个蜘蛛项目,发现在抓取数据时,有时会碰到301的页面,原本写的curl_init函数php7-远程获取api接口或网页内容,直接无法抓取301跳转后的页面,因此对原本的函数进行了一下优化,现 ...

  3. DELL R710 服务器内存排错

    DELL R710 服务器内存排错 dmidecode - DMI table decoder 通过dmidecode可以得知,有点像windows下的资源管理器 man dmidecode 可以得到 ...

  4. 关于排错:专注思考,细心观察,步步为营

    时常有朋友发邮件给我,说遇到了一个什么什么奇怪的问题,不知道是怎么回事,希望我帮忙看看.我基本上每天都会抽出或长或短的时间来回复这些邮件,不过也经常发现,其实许许多多的问题都完全是有能力自行解决的.在 ...

  5. 空空排错日志:OCS错误日志14501等解决办法

    今天为一个客户排错,错误日志: OCS Protocol Stack 14501 当尝试建立 MTLS 对等计算机时,远程 IP 地址 192.168.85.247 提供了大量无效的证书.在过去的 5 ...

  6. centos7grub配置文件及排错

    rhel7 grub配置文件及排错 http://hongge.blog.51cto.com/ RHEL7用了grub2,而不再是grub了 MBR分区的前446个字节存放的是系统引导程序grub,中 ...

  7. 山石网科-Hillstone-IPsec V_P_N常见故障debug排错心得终结版

    嗨,各位好. 相信各位过来点开的时候会鄙视一句"这厮,又来搞山石了",哈哈没错,这次确实又来了,不过这次带了点排错的心得过来,希望给未来在常见的配置过程当中,不知道怎么排错时候有些 ...

  8. Windows Server 2012 R2 WSUS-11:经典的客户端排错操作

    在实际的WSUS运维中,可能会出现需要手动调整客户机或者服务器的情况,比如因为组策略的原因,或者刷新间隔未到,客户端(包括客户机和服务器)未收到更新,这个时候就需要我们在客户端上执行一些操作来定位问题 ...

  9. CentOS7系统启动、排错、修复、破解root口令

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://183530300.blog.51cto.com/894387/1854344 C ...

最新文章

  1. 《Xcode实战开发》——1.2节参与计划
  2. 如何区分SCSI卡和RAID卡?
  3. 【转】使用ssh-copy-id 快速的配置免密登录
  4. Go三种方式创建赋值map
  5. 树莓派dht11上云_树莓派使用 DHT11 / DHT22 温湿度传感器
  6. python3.6创建exe可执行程序
  7. Windows 配置Git 篇
  8. 递归函数非递归化_递归神秘化
  9. 【Java】访问控制
  10. java 多线程(生产者消费者)
  11. 阿里巴巴 程劭非(寒冬)- 《浅谈前端交互的基础设施的建设》
  12. python︱六款中文分词模块尝试:jieba、THULAC、SnowNLP、pynlpir、CoreNLP、pyLTP
  13. Lua代码加密 LuaJit代码加密
  14. 情人年-CGArt | 风格 银光版
  15. python如何调用pyd_C#调用pyd的方法
  16. 学习《西方哲学史》摘录
  17. 互联网晚报 | 9月10日 星期五 | 美团启动数字人民币低碳出行试点;vivo X70系列正式发布;旷视科技科创板IPO过会...
  18. keil v5 No Ulink2/Me Device Found 的解决方法
  19. 计算机网络打不开怎么办,电脑网页打不开怎么回事
  20. 一套打通 Github 搜索语法

热门文章

  1. 成功解决cv2.error: C:\projects\opencv-python\opencv\modules\imgproc\src\resize.cpp:4044: error: (-215) s
  2. DL之DNN:自定义MultiLayerNet【6*100+ReLU,SGD】对MNIST数据集训练进而比较【多个超参数组合最优化】性能
  3. RL之SARSA:利用强化学习之SARSA实现走迷宫—训练智能体走到迷宫(复杂陷阱迷宫)的宝藏位置
  4. 第三次作业-介绍一款原型设计工具
  5. error CS1061:
  6. Android 自定义实现switch开关按钮
  7. Binary Tree Level Order Traversal
  8. MySQL命令行下执行.sql脚本详解
  9. linux命令:ftp
  10. C++:构造函数2——拷贝构造函数