☰
PCDN刷量防护实战:基于JA3/JA4指纹的精准拦截策略
2026/10/7 10:33:13 网站建设 项目流程

做运维的兄弟如果被“广东IP视频分片刷量”折磨过,应该能体会那种感觉:封IP,第二天换一批;封UA,人家改个UA继续打;上WAF规则,攻击方直接换SDK版本。我前后和PCDN刷量流量对抗了大半年,中间试过很多方案,最后真正把问题压下去的,是从TLS指纹层引入JA3/JA4,把“按IP封、按UA封”这种被动思路,彻底换成了“按身份识别、按行为积分”的主动思路。这篇文章就把整个链路拆开讲清楚:为什么广东IP段的PCDN刷量这么难根除,JA3/JA4到底解决了什么问题,以及一套可以从零落地的精准防护方案。

这套内容适合正在被刷量流量困扰的运维、安全工程师,也适合带宽成本被异常抬高、想搞明白流量构成的技术负责人。文章里所有规则和配置都来自真实对抗场景,可以直接抄。

1. 先复盘一次典型的PCDN刷量攻击

1.1 刷量事件的现象与初步处置

先说一次让我印象特别深的处置过程。当时凌晨日志里突然出现大量视频分片请求,流量曲线一夜之间抬上去好几个档次,机房出口带宽直接爆掉。打开日志一看,特征非常明显:

  • 源IP高度集中在广东地区的几个运营商地址段,尤其是广电出口的NAT池;
  • User-Agent大量出现gdhg-cw5100、internet_r_vid这类看起来像设备固件或SDK生成的标识;
  • 请求路径全是视频分片文件,单个请求体积不大,但并发数和QPS高得离谱;
  • 几乎不带Referer,Cookie为空,完全不像正常用户的播放行为。

第一反应肯定是封IP。我当时的操作是:统计TOP源IP,按IP段拉黑,iptables一次性ban掉几百个地址。效果持续了大概十分钟,紧接着同一批地址段里又冒出新IP继续打。这是因为广电宽带是典型的DHCP+NAT架构,设备重拨一下地址就换,你根本封不完。后来我又把UA关键字加进WAF规则,结果对方SDK里UA字符串做了参数化,前脚封gdhg-cw5100,后脚就出来一个gdhg-cw5101,规则追着人家跑。

这种“封了又来、换汤不换药”的循环,本质上说明一件事:你用的判定维度,攻击者可以低成本伪造。IP会漂移,UA是明文,只有往下挖到TLS握手层,才有机会拿到一个改动成本足够高的身份标识。

1.2 PCDN流量劫持是怎么发生的

PCDN说白了就是P2P方式的CDN分发。正规玩法是用户安装客户端,贡献上行带宽,平台给奖励,大家双赢。但黑产的路子完全不一样。他们会把PCDN的SDK塞进运营商的机顶盒、光猫、路由器固件里,或者通过固件升级流程静默植入。用户根本感知不到,家里的设备就变成了一个“肉鸡节点”。

这些节点平时表现得很正常,但只要后台下发指令,它就会向内容源站发起大量的视频分片请求。请求来的内容一部分被本地缓存复用,一部分被用来构造虚假的“上行贡献量”,从而骗过PCDN调度平台,套取流量结算收益。源站视角看到的,就是某个区域运营商出口IP持续刷量,请求特征和正常用户交错在一起,带宽成本蹭蹭往上涨。

关键点在“劫持”两个字。这些流量不是用户主动产生的,是设备在后台偷偷跑的。所以你在日志里看不到用户的登录态、没有业务Token、没有Cookie,因为SDK根本不需要这些。它要的就是在最底层把内容拉起来、把流量指标做上去。

明白了这个机制,再看封IP为什么失效就清楚了:攻击源不是一个固定服务器,而是几万个分布在各家各户的联网设备;出口IP是运营商NAT池动态分配的,今天是这个、明天是那个;UA和请求路径都是SDK可控的字符串,改起来毫无成本。

