网站被CC攻击怎么办?异常流量识别、Nginx限流与CDN防护教程

网站被CC攻击怎么办?异常流量识别、Nginx限流与CDN防护教程

网站突然变慢、CPU占用升高、PHP或数据库连接耗尽、Nginx出现大量499、502、503和504错误时,很多管理员会怀疑网站遭到CC攻击。

CC攻击通常通过大量看似正常的HTTP或HTTPS请求,持续访问动态页面、搜索接口、登录接口或其他高消耗资源,让Web服务器、应用进程和数据库逐渐失去响应。它与直接打满网络带宽的流量型DDoS不同,攻击流量可能不大,但每个请求都会触发真实业务计算。

处理CC攻击不能只依赖封禁几个IP。现代攻击可能使用代理网络、云主机、移动网络和大量真实客户端地址,简单封IP不仅效果有限,还可能误伤正常用户。

正确的处理顺序应该是:先确认故障是否由异常HTTP请求造成,保留日志和监控数据,再识别被攻击的域名与接口,随后通过CDN、WAF、Nginx限流、应用缓存和数据库保护逐层降低压力。

本文以Linux、Nginx和常见CDN场景为例,介绍一套可执行的CC攻击排查与防护方法。

一、什么是CC攻击

CC攻击通常属于应用层拒绝服务攻击。攻击者不一定发送超大数据包,而是模拟浏览器或客户端,反复请求网站中消耗资源较高的页面。

常见目标包括:

  • WordPress登录页、搜索页和XML-RPC接口。
  • 商品搜索、筛选和详情页面。
  • 登录、注册、验证码和密码找回接口。
  • 动态生成图片、PDF或报表的接口。
  • 没有缓存的API。
  • 会执行复杂数据库查询的URL。
  • 文件不存在时仍由应用程序处理的请求。
  • 绕过CDN直接访问源站IP的请求。

一次请求本身可能完全符合HTTP协议,但大量请求叠加后,会耗尽:

  • Nginx或Apache连接。
  • PHP-FPM、Gunicorn、Node.js等工作进程。
  • 数据库连接池。
  • CPU和内存。
  • 磁盘I/O。
  • 第三方API配额。
  • 公网带宽和CDN回源流量。

二、先区分CC攻击和其他故障

网站访问异常不一定是攻击。程序发布错误、数据库慢查询、缓存失效、定时任务和正常活动流量,也可能造成类似现象。

1. 正常流量突增

特点通常是:

  • 流量来源与推广、新闻或活动时间吻合。
  • 用户会访问多个页面和静态资源。
  • 转化、注册或订单等业务指标同步增加。
  • 请求头、Cookie和访问路径相对完整。

2. 搜索引擎或普通爬虫

特点可能是:

  • 请求具有一定抓取规律。
  • User-Agent相对固定。
  • 主要访问公开页面。
  • 访问速度较快,但通常不会持续攻击单个高消耗接口。

User-Agent可以伪造,不能只凭名称认定请求来自搜索引擎。必要时应通过来源IP与官方验证方法确认。

3. CC攻击

常见特征包括:

  • 大量请求集中访问少数动态URL。
  • 多个IP使用相似的路径、参数和请求频率。
  • 请求绕过正常页面流程,直接访问高成本接口。
  • 静态资源请求很少,动态请求比例异常。
  • Referer、Cookie、Accept-Language等请求头高度重复或明显缺失。
  • 应用进程、数据库连接或CPU先耗尽,公网带宽不一定跑满。

4. 流量型DDoS

如果公网带宽被迅速打满、服务器甚至无法建立SSH连接,或者云平台显示大量异常网络流量,问题可能已经超出单台Nginx可以处理的范围。

此时应优先使用云平台DDoS防护、清洗服务、CDN或高防产品。请求到达Nginx之前,服务器网络就可能已经拥塞,本机防火墙和应用限流无法解决上游带宽瓶颈。

三、发生异常时先保留现场

不要在没有记录数据的情况下立即重启服务器。重启可能暂时恢复服务,却会丢失进程状态和短期流量特征。

先记录当前时间:

`bash date `

查看系统负载:

`bash uptime top `

查看内存:

`bash free -h `

查看连接状态:

`bash ss -s `

查看80和443端口的连接:

`bash sudo ss -ant ‘( sport = :80 or sport = :443 )’ | head `

查看Nginx进程和应用进程:

`bash ps -eo pid,ppid,user,%cpu,%mem,etime,comm,args –sort=-%cpu | head -n 30 `

