自建服务器抵御DDoS/CC攻击,核心逻辑不是买一台高防硬抗,而是从网络层、传输层、应用层把攻击流量层层过滤,最终只让正常用户请求抵达后端。绝大多数中小型攻击(百G以下)完全可以通过合理的架构和软件调优扛住,成本远低于商业高防IP。下面直接进入实操,按攻击发起后流量的路径,从外到内逐层设防。

网络层第一道防线:内核参数与iptables调优

攻击流量进入网卡后,首先由内核协议栈处理。默认的Linux内核参数是为普通服务器设计的,面对海量SYN包或短连接会迅速耗尽资源。必须调整的关键参数如下:

net.ipv4.tcp_synack_retries = 1,控制SYN-ACK重试次数,默认5次,改为1次能快速释放半连接队列。net.ipv4.tcp_max_syn_backlog = 65535,扩大SYN队列长度。net.ipv4.tcp_syncookies = 1,开启SYN Cookie,在队列满时用算法验证客户端真实性,是抵御SYN Flood最有效的手段之一。net.core.somaxconn = 65535,调整全连接队列上限。net.ipv4.tcp_tw_reuse = 1,允许TIME_WAIT状态的socket被重新用于新的TCP连接,缓解CC攻击造成的大量短连接堆积。net.ipv4.tcp_fin_timeout = 30,缩短FIN-WAIT-2状态时长。net.ipv4.ip_local_port_range = 1024 65000,扩大可用端口范围。

内核参数调整后,用iptables的recent和limit模块做速率限制。比如限制单个IP每秒新建连接数不超过20个,超过的直接丢弃:

iptables -A INPUT -p tcp --dport 80 -m state --state NEW -m recent --set
iptables -A INPUT -p tcp --dport 80 -m state --state NEW -m recent --update --seconds 1 --hitcount 20 -j DROP

这条规则能过滤掉大量低并发的CC攻击源。对于UDP Flood,直接限制单IP的UDP包速率:

iptables -A INPUT -p udp --dport 53 -m limit --limit 50/s -j ACCEPT
iptables -A INPUT -p udp --dport 53 -j DROP

注意iptables规则顺序,先放行白名单IP(如CDN回源节点、自己的管理IP),再做限制,最后默认丢弃。把规则保存为脚本,开机自启。

传输层第二道防线:Nginx与HAProxy的连接管理

流量到达应用层前,反向代理是关键的缓冲层。Nginx作为前置机,需要针对DDoS和CC做专门配置。worker_processes设为CPU核心数,worker_connections设为65535,multi_accept on让每个worker一次性接受所有新连接。关键指令:

limit_conn_zone $binary_remote_addr zone=perip:10m; 和 limit_conn perip 10; 限制单个IP的并发连接数。limit_req_zone $binary_remote_addr zone=reqperip:10m rate=30r/s; 和 limit_req zone=reqperip burst=20 nodelay; 限制单IP请求速率,burst允许突发,nodelay立即处理突发请求。这两个模块是Nginx层面抗CC的核心。

对于静态资源,开启sendfile、tcp_nopush、gzip压缩,减少带宽消耗。设置合理的keepalive_timeout,攻击期间可以临时降到10秒甚至更短。如果攻击量很大,可以考虑用Nginx的stream模块做四层转发,把TLS终止放在后端,前置机只做纯转发,降低CPU负担。

HAProxy在四层抗DDoS方面表现更优。配置中maxconn设到全局上限,timeout client和timeout server设短。使用stick-table记录IP行为:

stick-table type ip size 1m expire 30s store conn_rate(3s),http_req_rate(10s)
tcp-request connection track-sc0 src
tcp-request connection reject if { sc0_conn_rate gt 100 }
http-request deny if { sc0_http_req_rate gt 200 }

这段配置在TCP层就根据连接速率拒绝,比应用层过滤更高效。HAProxy的nbproc多进程模式可以充分利用多核,但注意与stick-table的兼容性。

应用层第三道防线:WAF规则与行为分析

CC攻击的本质是模拟正常HTTP请求,单纯靠IP速率限制容易误伤共享IP的真实用户(如学校、公司出口)。需要在应用层做更精细的校验。Nginx配合lua-nginx-module可以实现自定义WAF逻辑。最有效的几个手段:

1. JS跳转验证:对可疑请求返回一段JS代码,要求浏览器执行计算并重定向。正常浏览器能自动通过,而攻击脚本通常不解析JS。可以用ngx_lua实现简单的Cookie挑战:生成随机token,要求客户端计算MD5后带在Cookie里,验证通过才放行。这种方式能过滤掉99%的简单CC脚本。