1.3 广东广电IP段为何成为“重灾区”

很多人问我为什么偏偏是广东IP、偏偏是广电段。我不是广东广电的内部人士,但从实际流量特征和行业公开信息来看,原因是结构性的。

第一,设备基数大。广东广电体系下机顶盒、光猫的存量非常大,而且很多设备是运营商统一定制、统一派发的。厂家在固件里做了什么、SDK里集成了哪些模块,普通用户完全没有感知,也不会去检查。基数一大,被植入PCDN节点的绝对数量自然就上来了。

第二,网络结构特殊。广电宽带大量使用运营商级NAT,出口地址池相对集中但IP和用户不是一一绑定关系。日志里看到同一个IP背后可能挂了几百个真实家庭用户。你要封这个IP,极大概率把正常用户也误伤进去。

第三,请求特征固定。很多被植入的终端上报UA时会带上设备型号和SDK标识,比如gdhg-cw5100这种来自特定光猫/网关型号的标识,以及internet_r_vid这类视频SDK相关的UA前缀。虽然可以伪造,但对于已经大规模铺开的老旧设备来说,固件不会频繁升级,UA和TLS指纹在很长时间内都保持稳定——这在后面反而成了我们识别它的突破口。

第四,单点流量小但总量惊人。每个家庭设备的带宽占用其实不大,可能就是几百Kbps到几Mbps,但几千台设备同时跑,汇聚到源站就是持续的洪峰。单IP看到的值不高,很容易被监控系统的阈值漏过去,但整体带宽曲线会慢慢爬升,直到你某天收到账单才意识到问题。

2. 为什么传统封禁策略总是治标不治本

2.1 IP封禁与UA封禁的脆弱性

先说IP封禁。IP在这个场景里等于“门牌号”,而攻击设备的门牌号是动态的。动态IP+NAT出口带来的结果是:同一时刻同一个源IP可以承载真实用户和攻击流量;下一次攻击流量出现时源IP可能已经换了。基于IP做黑名单,注定是打地鼠游戏。

再说UA封禁。UA是HTTP明文头,攻击SDK生成UA的成本低到可以忽略。你封gdhg-cw5100,SDK下次带上GDHG-CW5100或者后面加个空格、加个版本号,规则就失效了。UA只能作为辅助信号,不能作为独立判定依据。

还有一类人喜欢用限速或封禁特定Range分段请求。这个有一定效果,但同样绕得开。SDK可以调整请求策略,把分段改成整段拉取,把并发降下来伪装成慢速观看。你每加一条规则,对方就调整一次参数,运维永远在追赶。

真正稳固的判定维度,必须满足两个条件:一是藏在协议底层、普通请求里难以篡改;二是改动成本高到攻击方不愿意为你单独修改。TLS握手层的指纹恰好满足这两点。

2.2 从TLS握手层寻找“可信身份”

TLS握手是整个HTTPS请求的第一环。客户端在发起ClientHello时会带上自己支持的TLS版本、密码套件列表、扩展列表、椭圆曲线、格式等参数。这些参数不是随便填的,而是由客户端的TLS实现库在编译期和运行期共同决定的。浏览器有浏览器的组合,Go语言写的SDK有Go的那一套,OpenSSL和BoringSSL又自成体系。

JA3就是把这些握手参数按照固定顺序拼接成字符串,再做一次MD5哈希,得到一个32位的十六进制指纹。这个指纹相当于TLS客户端的“DNA”。正常情况下,同一个SDK的各个终端算出来的JA3几乎一样;而正规浏览器的JA3和PCDN SDK的JA3,差异非常明显。

我在实际抓包里见过一个典型的PCDN节点:它基于某款Go语言SDK封装,ClientHello里的密码套件顺序、扩展类型和浏览器完全不一样。同一个IP上,用Chrome打开的网页和后台PCDN流量各自握手的JA3完全不同。这给了我们一个很干净的切分维度:同一个来源IP上,用户可以放行,但特定指纹必须拦截。

