高频CC攻击本质上不是靠带宽“灌满”管道,而是用大量看似正常的请求耗尽服务器的TCP连接数、CPU、内存和数据库连接池。很多站点一被打就重启、加带宽,结果攻击流量一上来照样挂,原因是没抓住CC攻击的命门:它消耗的是应用层资源,不是网络层资源。所以防御思路必须从“扛流量”转向“省资源”和“识别异常请求”。
先解决最容易被忽略的一点:TCP连接队列和超时时间。默认情况下,服务器会为每个新建连接分配文件描述符和内存,攻击者只发SYN包或者建立连接后慢速发送请求头,就能把连接占满。你需要调整内核参数,缩短SYN重试次数、减少半连接队列的等待时间、加快TIME_WAIT状态的回收。以Linux为例,可以在/etc/sysctl.conf中加入以下配置:
net.ipv4.tcp_syn_retries = 2 net.ipv4.tcp_synack_retries = 2 net.ipv4.tcp_max_syn_backlog = 65535 net.ipv4.tcp_syncookies = 1 net.ipv4.tcp_fin_timeout = 10 net.ipv4.tcp_tw_reuse = 1 net.ipv4.tcp_tw_recycle = 1 net.ipv4.tcp_keepalive_time = 600 net.ipv4.tcp_keepalive_intvl = 15 net.ipv4.tcp_keepalive_probes = 3 net.ipv4.ip_local_port_range = 1024 65000
执行sysctl -p让配置生效。这一步能直接提升服务器在大量短连接冲击下的存活能力,很多中小站点只做这一项就能扛住初级CC攻击。但要注意,tcp_tw_recycle在NAT环境下可能造成部分用户连接异常,如果业务面向大量移动端用户,建议只开启tcp_tw_reuse并保持recycle关闭。
Web服务器层面的连接数限制与请求超时
Nginx是抗CC的第一道应用层防线。很多人只配置了worker_processes和worker_connections,却忽略了limit_conn和limit_req这两个模块。limit_conn限制单个IP的并发连接数,limit_req限制请求速率。高频CC攻击往往一个IP发起几百上千并发连接,limit_conn可以直接把单个IP的连接数压到10以内。配置示例如下:
http {
limit_conn_zone $binary_remote_addr zone=conn_perip:10m;
limit_req_zone $binary_remote_addr zone=req_perip:10m rate=20r/s;
server {
location / {
limit_conn conn_perip 10;
limit_req zone=req_perip burst=30 nodelay;
}
}
}
这里rate=20r/s表示每秒允许20个请求,burst=30是突发队列长度,nodelay表示超过速率直接拒绝而不是排队。这个配置对正常用户影响很小,但对CC攻击的请求洪流能直接拦截。需要注意的是,如果站点有大量静态资源,应该把limit_req只作用于动态请求,比如location ~ \.php$,否则正常页面加载几十个静态文件也可能触发限速。
识别真实攻击特征并动态封禁
高频CC攻击的请求通常带有明显特征:同一个User-Agent、同一个Referer、固定的URL路径、缺少Cookie或者Cookie值固定。单纯靠限速只能缓解,不能根治。更有效的方式是在Nginx层做特征匹配,对命中规则的请求直接返回444(Nginx自定义的断开连接状态码,不返回任何内容)。例如:
if ($http_user_agent ~* "sqlmap|nikto|fimap|nessus|nmap") {
return 444;
}
if ($http_referer = "") {
return 444;
}
但CC攻击者会不断更换User-Agent和IP,静态规则很快失效。更实用的做法是结合日志分析,用脚本定时统计最近一分钟内请求次数最多的IP和URL,自动加入防火墙黑名单。比如用一条shell命令统计Nginx日志中访问最频繁的IP:
tail -n 10000 /var/log/nginx/access.log | awk '{print $1}' | sort | uniq -c | sort -nr | head -20
把统计结果中请求量明显异常的IP用iptables封禁,或者写入Nginx的deny列表。这个操作可以做成cron任务每分钟执行一次,形成动态防御闭环。需要注意的是,要设置白名单,避免封掉搜索引擎爬虫和CDN回源IP。
利用缓存和静态化减少后端压力
CC攻击最怕的是请求根本不落到后端应用上。如果你的网站有大量动态页面,每次请求都要查数据库、执行PHP或Java代码,那么即使单个请求消耗不大,攻击者用几万并发也能把数据库连接池打满。把能缓存的页面全部缓存到Nginx或Redis,让攻击请求直接命中缓存,后端压力可以下降90%以上。
对于不常变化的页面,用Nginx的proxy_cache或fastcgi_cache做整页缓存。配置示例:
proxy_cache_path /tmp/nginx_cache levels=1:2 keys_zone=my_cache:50m max_size=1g inactive=60m;
server {
location / {
proxy_cache my_cache;
proxy_cache_key "$scheme$host$request_uri";
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
add_header X-Cache $upstream_cache_status;
proxy_pass http://backend;
}
}
对于个性化内容较多的站点,可以做局部缓存或数据缓存,把数据库查询结果存入Redis,减少重复查询。攻击请求即使到达后端,也只会命中Redis而不会穿透到数据库。这里的关键是提前规划好缓存策略,把热点数据、列表页、详情页的公共部分都缓存起来。
引入WAF和第三方清洗服务
当攻击流量超过单台服务器的处理能力时,靠本机配置已经不够了。这时候需要在前端部署WAF(Web应用防火墙)或者接入专业的DDoS/CC防护服务。WAF能基于行为分析识别CC攻击,比如同一IP在短时间内请求大量不同URL、请求间隔过于规律、请求头组合异常等。好的WAF还能做JS挑战和人机验证,对疑似攻击的请求返回一段JavaScript,要求浏览器执行后才能继续访问,这能有效过滤掉脚本发起的攻击。
第三方清洗服务则是把流量先引入高防机房,在云端过滤掉攻击流量后,只把正常请求回源到你的服务器。这种方式对高频CC攻击效果最直接,但成本较高,而且需要把域名解析切换到服务商提供的CNAME。选择时要注意服务商是否支持HTTPS、是否会影响SEO收录、回源IP是否固定。对于业务连续性要求高的站点,建议同时接入两家服务商做互备。
架构层面的隔离与降级
高频CC攻击往往针对某个特定URL或功能模块,比如搜索接口、登录接口、评论提交接口。如果这些接口和主站共用一套服务器资源,攻击会拖垮整个站点。正确的做法是把高风险接口独立部署,或者在前端做接口级别的限流和降级。比如搜索接口可以单独放到一个子域名或独立端口,限制每秒最大请求数,超限后直接返回空结果或提示稍后再试。
数据库层面也要做读写分离和连接数限制。攻击请求如果穿透到数据库,大量慢查询会占满连接池,导致正常请求无法获取连接。可以在数据库前加一层连接池中间件,设置每个应用的最大连接数和等待超时时间。同时开启数据库的慢查询日志,找出被攻击的SQL语句,针对性加索引或改写。
还有一个常被忽视的点:日志写入。CC攻击会产生海量访问日志,如果日志直接写磁盘,磁盘IO会被拖垮,进而影响整个服务器性能。应该把访问日志写入内存文件系统或通过syslog发送到独立日志服务器,避免日志IO成为瓶颈。Nginx可以配置access_log off或者写入/dev/shm。
持续监控与自动化响应
防御CC攻击不是一次性配置完就结束了,攻击者会不断调整策略。你需要建立一套监控体系,实时关注连接数、请求速率、后端响应时间、错误率等指标。当指标异常时,自动触发防御策略,比如临时提高限速阈值、封禁异常IP、切换备用线路。可以用Prometheus+Grafana做监控展示,配合脚本或自动化工具做响应。
具体来说,监控Nginx的stub_status模块输出的活跃连接数、请求数,监控后端应用的响应时间和错误日志。设置告警规则:当500错误率超过5%持续1分钟,或者后端响应时间超过2秒,立即通知运维并执行预设的防御脚本。这套机制的价值在于把人工响应时间从几分钟缩短到几秒,在高频攻击下,几秒的延迟就可能让服务器彻底崩溃。
最后要强调的是,防御高频CC攻击的核心是“让攻击请求的成本远高于正常请求,同时让正常请求不受影响”。单纯堆硬件或加带宽是最低效的方式,真正有效的是在每一层都做资源限制和异常识别,从内核参数到Web服务器,从缓存到WAF,从数据库到监控,形成完整的防御链条。只有每一层都能扛住压力,网站才能在持续攻击下保持稳定运行。