2. 浏览器指纹校验:检查请求头完整性,正常浏览器会携带Accept、Accept-Language、Accept-Encoding等头,而很多攻击工具缺失这些。在Nginx中配置:

if ($http_accept = "") { return 444; }
if ($http_user_agent ~* "curl|wget|python|java") { return 444; }

注意User-Agent过滤不要过于严格,只封明显脚本特征。444状态码是Nginx特有的,直接关闭连接不返回任何内容,节省出站带宽。

3. 动态限速与黑名单联动:用Lua脚本统计每个IP的请求间隔,正常用户点击间隔通常大于500ms,而CC攻击的请求密集且均匀。如果某个IP在10秒内请求间隔标准差极小,直接加入iptables黑名单封锁30分钟。这种基于行为模式的分析比固定阈值更精准。

4. 验证码:对触发规则的IP弹出验证码。自建方案可以用极验或hCaptcha的免费额度,在Nginx层用Lua做验证码校验,通过后生成临时白名单Cookie,有效期1小时。验证码是最后手段,对用户体验有影响,建议只对高度可疑的IP启用。

自建清洗集群:用BGP引流做分布式防御

如果攻击流量超过单机带宽(比如大于1Gbps),单台服务器无论如何优化都会被打满带宽。这时需要多台服务器组成清洗集群。架构如下:

准备3-5台不同机房的VPS作为清洗节点,每台都部署上述防护策略。使用DNS轮询或自建BGP Anycast来分摊流量。BGP Anycast的实现需要你有自己的AS号和IP段,成本较高但效果最好——多个机房广播同一个IP,流量自动路由到最近的节点,任一节点被打死不影响其他节点。如果不想碰BGP,可以用DNS分线路解析,把不同运营商的用户解析到不同清洗节点。

清洗节点与源站之间用专线或加密隧道(如WireGuard)通信,确保回源流量不被窃听。源站只允许清洗节点的IP访问,其他来源全部拒绝。这样即使攻击者知道源站真实IP,也无法直接访问。清洗节点上运行Nginx反向代理,把清洗后的正常流量转发到源站。这套架构的抗D能力取决于清洗节点的总带宽,5台1Gbps的节点就能扛住5Gbps以下的攻击,成本每月几百元。

监控与自动化响应

防御不是一次性配置完就结束了,攻击者会不断变换手法。需要部署实时监控和自动响应机制。用Prometheus加Node Exporter采集系统指标,Grafana展示网络流量、连接数、请求速率。当流量超过阈值时,用Alertmanager触发自动脚本:

脚本逻辑可以这样设计:当出口流量超过带宽的80%持续1分钟,自动调用云服务商API购买临时带宽扩容(如果支持);同时分析Nginx日志中请求数最多的前20个IP,自动加入iptables黑名单;如果攻击特征明显(如某个URL被集中请求),自动在Nginx中对该URL返回403。这些操作都可以通过Ansible或直接SSH执行命令来完成。

日志分析用goaccess或自写脚本,每分钟统计一次请求Top IP和Top URL。攻击期间,把可疑IP的请求日志单独存下来,事后分析攻击工具的特征,更新WAF规则。形成“检测-响应-分析-强化”的闭环。

硬件与系统层面的加固

网卡多队列配置容易被忽略。现代网卡支持RSS(接收端缩放),把网络中断分配到多个CPU核心处理。检查网卡是否支持多队列:ethtool -l eth0,然后用ethtool -L eth0 combined 4设置队列数等于CPU核心数。配合irqbalance服务或手动绑定中断到不同核心,能显著提升小包转发性能。

如果流量极大,考虑使用DPDK绕过内核协议栈。DPDK让应用直接操作网卡,小包转发性能可提升10倍以上。但DPDK开发门槛高,一般用现成的方案如VPP或TRex。对于绝大多数场景,内核调优加上Nginx/HAProxy已经足够。

最后,源站服务器务必隐藏真实IP。所有域名解析到清洗节点,源站IP只用于清洗节点回源。源站不开启任何对外服务端口,仅允许清洗节点IP段的SSH和HTTP访问。定期更换源站IP也是有效的预防手段。

整套方案从内核参数、iptables、反向代理、WAF、分布式清洗到自动化响应,层层递进。根据攻击规模灵活组合,百兆级别攻击单机优化就能扛,千兆级别上清洗集群,万兆以上再考虑引入商业服务。自建的核心优势是成本可控、数据自主、规则灵活,适合对成本和可控性有要求的技术团队。