打个比方:IP是门牌号,UA是着装,JA3是声音。门牌号会换,衣服可以改,但声音特征短时间内很难伪装。

2.3 JA3与JA4的差异和演进

JA3虽然好用,但有明显短板:它把所有字段拼在一起做MD5,字段间没有结构化区分,一旦某个扩展顺序变化,整个哈希就全变,容易误伤;而且它只覆盖ClientHello,对服务端响应、HTTP层行为没有刻画。

JA4是后来提出的新一代TLS指纹标准,用四个字段分别描述TLS版本、SNI、密码套件数量、扩展数量、ALPN、指纹分片等信息。典型格式类似:

t13d1516h2_8daaf6152771_02713d6d1a1f_0

拆开看:第一段表示TLS 1.3、DH模式、1516字节ClientHello等概要信息;第二段是密码套件的有序指纹分片;第三段是扩展指纹;最后一段表示没有ALPN等额外信息。JA4还衍生出了JA4S(服务端指纹)、JA4H(HTTP请求头部指纹)、JA4L(TCP流量时序指纹),覆盖了整个会话链路。

放到PCDN防护场景里,JA4的价值在于:即使SDK做了一点参数调整导致JA3变化,JA4的结构化信息依然能帮你快速判断“这个流量是什么类型的客户端发出来的”;再配合JA4H看HTTP层的Range、UA、Content-Type组合,识别率会更高。我在规则里同时保留JA3和JA4两条路,JA3做粗过滤,JA4做细判定,实测误报率比单纯用JA3低不少。

3. 精准防护方案:从采集到联动的完整落地

3.1 采集层:把JA3/JA4指纹变成日志字段

第一步是要能让边缘网关输出TLS指纹。方案有三个,大家按自己环境选。

方案A:Nginx + nginx-ssl-ja3模块。这个模块需要把Nginx和BoringSSL配合编译,编译参数大致如下:

./configure \ --with-compat \ --add-dynamic-module=../nginx-ssl-ja3 \ --with-http_ssl_module make && make install

装好之后在server块里开启变量,并打到access_log里:

server { listen 443 ssl; ssl_ja3 on; log_format ja3log '$remote_addr|$ssl_ja3|$http_user_agent|$request_uri'; access_log /var/log/nginx/ja3.log ja3log; }

这样每条请求日志里都会带上$ssl_ja3,后续用ELK或ClickHouse做聚合非常方便。

方案B:APISIX/Kong等API网关。Kong有ja3插件,APISIX也可以通过自定义插件在ssl阶段做指纹提取。如果你的业务已经走在网关上,这是改动最小的路径,不需要动Nginx源码。

方案C:流量镜像分析。把核心边缘节点的TLS握手流量镜像一份到抓包服务器,用离线分析工具解析ClientHello并算指纹。这个方案适合第一阶段排查,因为实时性差,但胜在不用改生产环境,能先摸清楚攻击指纹长什么样。

我个人实际用的是“Nginx补丁+日志采集”的组合。第一周先离线抓包,把攻击流量里的JA3/JA4样本洗出来;确认特征之后,再给生产Nginx打上模块,让指纹字段进入实时日志链路。

3.2 规则层:多维联合判定模型

有指纹之后不要急着封禁。直接按指纹封死,误伤面太大,尤其广电NAT出口后面还挂着真实用户。我采用的是“安全积分”模型,把多维信号折算成分数,分数触发不同动作。

维度命中条件分值
TLS指纹JA3命中已知PCDN指纹库+30
UA特征命中gdhg-cw5100、internet_r_vid+10
IP地域源IP归属于广东广电NAT特征段+20
请求行为单IP QPS>100且无Referer+15
请求路径连续Range分片视频请求+10

