网站被恶意爬虫耗尽资源?学会用 Nginx 限流与 IP 黑名单保护服务器

前言

做个人站长的朋友一定遇到过这种情况:打开服务器监控面板,发现 CPU 飙到 100%,带宽被打满,网站打开慢如蜗牛。登进去一看,要么是某个搜索引擎的爬虫在疯狂抓取,要么是竞争对手的采集工具在盗取你的内容。对于只有 1 核 1G 低配服务器的个人站长来说,这种恶意流量简直就是噩梦。

本文分享几个实战中用得上的 Nginx 防护手段,不需要昂贵的防火墙设备,纯软件层面就能挡住绝大多数恶意流量。

一、先定位问题:到底是谁在访问?

# 查看实时访问日志,按 IP 统计请求数
tail -1000 /var/log/nginx/access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -20

# 查看特定时间段的请求频率
grep "29/Jul/2026" /var/log/nginx/access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -10

正常用户的请求频率通常在每分钟几到几十次,如果某个 IP 的请求数在短时间内达到数百甚至数千次,基本可以断定是爬虫或攻击流量。

二、Nginx 限流三板斧

2.1 请求频率限制(limit_req)

http {
    limit_req_zone $binary_remote_addr zone=per_ip:10m rate=1r/s;
}

server {
    location / {
        limit_req zone=per_ip burst=5 nodelay;
    }
}

参数说明:

  • rate=1r/s:平均每个 IP 每秒只能发起 1 个请求
  • burst=5:允许瞬时突发 5 个请求
  • nodelay:突发请求不延迟处理,超出 burst 直接返回 503

2.2 并发连接数限制(limit_conn)

http {
    limit_conn_zone $binary_remote_addr zone=conn_per_ip:10m;
}

server {
    location / {
        limit_conn conn_per_ip 10;
    }
}

2.3 带宽限制(limit_rate)

location ~ \.php$ {
    limit_rate 200k;
}

location ~* \.(jpg|png|gif|zip|rar)$ {
    limit_rate 500k;
}

设置 200KB/s 的速度限制后,爬虫抓取一篇 50KB 的文章只需 0.25 秒,体验不受影响;但抓取 1000 篇文章就需要超过 8 分钟,大幅降低爬取效率。

三、IP 黑名单与白名单

3.1 手动封禁恶意 IP

# /etc/nginx/blockips.conf
deny 192.168.1.100;
deny 10.0.0.0/8;
deny 203.0.113.0/24;

# 在 nginx.conf 中引入
http {
    include /etc/nginx/blockips.conf;
}

3.2 自动封禁:结合 fail2ban

# 安装 fail2ban
apt install fail2ban

# 创建 Nginx 限流监控配置
cat > /etc/fail2ban/jail.d/nginx-limit-req.conf << 'EOF'
[nginx-limit-req]
enabled = true
filter = nginx-limit-req
action = iptables-multiport[name=nginx, port="80,443"]
logpath = /var/log/nginx/error.log
maxretry = 3
findtime = 60
bantime = 3600
EOF

systemctl restart fail2ban

配置完成后,如果某个 IP 在 60 秒内触发 3 次限流,fail2ban 会自动将其封禁 1 小时。

3.3 搜索引擎爬虫白名单

map $http_user_agent $is_search_bot {
    default 0;
    "~*(Googlebot|Bingbot|Baiduspider|YandexBot|DuckDuckBot)" 1;
}

server {
    location / {
        if ($is_search_bot = 0) {
            limit_req zone=per_ip burst=5 nodelay;
        }
    }
}

四、其他实用防护技巧

4.1 屏蔽非浏览器 UA

if ($http_user_agent ~* (python|curl|wget|scrapy|Java|okhttp|Go-http-client)) {
    return 444;
}

4.2 限制请求方法

if ($request_method !~ ^(GET|HEAD|POST)$) {
    return 444;
}

4.3 利用 GeoIP 屏蔽非目标地区

load_module modules/ngx_http_geoip_module.so;

http {
    geoip_country /usr/share/GeoIP/GeoIP.dat;
    map $geoip_country_code $allowed_country {
        default no;
        CN yes;
        HK yes;
        TW yes;
        MO yes;
    }
    server {
        if ($allowed_country = no) {
            return 444;
        }
    }
}

五、效果验证与监控

# 查看有多少 IP 被限流
grep "limiting requests" /var/log/nginx/error.log | wc -l

# 查看被 fail2ban 封禁的 IP
fail2ban-client status nginx-limit-req

# 查看服务器负载变化
htop

# 查看带宽占用
nload

建议在配置完限流后的第一周每天检查一次日志,观察是否有误杀正常用户的情况。

六、总结

服务器安全防护是一个持续的过程,没有一劳永逸的方案。Nginx 限流 + IP 黑名单 + fail2ban 自动封禁的组合,对于个人站长来说是成本最低、效果最好的防护手段。不要追求一步到位配置万无一失的防护系统,那既不现实也没有必要。从最基本的频率限制开始,遇到问题再逐步加码,才是务实的做法。

另外提醒一点:防护措施再完善,也要做好数据备份。服务器被爬取内容固然让人不爽,但真遇到数据丢失才是追悔莫及。每周自动备份数据库和网站文件到对象存储,这是每个站长都应该养成的习惯。

Last modification:July 31st, 2026 at 08:16 am

Leave a Comment