资讯动态

PHP实现微信域名拦截检测:原理、代码与避坑指南

发布时间:2026/10/8 3:48:40 来源:尧图企业网站定制
做微信推广域名的人肯定遇到过这种情况好好的落地页发到群里自己点得欢客户一点却弹出“已停止访问该网页”。更头疼的是域名什么时候被拦的、为什么被拦、现在恢复没有全靠肉眼去看。微信域名检测、域名安全检测、域名拦截检测这些词反复被搜就是因为大家需要一套能自动化判断域名在微信内是否可访问的办法。我之前做了个小工具原理并不复杂但真正落地踩了不少坑这里把完整思路和可复用的代码都摊开讲清楚适合有推广需求的技术运营、独立开发者也适合第一次接触域名检测的朋友参考。1. 微信域名拦截检测的基本原理1.1 微信拦截机制到底是怎么运作的微信内部的域名拦截体系本质上是一套风控系统。当用户通过微信内置浏览器X5内核或系统内核访问某个URL时客户端会先向微信的安全检测服务发起请求查询这个域名当前的风控状态。如果域名被命中恶意、诱导分享、欺诈等规则微信不会直接拒绝连接而是返回一个拦截提示页常见文案就是“已停止访问该网页”。这套机制有几个特点。第一拦截粒度通常是域名级别也可能是具体路径所以同域名下的不同页面状态可能不一样。第二拦截不是永久的申诉后能恢复但恢复周期不固定。第三微信会结合访问环境做动态判断比如设备特征、IP信誉、访问频率单次请求被拦不代表所有用户都会被拦但是多数情况下被拦状态会扩散。理解这些对设计检测脚本非常重要因为我们要检测的就是“模拟真实微信环境访问时返回的响应是否符合拦截特征”。1.2 检测方案的核心设计思路既然拦截是发生在微信浏览器环境内的那就最好模拟真实的微信浏览器去请求目标URL。普通的curl或浏览器直接访问微信服务器往往放行因为那些请求没有带微信客户端特征。所以关键点在于构造一个完整的、安全的微信浏览器UAUser-Agent。这里有朋友会问是不是只要UA带上微信用关键词就行我踩过坑远没那么简单。微信的检测不仅看UA还会看一些浏览器环境变量比如Referer、Cookie以及请求头中的某些特殊标记。不过对于基础域名检测来说一个有效的微信UA配合正确的请求头已经能触发绝大多数拦截判定。原理就是微信安全服务器根据UA判定请求方是微信内置浏览器于是套用微信环境下的风控策略返回对应的拦截页或是正常页面。我们要做的就是把服务器返回内容拿回来分析用关键词匹配来判断当前状态。2. 快速上手PHP实现微信域名检测脚本2.1 环境准备与工具选型我用的PHP 7.4只要PHP装了curl扩展就行。大部分服务器默认都有可以用php -m | grep curl确认。你的PHP不会没关系逻辑是通用的会点别的语言一样能写。之所以选PHP纯粹是部署方便一台普通Cloud VM就能跑不依赖Node或Python运行时。需要准备的工具很朴素一台能访问外网的服务器最好国内机房因为微信安全策略对海外IP可能有差异化表现PHP环境7.0以上即可一个待检测的域名列表放在txt里一行一个如果你不想要服务器本地跑也行只要有外网。但我要提醒一句本地家庭宽带IP如果被多人使用或信誉不高检测结果可能不准尤其高峰期容易出现误报。所以正式监测建议用干净的云主机IP。2.2 核心检测函数实现先写一个最核心的检测函数用curl模拟微信浏览器的完整请求?php /** * 检测域名在微信环境下的访问状态 * param string $url 完整URL如 https://example.com/landing * return array 检测结果 */ function checkWechatDomain($url) { $wechatUA Mozilla/5.0 (Linux; Android 10; SM-G9810 Build/QP1A.190711.020; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.108 Mobile Safari/537.36 MicroMessenger/7.0.20.1780(0x28001453) NetType/WIFI Language/zh_CN; $ch curl_init(); curl_setopt_array($ch, [ CURLOPT_URL $url, CURLOPT_RETURNTRANSFER true, CURLOPT_FOLLOWLOCATION true, CURLOPT_MAXREDIRS 5, CURLOPT_TIMEOUT 15, CURLOPT_SSL_VERIFYPEER false, CURLOPT_SSL_VERIFYHOST false, CURLOPT_USERAGENT $wechatUA, CURLOPT_HTTPHEADER [ Accept: text/html,application/xhtmlxml,application/xml;q0.9,image/webp,image/apng,*/*;q0.8, Accept-Language: zh-CN,zh;q0.9,en;q0.8, Cache-Control: no-cache, Pragma: no-cache, Upgrade-Insecure-Requests: 1, ], ]); $body curl_exec($ch); $statusCode curl_getinfo($ch, CURLINFO_HTTP_CODE); $error curl_error($ch); curl_close($ch); if ($error) { return [ url $url, status error, message $error, ]; } return [ url $url, status_code $statusCode, body $body, status unknown, ]; }注意这里我把FOLLOWLOCATION开了因为微信拦截页可能通过302跳转返回跟随跳转可以拿到最终内容。SSL验证关掉是为了减少证书链问题但对精度要求高的用户建议开启证书验证避免被中间人干扰。2.3 拦截判定规则与阈值拿到响应体之后还是要靠关键词判断。微信安全提示页的文案相对固定常见的有这么几类“已停止访问该网页”“网页含有诱导分享、诱导关注等行为”“被多人投诉为保护绿色网络环境已停止访问”“包含垃圾广告内容”“网页包含恶意程序”我把这些关键词做成一个数组匹配到了就算拦截。同时要兼顾正常情况如果返回了页面标题、正文中包含目标页面的特征词或者响应体不是安全提示页模板就判定为正常。如果只返回状态码200但响应体是空或者是一段JS跳转需要特别处理。可能目标站本身是SPA也可能是微信返回了一个临时空页这时候建议再发一次请求增加一个Referer头用于模拟从好友会话进入。完善后的判定函数function judgeIntercepted($body, $url) { $interceptKeywords [已停止访问, 诱导分享, 被多人投诉, 垃圾广告, 恶意程序]; foreach ($interceptKeywords as $keyword) { if (strpos($body, $keyword) ! false) { return intercepted; } } // 如果页面存在明显的站内特征如title标签或url关键字认为是正常页面 if (strpos($body, html) ! false || strpos($body, title) ! false || strpos($body, window.location) ! false) { return normal; } return suspicious; }这里为什么不是直接strpos用! false就完事因为strpos如果匹配到第0位会返回00 false是真必须用全等判断。这是新手最容易犯的错误我直接把完整写法放上来别再踩了。2.4 主流程与结果输出主流程很简单读取域名列表循环检测写入日志。不过这里有个细节一次别检测太多每个请求间隔至少1秒否则容易触发微信或目标站的频率限制。个人实测单个IP连续检测50个不同域名容易让部分目标站返回验证码到时候结果就失真了。下面是我一个简单可跑的版本$listFile domains.txt; $resultFile result.csv; $domains file($listFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); $handle fopen($resultFile, w); fputcsv($handle, [域名, 状态, 状态码, 响应长度, 时间]); foreach ($domains as $domain) { $domain trim($domain); if (stripos($domain, http) ! 0) { $domain https:// . $domain; } $resp checkWechatDomain($domain); $status $resp[status] ?? error; if ($status unknown isset($resp[body])) { $status judgeIntercepted($resp[body], $domain); } fputcsv($handle, [ $domain, $status, $resp[status_code] ?? , isset($resp[body]) ? strlen($resp[body]) : 0, date(Y-m-d H:i:s) ]); echo [{$domain}] {$status}\n; sleep(1); // 避免请求过快 } fclose($handle); echo 检测完成结果已写入 {$resultFile}\n;这个脚本适合一次性检测几十个域名。如果要长期监控建议把结果放到数据库或者钉钉机器人推送但基础原理就是上面这套。3. 高级玩法批量检测与API化3.1 批量检测的任务队列设计一次性检测成千上万个域名时直接循环加sleep效率太低。我的做法是引入Redis队列或者简单的多进程。如果不想引入Redis直接用PHPpcntl_fork做多进程但要处理好子进程的互斥。设计逻辑将域名列表压入Redis队列启动N个worker进程每个进程不断从队列取一条域名检测结果写入MySQL或MongoDB设定任务结束条件队列为空且没有进行中的任务我自己实测过4核服务器起4个进程检测1000个域名大约耗时5分钟比单线程快了4倍。注意尽量不要超过10个并发因为微信安全服务也有接口限流并发太猛容易把IP风控掉后面检测全部误报。多进程版核心代码片段只展示fork部分思路$processCount 4; $pidArray []; for ($i 0; $i $processCount; $i) { $pid pcntl_fork(); if ($pid -1) { die(fork失败); } elseif ($pid) { $pidArray[] $pid; } else { // 子进程从队列获取并检测 while ($url $redis-lpop(domain_queue)) { $resp checkWechatDomain($url); // 处理结果... usleep(200000); // 0.2秒 } exit(0); } } foreach ($pidArray as $pid) { pcntl_waitpid($pid, $status); }如果你服务器上没有pcntl扩展也可以用curl_multi实现并发请求那是另一种玩法但判断逻辑更复杂看你顺手。3.2 封装成API接口给业务系统调用很多业务场景不只是检测一次而是推广链接每次都实时检测这时候最好写一个简单的HTTP接口。我用PHP内置的JSON输出接口地址比如api.php?urlhttps://xxx.com/page。接口返回统一结构{ code: 0, message: success, data: { url: https://xxx.com/page, status: normal, status_code: 200, check_time: 2025-01-01 12:00:00 } }实现时注意几个要点限制访问频率同一个IP每秒钟最多调用5次防止别人拿你的接口乱测只允许检测自己业务的白名单域名避免被恶意利用去探测别人的域名开启缓存同一个域名5分钟内不重复检测直接返回上次结果// 简单示例 $url $_GET[url] ?? ; if (!preg_match(/^https?:\/\/[a-z0-9.-]/i, $url)) { exit(json_encode([code 1, message URL格式不正确])); } $cacheKey wx_check_ . md5($url); $cache $redis-get($cacheKey); if ($cache) { exit($cache); } $result checkWechatDomain($url); if ($result[status] unknown) { $result[status] judgeIntercepted($result[body] ?? , $url); } // 清理过期key和不需要的字段 $data array_intersect_key($result, array_flip([url, status, status_code])); $data[check_time] date(Y-m-d H:i:s); $response json_encode([code 0, message success, data $data]); $redis-setex($cacheKey, 300, $response); echo $response;通过API化域名检测就能无缝接入你的推广监控面板或者告警系统省去人工点开链接检查的重复劳动。3.3 配合定时任务监控域名状态变化域名被拦截后的恢复时间很不固定短则几小时长则几天。我的建议是每10分钟跑一次检测把状态连续变化记录下来。这样你能看到“某天几点几分被拦”、“持续了多长时间”对于运营团队复盘非常有用。定时任务我一般写一个shell脚本#!/bin/bash cd /path/to/project /usr/bin/php check.php /var/log/domain_monitor.log 21然后加到crontab*/10 * * * * /bin/bash /path/to/project/run_check.sh日志按天记录一个月清理一次。如果发现状态从normal变为intercepted马上通过webhook推到钉钉群。推送代码简单就是curl一个钉钉自定义机器人地址这里不展开了。总之定时监控这个流程能把“不知道什么时候挂”变成“挂了立刻知道”这是检测系统的核心价值之一。4. 坑与经验常见问题与避坑指南4.1 为什么检测结果总是误判正常这是我在评论区被问最多的问题。明明域名已经被微信拦截了但脚本检测出来的却是normal。排查下来大概率是以下原因。第一你用的UA太老。微信UA版本要定期更新老UA可能已经不在风控识别范围内。建议每隔三个月去网上搜一下最新的微信UA替换进脚本。第二请求头不全。微信内置浏览器还会带上X-Requested-With: com.tencent.mm这个特征头。有些拦截策略会校验这一点只带UA不带这个头就会当成普通浏览器。我在代码里补充一个头X-Requested-With com.tencent.mm,加这个头可以显著提高拦截命中率但注意部分PC微信UA不适合加识别环境要精准。第三目标域名有跳转。比如你的落地页本身302到另一个域名虽然原域名没被拦但跳转后的域名被拦微信最终也会弹拦截页。所以检测时一定要开启跟随跳转并且判断的是最终URL的内容。我的代码已经用FOLLOWLOCATION实现了但如果你自己写要记得。第四IP被污染。使用被标记过的IP发起请求微信可能直接放行导致检测不到真实状态。解决方法是换干净的IP最好是住宅IP机房IP本身容易在风控评分中被降低权重。4.2 检测结果显示suspicious该怎么办suspicious表示响应体既没有明确的拦截关键词也没有常规页面特征。常见于三种情况目标站返回了一个验证码页面目标站太慢没能加载出内容微信返回了一个空白的安全确认框需要用户手动点击“继续访问”每一次请求结果有浮动是正常的。我的处理方法是如果第一次是suspicious隔3秒再检测一次连续3次都是同样结果才判定为可疑。如果连续3次中至少一次是normal就判定为normal。这个“三次加权”策略能过滤掉大多数瞬时网络抖动带来的误差。另外suspicious不等于被拦截千万别直接告警否则运营那边会被假警报折腾疯。我在真实环境里统计过suspicious中大约只有30%会在后续重新检测时变成intercepted其余大部分是网络问题或动态页面渲染导致。4.3 关于频率限制和封禁风险检测频率不是越高越好。你拿着一个IP每秒请求几十次目标站可能拉黑你微信安全系统也可能临时给你这个IP打折之后测什么都显示正常等于白测。稳妥的频率是每个域名间隔1秒一个IP每秒不超过5个请求。如果是多进程批量检测总并发控制在10以内。还有不要用同一个IP去检测大量低质量的域名。如果某个域名因为传播垃圾信息被标记你用同一IP频繁测它万一发生关联自己IP信誉会受影响。正规用法是只检测自己的域名借用检测接口给第三方也要限制他们的行为。我这里给一个参考频率表检测场景最大并发单域名间隔说明手动单条检测10.3秒用户直接点按钮触发定时监控100个域名内21秒每10分钟跑一轮批量检测千级别5-80.5秒多进程队列批量检测万级别10以内0.2秒配合代理池更稳再补充一点微信检测只能是“辅助工具”不能保证100%和用户实际看到的一致。因为用户端的微信版本、系统内核、当前网络环境、账号是否异常等因素都会影响最终展示。所以当你检测到被拦截后最快的确认方式仍然是拿一个正常手机微信发给小号实际点一次看看。4.4 合规使用与业务心态写这类工具的初衷是监测自家域名状态及时发现异常而不是帮人研究如何绕过微信规则。微信平台的规则对每个人都是公开的域名被拦截通常是因为内容违规或用户投诉正确的路径是清理违规内容、提交申诉。做域名检测工具时也尽量不要提供所谓的“防红”跳转代码这类东西既无效又有合规风险。真正健康的使用场景是作为运营人员手里的一个巡检工具。比如我接手某个推广项目时第一件事就是把历史所有域名扫描一遍把哪些早就被拦截的、还在给用户推的域名全部标记出来通知业务方替换或整改。这一套流程帮我避免了无数个“用户点进来看到封禁页”的尴尬。还有一点检测结果属于业务数据不要保存在公共平台或公开仓库里。我见过有人把域名检测结果传GitHub真是没必要。毕竟域名和拦截状态意味着你的推广渠道信息低调一点对业务没坏处。最后再给点实用的建议如果你只想做最简单的复现复制第一节到第二节的PHP代码就能跑。但如果你跟我一样要长期依赖它建议往工程化方向打磨支持多域名异步检测保留历史记录写个小前端展示趋势。我另外发现一个细节微信UA会随版本迭代我的脚本里维护着一个UA库每个UA对应不同的微信版本检测时可以随机抽取一个这样更贴近真实用户分布而不是所有请求固定一个UA。实测下来随机UA比固定UA的检测准确率高几个百分点而且不容易触发频率限制。平时我还会用这个工具去做竞品域名观察——当然只观察他们公开的落地页状态不调用任何非公开接口也不搞任何黑产操作。本质上只需要一个php文件没有任何技术门槛但你把它当成一个严肃的监控系统对待它回报你的就是实打实的安全感。以后你的朋友遇到域名被封你可以甩给他这段代码说“先自己测测别急。”

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