同时保存:

  • 云平台CPU、内存、带宽和连接数监控截图。
  • CDN请求量、命中率、回源量和安全事件。
  • Nginx访问日志与错误日志。
  • PHP-FPM、Java、Node.js或其他应用日志。
  • 数据库连接数、慢查询和锁等待。

四、从Nginx日志识别异常请求

先确认实际日志路径:

`bash sudo nginx -T | grep access_log `

以下命令假设日志位于 /var/log/nginx/access.log,实际使用时需要替换路径。

1. 统计访问最多的客户端IP

`bash awk ‘{print $1}’ /var/log/nginx/access.log \ | sort | uniq -c | sort -nr | head -n 30 `

如果网站经过CDN或反向代理,日志第一列可能是CDN节点地址,而不是真实访客IP。没有正确配置真实IP模块前,不要直接根据该字段封禁。

2. 统计访问最多的URL

常见日志格式中,请求路径可能位于第7列:

`bash awk ‘{print $7}’ /var/log/nginx/access.log \ | sort | uniq -c | sort -nr | head -n 30 `

如果日志格式经过自定义,应先查看样本:

`bash tail -n 20 /var/log/nginx/access.log `

再根据字段位置调整命令。

3. 按状态码统计

`bash awk ‘{print $9}’ /var/log/nginx/access.log \ | sort | uniq -c | sort -nr `

常见状态码含义:

  • 200:请求成功,不代表请求一定正常。
  • 301302:重定向。
  • 403:被访问控制或安全规则拒绝。
  • 404:资源不存在,可能存在扫描。
  • 429:请求过多,常用于限流响应。
  • 499:客户端在Nginx返回响应前断开。
  • 502503504:上游应用不可用、繁忙或超时。

4. 查看实时高频请求

`bash sudo tail -F /var/log/nginx/access.log `

线上流量较大时,不要长时间把全部日志输出到终端。可以结合 grep 观察目标接口:

`bash sudo tail -F /var/log/nginx/access.log | grep ‘/login’ `

5. 统计最近时间段

如果日志时间格式是常见的Nginx格式,可以先提取目标分钟的记录:

`bash grep ’06/Aug/2026:14:30′ /var/log/nginx/access.log \ | awk ‘{print $7}’ | sort | uniq -c | sort -nr | head `

修改为实际故障时间。不同语言环境和日志格式可能需要调整。

五、确认源站是否被绕过CDN

已经接入CDN的网站,仍可能因为源站IP暴露而被直接攻击。

检查方法包括:

  • 对比CDN请求量和源站访问日志。
  • 查看日志中的Host头是否异常。
  • 检查源站是否接受任意IP直接访问。
  • 检查历史DNS记录、邮件记录和其他子域名是否泄露源站IP。
  • 查看云平台安全组是否允许全球地址访问80和443端口。

更稳妥的源站保护方式是:

  1. 只允许CDN回源地址访问源站80和443端口。
  2. 为CDN回源配置专用Host或验证请求头。
  3. 不在其他DNS记录中复用源站公网IP。
  4. 源站管理端口使用固定办公IP、VPN或堡垒机访问。

CDN回源地址可能更新,应使用服务商提供的官方地址列表或自动化同步方案,避免手工写入后长期不维护。

六、先通过CDN和WAF降低源站压力

CC攻击本质上是大量应用层请求,越早在源站之外拦截,服务器承受的压力越小。

可以采取:

  • 为静态文件和可缓存页面设置合理缓存。
  • 对登录、搜索、注册和API启用速率限制。
  • 对明显自动化请求启用托管质询或浏览器验证。
  • 使用WAF托管规则拦截常见攻击载荷。
  • 对异常地域、ASN、User-Agent或路径组合设置临时规则。
  • 为源站隐藏和访问控制设置独立规则。

不要在攻击期间直接开启过于严格的全站验证。这样可能影响搜索引擎、API客户端、支付回调和正常用户。

优先保护高成本接口,并为确认不需要浏览器访问的接口使用更明确的身份认证、签名或API网关规则。

七、使用Nginx限制请求速率

Nginx的 limit_req 模块可以按指定键限制请求处理速率。常见做法是按客户端IP建立共享内存区域。

在 http 配置块中定义:

`nginx limit_req_zone $binary_remote_addr zone=per_ip_rate:20m rate=5r/s; `

含义:

  • $binary_remote_addr:以二进制形式保存客户端地址。
  • zone=per_ip_rate:20m:建立名为 per_ip_rate 的20MB共享区域。
  • rate=5r/s:每个键平均每秒允许5个请求。

