服务器被挂蜘蛛池怎么办?抓取滥用防护实战

如果服务器 CPU 突然飙高、带宽跑满,但自己的站访问量并没有涨,日志里还出现一堆陌生的域名,那很可能不是被攻击,而是你的服务器被别人拿去跑蜘蛛池或站群程序了。本文用 9 个问答讲清怎么自查、怎么切断资源滥用,配置与命令均可直接复制。

Q:蜘蛛池是什么?为什么会影响到我的网站?

蜘蛛池是一类黑帽 SEO 工具:用一批域名加大量相互链接的页面,把搜索引擎蜘蛛吸引过来并让它长时间停留在站内,再把要推广的目标站链接塞进这批页面里,借蜘蛛的高频访问撬动收录和权重。

它对普通站长的实际影响有三条,都与资源和收录有关:

  • 吃资源:蜘蛛池主机需要维护成千上万个页面,CPU、内存、磁盘 IO 和连接数被持续占用,你的正常业务被拖慢甚至打不开。
  • 占带宽与出口:站群之间互链互采,出向流量很大,机房很容易因此判定异常并限速。
  • 污染收录:你的站如果被拉进互链网络,会出现大量低质外链,正常内容反而被稀释。

最常见的两种入口是:服务器被入侵后挂上站群程序,以及共享主机 / VPS 被同租户当成蜘蛛池宿主

Q:怎么判断服务器上被挂了蜘蛛池?

四个信号,命中两个就要立刻深查。