规则引擎逻辑:

  • 总分小于50:正常放行,只记录日志;
  • 50到70:进入“观察区”,响应头加自定义标记,限速;
  • 70到90:进入“挑战区”,302跳转一次性token校验页;
  • 大于90:直接返回403,并在缓存里对该“指纹+区域”组合执行数小时封禁。

这套模型的关键是:单看任何一条都不致命。IP来自广东不是罪,UA长得怪也不是罪,但“IP特征+UA特征+TLS指纹+高频行为”同时命中,基本可以确定是PCDN刷量。

挑战机制要单独说一下。PCDN的SDK是嵌入式终端,它不具备执行JavaScript的能力。你给它一个302跳转到校验页,正常浏览器会跟着跳、执行JS、拿Token、回源继续播放;而SDK拿到302之后要么原地丢弃、要么直接重试原地址,永远不会完成校验。这一个动作就能把真实用户和攻击流量区分开,比单纯封禁优雅得多。

3.3 执行层:观察、挑战、封禁三级处置

执行层要解决“怎么拦”的问题。很多人一上来就封IP段,这是最粗暴也最容易误伤的做法。我的建议是按“日志→挑战→封禁”三级递进。

第一级,观察限速。对命中50到70分的流量,直接给源站带宽加一层限速,例如Nginx配:

limit_req_zone $binary_remote_addr zone=flood:10m rate=5r/s; server { location /video/ { limit_req zone=flood burst=20 nodelay; proxy_pass http://upstream_video; } }

5r/s对真实用户来说完全够用,但对PCDN节点的每秒几十个分片请求来说,等于断粮。限速的好处是不会产生“用户刷不出来”的投诉,只是变慢。

第二级,挑战校验。70到90分的流量强制302到校验页。校验页种下短期Token,回源请求带上Token才放行。这一步能过滤掉绝大多数不具备浏览器能力的SDK流量。

第三级,指纹封禁。90分以上的流量,按“JA3/JA4+IP地域”二元组封禁,而不是只封IP。比如某个广东广电IP段在换IP,但JA3始终不变,那就把该IP段的这个JA3封掉,后面的真实用户不受影响;如果同一IP上出现了两个指纹,一个浏览器、一个PCDN SDK,那浏览器继续放行,SDK指纹照封不误。

这套三级处置的节奏很重要。不要第一天就把所有规则调到最严,先观察记录一周,把误伤数据拉出来看看,再逐步收紧。攻击方会试探你的底线,你的规则也要有灰度发布的过程。

4. 实战问题排查与长期治理

4.1 误伤真实用户:这是所有封禁策略绕不开的坑

我踩过的最大一个坑,是用IP段直接封禁,导致广电宽带下一整片真实用户播放异常。当时客服反馈量立刻上来了,社区里开始有人骂平台“看视频卡成PPT”。

后来排查发现,问题出在NAT上。同一个出口IP背后有大量真实家庭用户,他们有的人在用PC浏览器看视频(指纹是Chrome系),有的人在用手机App(指纹是Android WebView系),还有人家里被植入了PCDN节点(指纹是SDK系)。三种流量共用同一个IP。

调整策略之后我做了三件事:

  • 封禁对象从“IP”改成“IP+指纹”二元组;
  • 对带业务Cookie或登录态的请求直接跳过挑战;
  • 通过验证的用户种一个12小时有效的放行Cookie。

这三招下去,客服投诉基本清零,攻击流量依然被挡在外面。核心思路就一句话:真实用户有业务特征,攻击流量没有;把有业务特征的放行,剩下的才进入严格判定。

4.2 指纹随机化对抗:规则库要“养”

很多人会问,攻击方把SDK升级一下,TLS指纹不就变了吗?理论上确实可以,但实际对抗中,PCDN黑产有一个天然弱点:SDK已经烧录在几十万台终端里,终端固件的升级周期非常慢,短期内让所有终端同步更换TLS栈根本不现实。

不过这不代表可以躺平。我发现过攻击方尝试用curl-impersonate这类工具模拟浏览器指纹,把JA3改成Chrome的样子。对这种变异流量,单靠静态指纹库会失效。我的应对是加一个“新指纹聚类”流程:每周把上一周的日志跑一遍聚类,按“相似UA+相似IP地域+相似分片行为”归并出新指纹,人工确认后入库。攻击方每变异一次,我们最多滞后几天就能补上规则。

还有一个经验:不要在UA层面和对方纠缠。UA是他们最方便改的字段,改了毫无成本;TLS指纹是他们最不方便改的字段,改了需要重新拆包。精力永远要投在对方改动成本高的环节上。

4.3 排查命令与工具速查

诊断一个流量是不是PCDN刷量,最快的路径是抓包看TLS握手。下面这条命令把443端口的握手流量抓下来:

tcpdump -i eth0 -f "tcp dst port 443" -w pcdn.pcap

抓到包后用Python脚本解析ClientHello并计算JA3。完整实现大概200行,核心思路是解析TLS Record层,提取ClientHello里的版本号、密码套件、扩展类型、椭圆曲线和点格式,拼成固定格式字符串再做MD5。示意代码如下:

import hashlib from scapy.all import rdpcap, TCP, Raw def calc_ja3(pcap_file): packets = rdpcap(pcap_file) for pkt in packets: if TCP in pkt and Raw in pkt: data = pkt[Raw].load # 这里需要按TLS ClientHello结构逐字段解析 # ssl_version, ciphers, extensions, curves, point_formats # 拼接规则: # ja3_string = "{},{},{},{},{}".format(...) # ja3 = hashlib.md5(ja3_string.encode()).hexdigest() pass

不想自己写的话,有两个现成工具很好用:一个是ja3的Python库,能直接读取pcap输出JA3指纹;另一个是tshark,一条命令就能看:

tshark -r pcdn.pcap -Y "ssl.handshake.type==1" -T fields \ -e tcp.stream -e ja3.hash -e ja3.string

生产环境的实时排查则直接聚合Nginx日志。我习惯用awk快速看Top指纹:

awk -F'|' '{print $2}' /var/log/nginx/ja3.log | sort | uniq -c | sort -rn | head -20

把Top指纹和UA字段放一起看,基本一眼就能判断出哪些是SDK流量。

4.4 从应急封禁走向常态化运营

把火扑灭只是第一步,长期治理需要把规则变成一套持续运营的体系。我现在维护的仪表盘包括四个核心指标:命中指纹库的请求数趋势、UA特征分布、地域命中分布、带宽占比。任何一项出现异常抬升,先看是不是新指纹变异。

告警阈值设在“某个指纹的请求量环比上涨100%”,触发后自动把新增指纹加入观察区,人工确认再转封禁。每周做一次新指纹聚类,每月复盘一次误伤率。误伤率大于0.1%就要回退规则,因为真实用户体验永远排在第一位。

跟设备侧的协同也很重要。通过UA里的设备型号,比如gdhg-cw5100,可以反查这批设备的固件版本和出厂批次,再推动设备方排查固件里是否有异常模块。这个环节需要耐心,效果也不是立竿见影,但一旦下掉一批问题固件,刷量基数会真正减少,比单纯堵流量管用得多。

我在实际对抗里最大的体会是:PCDN刷量不是一场能“打赢”的仗,而是一场需要持续投入的“管理”工作。IP封禁是灭火,JA3/JA4是建防火墙,而规则的持续迭代才是让防火墙长期有效的关键。最后分享一个小技巧:所有封禁规则上线前,先用历史流量回放一遍,算清楚误伤率再上生产,这一步每次都能帮我避开大坑。后续我打算单独写一篇关于新指纹自动聚类的实现细节,如果大家也在被这类问题困扰,欢迎交流各自的对抗经验。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询