在需要保护的接口中使用:

`nginx location = /login { limit_req zone=per_ip_rate burst=10 nodelay; proxy_pass http://app_backend; } `

burst=10允许短时间内存在一定突发请求;nodelay表示突发额度内的请求不排队延迟处理。

建议返回明确的限流状态码:

`nginx limit_req_status 429; `

完整示例:

`nginx http { limit_req_zone $binary_remote_addr zone=per_ip_rate:20m rate=5r/s; limit_req_status 429;

server { listen 443 ssl; server_name example.com;

location = /login { limit_req zone=per_ip_rate burst=10 nodelay; proxy_pass http://app_backend; } } } `

不要把同一个严格阈值直接应用到全站。网页加载可能同时发起多个CSS、JavaScript、图片和接口请求,全站按IP限制过低会误伤共享网络、公司出口和移动运营商用户。

八、先用dry run观察误伤

支持相应指令的Nginx版本可以启用:

`nginx limit_req_dry_run on; `

Dry run模式不会真正限制请求,但会记录哪些请求本来会被限流。可以先运行一段时间,根据日志调整速率和突发额度,再正式启用。

建议流程:

  1. 只选择登录、搜索或高消耗接口。
  2. 开启dry run。
  3. 覆盖正常业务高峰。
  4. 检查正常用户、爬虫和第三方回调是否命中。
  5. 调整 rate 和 burst
  6. 再关闭dry run正式执行。

九、限制并发连接

limit_conn模块可以限制每个键同时存在的连接或请求数量。

在 http 块定义:

`nginx limit_conn_zone $binary_remote_addr zone=per_ip_conn:20m; `

在目标位置启用:

`nginx location /api/ { limit_conn per_ip_conn 20; limit_conn_status 429; proxy_pass http://app_backend; } `

需要注意:

  • 经过HTTP/2或HTTP/3时,每个并发请求可能被分别计数。
  • NAT、公司网络和移动运营商出口可能有大量用户共享IP。
  • WebSocket、SSE和长轮询连接持续时间较长,不能使用普通页面的阈值。
  • 如果Nginx看到的是CDN节点IP,会把大量用户错误地归为同一个地址。

并发限制应根据接口类型设置,不建议全站使用统一数值。

十、经过CDN时正确获取真实IP

网站经过可信CDN或反向代理时,需要配置Nginx真实IP模块,否则限流和日志都可能只看到代理节点。

示例结构:

`nginx set_real_ip_from 192.0.2.0/24; real_ip_header X-Forwarded-For; real_ip_recursive on; `

这里的IP网段和请求头只是示例,必须替换为CDN官方公布的回源地址和指定真实IP头。

安全要点:

  • 只信任CDN官方回源IP。
  • 不要对所有来源无条件信任 X-Forwarded-For
  • 源站安全组尽量只允许CDN访问。
  • CDN地址列表变化时及时同步。

如果任意客户端都能直接访问源站并自行填写真实IP请求头,攻击者就可能伪造地址绕过按IP限流。

十一、针对高风险接口设置单独规则

不同接口的正常访问频率差异很大,应该分开保护。

登录接口

可以同时使用:

  • IP速率限制。
  • 账号维度失败次数限制。
  • 验证码或人机验证。
  • 多因素认证。
  • 登录失败延迟。

只按IP限制无法防止分布式尝试,也可能误伤共享出口用户。

搜索和筛选接口

建议:

  • 限制每页数量和查询复杂度。
  • 缓存热门查询。
  • 限制通配符和深度分页。
  • 为匿名用户设置更严格配额。
  • 对高成本查询设置超时。

API

优先使用:

  • API密钥或签名。
  • 用户、应用和令牌维度配额。
  • API网关限流。
  • 请求体大小限制。
  • 幂等控制。
  • 明确的超时和熔断。

WordPress

重点检查:

  • /wp-login.php
  • /xmlrpc.php
  • /wp-admin/admin-ajax.php
  • 站内搜索
  • 无缓存的动态页面

如果业务不需要XML-RPC,可以在确认插件和移动客户端不依赖它后限制访问。不要盲目禁用导致远程发布、Jetpack或其他功能异常。

十二、保护应用和数据库

Nginx只能限制进入应用层的请求数量,不能代替应用优化。