# 1. 网站目录里出现大量不认识的站点
ls -lt /www/wwwroot | head -20
du -sh /www/wwwroot/* 2>/dev/null | sort -h | tail -10

# 2. Nginx 配置里出现陌生 server_name
grep -rhE "^\s*server_name" /etc/nginx/ /www/server/panel/vhost/nginx/ 2>/dev/null | sort | uniq -c | sort -rn | head -20

# 3. 连接数与 TCP 状态是否异常(大量 ESTABLISHED 却没人访问)
ss -s
ss -ant state established | wc -l

# 4. 有没有陌生的定时任务在跑脚本
crontab -l
ls -l /etc/cron.d/ /var/spool/cron/ 2>/dev/null

关键判据是「CPU 高 + 你的站访问量没涨 + 日志里有陌生 Host」这三个同时出现。单独 CPU 高也可能是采集、备份、编译,不一定是被挂。

Q:怎么统计出到底是哪些域名在吃我的服务器?

Nginx 默认日志不记录 Host,先加上,跑一天就能看清全貌。

# 在 http 段加一个带 $host 的日志格式
log_format vhost '$host $remote_addr [$time_local] "$request" $status';
access_log /var/log/nginx/vhost.log vhost;

# 统计 Host 分布:Top 20 域名及其请求数
awk '{print $1}' /var/log/nginx/vhost.log | sort | uniq -c | sort -rn | head -20

# 统计陌生 Host 占比(把 www.example.com 换成你自己的域名)
awk '$1 != "www.example.com" {n++} END{print "unknown_host=" n+0}' /var/log/nginx/vhost.log
wc -l < /var/log/nginx/vhost.log

判读经验:正常站点未绑定域名的请求占比通常在 1% 以下,多是扫描器和 IP 直连探测;如果超过 20%,并且这些 Host 每天固定出现、请求量还很稳定,那就是站群或蜘蛛池在跑。

Q:未绑定域名的请求怎么一刀切掉?

用一个 default_server 把所有不在白名单里的 Host 直接断连。注意返回 444 而不是 301——301 会把权重导给别人,等于替站群做嫁衣。

# 放在所有 server 块之前,兜住未绑定域名
server {
    listen 80 default_server;
    listen 443 ssl default_server;
    server_name _;

    ssl_certificate     /etc/nginx/ssl/default_default.crt;
    ssl_certificate_key /etc/nginx/ssl/default_default.key;

    # 444 = 直接关闭连接,不回任何响应
    return 444;
}

# 自己站点显式声明 server_name,不要用通配符或正则大范围匹配
server {
    listen 80;
    server_name www.example.com example.com;
    return 301 https://www.example.com$request_uri;
}

两个注意点:default_server 每个端口只能有一个,443 端口必须配上证书,否则 Nginx 起不来;不要为了省事写成 server_name ~^.*$,那等于把门完全打开,站群换个域名照样进得来。

Q:官方蜘蛛和冒充的爬虫怎么区别对待?

原则是官方蜘蛛放行但不免税,可疑爬虫限速但不禁死,用 map 分组给不同档位。

# 官方蜘蛛拿到空 key(不计入限速),其他爬虫按 IP 限速
map $http_user_agent $crawl_key {
    default                                        $binary_remote_addr;
    "~*(Baiduspider|bingbot|Googlebot|YisouSpider|Sogou web spider|360Spider)"  "";
}

limit_req_zone $crawl_key zone=crawl:10m rate=5r/s;

server {
    listen 443 ssl;
    server_name www.example.com;

    # 单 IP 5r/s + 突发 20,正常用户摸不到这个上限,批量采集会立刻被压
    limit_req   zone=crawl burst=20 nodelay;
    limit_conn  crawl_conn 30;
    limit_req_status 429;
}
limit_conn_zone $binary_remote_addr zone=crawl_conn:10m;

为什么官方蜘蛛要给空 key:Nginx 对空 key 的请求不参与限速统计,等于只对可疑爬虫生效,收录不受影响。但官方蜘蛛同样要限并发,否则一个蜘蛛也能把源站拖慢——放行不等于放开

Q:抓取配额被无效页面消耗光了怎么办?

蜘蛛池最擅长干的就是让你的站被无意义页面填满,把抓取配额吃光,真正要收录的内容反而进不去。要主动收缩可抓范围。

# robots.txt:明确挡掉参数组合页、搜索页、筛选页等高消耗低价值路径
User-agent: *
Disallow: /search
Disallow: /api/
Disallow: /*?*sort=
Disallow: /*?*page=
Disallow: /*?*from=
Disallow: /member/
Allow: /

Sitemap: https://www.example.com/sitemap.xml
  • sitemap 只放核心内容页:标签聚合页、翻页、带参数的列表页全部剔除,数量控制在几百条以内,质量比数量重要得多。
  • 参数页加 noindex:对筛选、排序、打印类页面回 X-Robots-Tag: noindex,别让它们和正文页抢收录。
  • 禁止用 robots.txt 挡 CSS 和 JS:挡掉之后搜索引擎看不懂页面结构,反而拉低质量判断。
# 对参数页统一加 noindex(放在站点 server 块内)
location ~ ^/(search|list) {
    add_header X-Robots-Tag "noindex, nofollow" always;
    proxy_pass http://backend;
}

Q:服务器被当成爬虫出口怎么办?

这是最危险的情况:你的机器在对外抓别人,说明已经被入侵或者装了代理服务,占的是你的带宽、背的是你的 IP 声誉。

# 1. 看出向连接:谁在往外连 80/443
ss -antp state established '( dport = :80 or dport = :443 )' \
  | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head -20

# 2. 找异常进程:长期高 CPU 又不在你的业务名单里
ps -eo pid,ppid,etime,pcpu,pmem,cmd --sort=-pcpu | head -20

# 3. 查最近 7 天被改动过的可执行脚本
find /www/wwwroot /tmp /dev/shm -maxdepth 3 -type f \( -name "*.php" -o -name "*.py" -o -name "*.sh" \) \
  -newermt "-7 days" 2>/dev/null | head -30

# 4. 确认没有对外提供代理
grep -rEn "proxy_pass|socks|tinyproxy|3proxy|squid" /etc/nginx/ /www/server/panel/vhost/ 2>/dev/null | head

处置顺序:先断出口(安全组出向只放白名单端口)→ 再清进程与计划任务 → 最后改密码、换密钥、补漏洞。只清进程不改密码,第二天就会被重新装上。

Q:站点被拉进互链网络、外链被污染了怎么办?

外链被污染没法完全消除,但可以止损、可以申诉,也可以让它对权重的影响降下来。

  • 先量化:用站长平台查外链总量与新增趋势,一周内新增几千条低质域名外链,基本可以确认被拉进去了。
  • 百度搜索资源平台:在「拒绝外链」里批量提交这些域名。规则支持按域名和按 IP 段提交。
  • Google Search Console:用 Disavow Tool 提交 disavow 文件,一个域名一行 domain:spamsite.com
  • 关注自己的内容是否被镜像:蜘蛛池常顺手把被采集的内容做成镜像站,发现后按侵权投诉或 DMCA 流程处理。

要强调的是:拒绝外链是止损动作,不是提速动作。权重不会因此立刻回升,但不处理会持续被稀释。

Q:还有什么补充建议?

  • 先分清「被入侵」还是「被共享」:VPS 上出现陌生站点通常是面板弱口令被爆破或被同租户利用;独立服务器出现陌生进程才是入侵。两者处置完全不同,前者改密换端口,后者要重装系统。
  • Host 统计要常态化:把未绑定域名占比做成日监控,超过 20% 就查。等 CPU 打满了才发现,业务已经受影响。
  • 出口比入口更容易被忽略:大多数站长只盯入向流量,实际上被挂蜘蛛池的服务器出口流量往往先异常。安全组入向和出向都要收紧才是完整配置。
  • 面板和 SSH 别用弱口令:站群投放者批量扫的就是 8888、22 端口和默认账号,改端口、开密钥登录、加登录失败封禁,能挡掉九成尝试。
  • 给爬虫留合理配额:治理的终点是「有效内容被正常收录、无效请求被拦住」,不是把爬虫全挡掉。官方蜘蛛保留放行,可疑爬虫限速,这才是可持续的状态。