
大白话解释---黑产是什么 薅羊毛的、爬数据的、暴力破解密码的、扫描接口找漏洞的统称黑产。特征是行为和正常用户不一样。---四道拦截 第一道IP黑名单 已知的坏IP直接封不用判断秒拒。来源可以是安全情报、之前被封过的记录。 第二道临时封禁 之前触发过频率限制被封的IP封禁时间没到继续拒绝告诉它还要等多少秒。 第三道UA检测 正常浏览器的UA长这样Mozilla/5.0(WindowsNT10.0...)Chrome/...爬虫/脚本的UA长这样python-requests/2.28、Go-http-client/1.1没有UA或包含这些关键词直接拦。 第四道行为检测扫描识别 正常用户1分钟内就访问那几个页面不会乱跑。 黑产扫描接口时会在1分钟内打几十上百个不同URL找有没有未授权接口、敏感路径。 代码里把路径数字替换掉再比较/user/1和/user/2算同一种不然换个ID就绕过了。1分钟内超过20种不同路径判定扫描封10分钟。---封禁时间设计-频率超限封5分钟可能是误触给机会-扫描行为封10分钟主动探测更严---跑起来 php8.4/mnt/d/antifraud/antifraud.php 测试UA拦截 curl-Apython-requests/2.28http://localhost:9900/测试无UA拦截 curl--user-agenthttp://localhost:9900/?php/** * 防刷与黑产拦截系统 * * 大白话 * 黑产特征同一IP高频请求、UA是爬虫、没有正常浏览器行为、 * 短时间内打了很多不同接口扫描行为 * * 四道拦截 * 1. IP黑名单 → 直接封掉的IP秒拒 * 2. 频率检测 → 1秒内请求太多临时封禁 * 3. UA检测 → 明显的爬虫/脚本特征 * 4. 行为检测 → 短时间内访问接口种类太多在扫描 * * 运行 * php8.4 antifraud.php */useSwoole\Http\Server;useSwoole\Http\Request;useSwoole\Http\Response;useSwoole\Coroutine\Http\Client;useSwoole\Table;// 永久黑名单从数据库/配置加载这里写死示例constIP_BLACKLIST[1.2.3.4,5.6.7.8];// 可疑UA关键词包含这些的直接拦constBAD_UA_KEYWORDS[python-requests,go-http-client,java/,curl/,scrapy,httpclient,okhttp,libwww,wget,];// 后端服务constBACKEND_HOST127.0.0.1;constBACKEND_PORT8080;// ── 共享内存表 ────────────────────────────────────────────────// 频率表IP → {当前窗口请求数, 窗口到期时间, 封禁到期时间}$rateTablenewTable(65536);$rateTable-column(count,Table::TYPE_INT,4);$rateTable-column(reset_at,Table::TYPE_INT,4);$rateTable-column(banned_until,Table::TYPE_INT,4);$rateTable-create();// 行为表IP → {本分钟访问的接口指纹集合, 窗口到期时间}// 用逗号拼接的md5列表模拟集合$behaviorTablenewTable(65536);$behaviorTable-column(paths,Table::TYPE_STRING,1024);$behaviorTable-column(reset_at,Table::TYPE_INT,4);$behaviorTable-create();$servernewServer(0.0.0.0,9900);$server-set([worker_numswoole_cpu_num(),enable_coroutinetrue,]);$server-on(request,function(Request$req,Response$res)use($rateTable,$behaviorTable){$ip$req-server[remote_addr];$ua$req-header[user-agent]??;$path$req-server[request_uri];$nowtime();// ── 1. IP 永久黑名单 ──────────────────────────────────────if(in_array($ip,IP_BLACKLIST,true)){block($res,403,ip_blacklist);return;}// ── 2. IP 临时封禁之前触发频率限制被封的─────────────$rate$rateTable-get($ip);if($rate$rate[banned_until]$now){$res-header(Retry-After,(string)($rate[banned_until]-$now));block($res,429,temp_banned);return;}// ── 3. UA 检测 ────────────────────────────────────────────// 没有UA或UA包含爬虫关键词if($ua){block($res,403,no_ua);return;}$uaLowerstrtolower($ua);foreach(BAD_UA_KEYWORDSas$kw){if(str_contains($uaLower,$kw)){block($res,403,bad_ua);return;}}// ── 4. 频率检测每IP每秒超60次 → 封禁5分钟 ─────────────if($rate$rate[reset_at]$now){if($rate[count]60){// 触发封禁$rateTable-set($ip,[count0,reset_at$now1,banned_until$now300,// 封5分钟]);block($res,429,rate_limit);return;}$rateTable-incr($ip,count);}else{$rateTable-set($ip,[count1,reset_at$now1,banned_until0]);}// ── 5. 行为检测1分钟内访问超过20种不同路径 → 扫描行为 ──// 黑产扫描接口时会在短时间内打大量不同URL$pathKeymd5(preg_replace(/\d/,{id},$path));// 把数字替换掉/user/1和/user/2算同一种$brow$behaviorTable-get($ip);if($brow$brow[reset_at]$now){$seenarray_filter(explode(,,$brow[paths]));if(!in_array($pathKey,$seen,true)){if(count($seen)20){// 1分钟内访问了20种不同接口判定为扫描$rateTable-set($ip,[count0,reset_at$now1,banned_until$now600,// 封10分钟]);block($res,403,scan_detected);return;}$seen[]$pathKey;$behaviorTable-set($ip,[pathsimplode(,,$seen),reset_at$brow[reset_at]]);}}else{$behaviorTable-set($ip,[paths$pathKey,reset_at$now60]);}// ── 全部通过转发请求 ────────────────────────────────────$cnewClient(BACKEND_HOST,BACKEND_PORT);$c-set([timeout10]);$c-setHeaders($req-header??[]);$c-setMethod($req-server[request_method]);$body$req-rawContent();if($body!$body!false)$c-setData($body);$qs$req-server[query_string]??;$c-execute($path.($qs!??$qs:));if($c-statusCode0){$res-status(502);$res-end(upstream error);$c-close();return;}$res-status($c-statusCode);foreach($c-headers??[]as$k$v)$res-header($k,$v);$res-end($c-body);$c-close();});functionblock(Response$res,int$code,string$reason):void{$res-status($code);$res-header(Content-Type,application/json);$res-header(X-Block-Reason,$reason);$res-end(json_encode([errorrequest blocked,reason$reason]));}$server-on(workerStart,function($s,$wid){if($wid0){echoAnti-Fraud → http://0.0.0.0:9900\n;echo拦截规则: IP黑名单 / UA检测 / 频率限制(60/s) / 扫描检测(20路径/min)\n;}});$server-start();