应用层

  • 为动态页面和接口增加缓存。
  • 设置合理的请求超时。
  • 限制上传大小和请求体大小。
  • 限制单次查询、导出和报表范围。
  • 避免错误后立即无限重试。
  • 为外部接口调用设置超时、重试上限和熔断。
  • 将耗时任务放入队列异步处理。

PHP-FPM

检查进程池:

`bash sudo systemctl status php-fpm `

服务名称可能带版本号,例如 php8.3-fpm

配置时重点关注:

  • pm.max_children
  • pm.max_requests
  • request_terminate_timeout
  • 慢日志

pm.max_children过低会导致正常请求排队,过高则可能耗尽内存和数据库连接。应根据单个PHP进程实际内存与服务器容量计算。

数据库

检查:

  • 活跃连接和连接池。
  • 慢查询。
  • 锁等待。
  • 缺失索引。
  • 被重复调用的高成本SQL。
  • 临时表、排序和全表扫描。

攻击常常只是放大了原本存在的性能问题。一个正常访问也很慢的接口,在高并发下更容易拖垮数据库。

十三、是否应该直接封禁IP

临时封禁少量明确异常的IP可以快速降低压力,但不应作为长期核心方案。

适合临时封禁的情况:

  • 单个或少量IP持续高频攻击。
  • 来源明确且不存在正常用户。
  • 攻击正在影响服务,需要立即缓解。

不适合只靠封IP的情况:

  • 攻击地址数量很多并持续变化。
  • 大量用户共享NAT出口。
  • 网站经过CDN但真实IP配置不正确。
  • 攻击使用合法云服务或移动网络地址。
  • 攻击绕过CDN直接打源站。

封禁前应保留日志,设置到期时间,并定期清理临时规则,避免防火墙长期积累无效条目。

十四、Nginx配置上线前必须测试

修改配置后执行:

`bash sudo nginx -t `

测试通过后重新加载:

`bash sudo systemctl reload nginx `

不要直接重启Nginx来验证配置。重新加载通常可以保留现有连接,并降低配置错误带来的影响。

上线后观察:

  • 429状态码数量。
  • 正常用户错误率。
  • 登录和支付回调。
  • 搜索引擎抓取。
  • CDN回源状态。
  • 上游响应时间。
  • CPU、内存和数据库连接。

十五、攻击期间的推荐处理顺序

  1. 保存系统监控、CDN数据和访问日志。
  2. 判断是应用层CC还是流量型DDoS。
  3. 找出被集中访问的域名、URL和接口。
  4. 确认日志记录的是真实客户端IP。
  5. 启用CDN或WAF的临时防护规则。
  6. 限制源站只接受可信CDN回源。
  7. 对高成本接口启用Nginx请求速率和并发限制。
  8. 使用dry run或小范围规则验证误伤。
  9. 为动态页面、API和数据库增加缓存与超时。
  10. 临时关闭非必要的高消耗功能。
  11. 攻击缓解后复盘源站暴露、慢接口和监控缺口。
  12. 将临时规则整理为可维护的长期防护策略。

十六、建立长期监控

建议持续监控:

  • 每秒请求数。
  • 各状态码数量。
  • 访问最多的域名和URL。
  • CDN命中率与回源请求量。
  • Nginx活动连接。
  • 上游响应时间。
  • 应用工作进程数量。
  • 数据库连接与慢查询。
  • CPU、内存、磁盘I/O和公网带宽。
  • 429、502、503和504错误。

仅设置“CPU超过90%”告警通常不够。CC攻击可能先耗尽数据库连接或PHP工作进程,而CPU尚未完全跑满。

更有效的告警方式是同时关注请求速率、响应时间、错误率和资源使用情况。

总结

CC攻击通过大量高成本HTTP请求消耗Web服务器、应用进程和数据库资源。它不一定打满公网带宽,也不一定来自少量固定IP,因此简单重启服务器或批量封禁IP通常只能短暂缓解问题。

排查时应从访问日志、系统负载、连接状态和CDN回源数据入手,确认攻击目标与真实客户端来源。防护时应优先在CDN、WAF和源站访问控制层减少无效流量,再使用Nginx的请求速率限制和并发限制保护关键接口。

长期解决方案还包括缓存、接口认证、数据库优化、超时控制、源站隐藏和多维度监控。只有把边缘防护、Web服务器限制和应用性能治理结合起来,网站才不容易在下一次异常流量出现时再次失去响应。

知识库网站安全

网站SSL证书过期怎么办?证书检查、重新签发与自动续期教程

2026-8-5 15:22:08

实操指南知识库

Linux服务器 AppArmor 安全配置

2024-12-11 14:11:13