服务器在遭受高频短连接攻击时,最直观的现象是连接表被迅速占满,大量socket处于TIME_WAIT或SYN_RECV状态,正常用户的请求无法建立新的TCP握手。这种攻击并不依赖巨大的带宽,而是通过海量的、短暂的、合法的TCP连接请求来耗尽内核的跟踪资源。在Debian系统下,默认的内核参数是为了通用场景设置的,面对这种特定类型的资源耗尽攻击,必须进行针对性的深度调优。
理解攻击向量与内核的关联高频短连接攻击主要瞄准两个软肋。第一是conntrack表,也就是连接跟踪表。内核需要记录每一个经过网络栈的连接状态,即使是拒绝的连接,在排查阶段也会短暂占用表项。当攻击者以极高频率发送伪造源IP的SYN包时,conntrack表会在几秒内爆满,导致后续所有包被丢弃。第二是本地端口的快速回收问题。如果攻击是针对本机服务,大量主动关闭的连接会滞留在TIME_WAIT状态,迅速耗尽可用的临时端口,或者导致socket的hash表冲突激增,CPU软中断占用飙升。优化必须同时从这两方面入手。
加固连接跟踪表,防止conntrack溢出netfilter的连接跟踪模块是抵御此类攻击的第一道防线,也是最脆弱的环节。默认的conntrack_max通常根据内存自动计算,但在攻击流量下这个值远远不够。我们需要手动增大上限,并让内核在表满时采取更激进的丢弃策略。
# 查看当前连接跟踪表大小和当前使用量 cat /proc/sys/net/netfilter/nf_conntrack_max cat /proc/sys/net/netfilter/nf_conntrack_count
直接提高最大跟踪连接数,这个值取决于物理内存,每一条跟踪大约占用300字节左右。对于8GB内存的服务器,设置一个较高的值可以争取更多处理时间。
# 设置最大连接跟踪数,例如设置为2097152 sysctl -w net.netfilter.nf_conntrack_max=2097152
更关键的参数是nf_conntrack_tcp_timeout_syn_recv和nf_conntrack_tcp_timeout_syn_sent。攻击者在发送第一个SYN后往往不会完成三次握手,大量的半开连接会长时间占用表项。默认的超时时间过长,必须大幅缩短,让无效的半开连接快速被内核清理掉。
# 将SYN_RECV状态的超时从默认的60秒降低到10秒 sysctl -w net.netfilter.nf_conntrack_tcp_timeout_syn_recv=10 # 将SYN_SENT状态的超时从默认的120秒降低到10秒 sysctl -w net.netfilter.nf_conntrack_tcp_timeout_syn_sent=10
当连接跟踪表确实被填满时,内核的行为由nf_conntrack_buckets和net.netfilter.nf_conntrack_generic_timeout等参数控制。但更直接有效的是开启TCP时间戳和重用机制,并结合SYN Cookie来从源头减少不必要的跟踪条目。对于不需要进行NAT的纯Web服务器,如果确认没有使用iptables的nat表规则,甚至可以彻底卸载nf_conntrack模块,但通常建议保留并优化。
调优TCP协议栈,加速短连接回收高频短连接攻击如果是针对本机服务,比如HTTP的80端口,那么本地会产生大量的TIME_WAIT状态。TIME_WAIT是TCP协议保证可靠关闭的必要机制,但在攻击场景下,2MSL的等待时间会成为灾难。我们需要让内核能够快速回收处于TIME_WAIT状态的socket,并允许端口复用。
# 开启TCP时间戳,有助于精确计算RTT和快速回收 sysctl -w net.ipv4.tcp_timestamps=1 # 开启快速回收TIME_WAIT状态的连接,需配合tcp_timestamps使用 sysctl -w net.ipv4.tcp_tw_recycle=1 # 注意:在较新的Debian内核中,tcp_tw_recycle已被移除,因为它对NAT设备后的客户端不友好。 # 对于现代内核,应重点使用tcp_tw_reuse sysctl -w net.ipv4.tcp_tw_reuse=1
tcp_tw_reuse允许内核将处于TIME_WAIT状态的socket用于新的客户端连接,这在服务端主动关闭连接的高并发场景下极其有效。同时,我们需要扩大本地临时端口的范围,如果服务器需要作为客户端去连接后端,例如反向代理场景,端口范围过小会迅速耗尽。
# 扩大本地临时端口范围,从默认的32768-60999扩大到1024-65535 sysctl -w net.ipv4.ip_local_port_range="1024 65535"
对于TIME_WAIT状态的最大数量,虽然不能直接硬性限制,但可以通过调整tcp_max_tw_buckets来控制。当TIME_WAIT连接数超过这个阈值时,内核会立即销毁多余的连接,并打印警告日志。在攻击期间,这能防止系统因跟踪大量TIME_WAIT而崩溃。
# 设置TIME_WAIT桶的最大数量,例如设置为262144 sysctl -w net.ipv4.tcp_max_tw_buckets=262144启用并强化SYN Cookie机制
SYN Cookie是抵御SYN Flood攻击的核心机制。当系统的SYN队列满时,内核会使用加密的Cookie来响应SYN请求,而无需在内存中分配完整的连接跟踪资源,直到收到客户端的最终ACK才真正建立连接。这能从根本上对抗半开连接攻击。
# 开启SYN Cookies sysctl -w net.ipv4.tcp_syncookies=1 # 调整SYN队列的最大长度,这个队列是等待三次握手完成的半连接队列 sysctl -w net.ipv4.tcp_max_syn_backlog=8192 # 调整处于SYN_RECV状态的最大连接数 sysctl -w net.ipv4.tcp_max_syn_backlog=16384
SYN Cookie并非完全没有代价,它会禁用部分TCP高级特性,如窗口缩放,但在攻击期间,保证服务可用性远比性能优化重要。在Debian系统中,一旦启用SYN Cookie,当SYN队列压力大时内核会自动触发,无需人工干预。
优化孤儿socket与文件描述符限制攻击可能导致大量的socket处于CLOSE_WAIT或LAST_ACK等状态,如果应用层没有及时关闭,这些孤儿socket会消耗内核内存。我们需要限制孤儿socket的数量,并确保系统的文件描述符上限足够高,避免出现“Too many open files”错误。
# 设置系统中允许的孤儿socket最大数量,超出后会被内核复位 sysctl -w net.ipv4.tcp_max_orphans=65536 # 调整系统级文件描述符上限 sysctl -w fs.file-max=6553560 # 同时需要在/etc/security/limits.conf中设置用户级限制 # * soft nofile 65535 # * hard nofile 65535
对于服务进程,比如Nginx或HAProxy,还需要在它们的配置文件中单独提高worker进程的nofile限制,确保每个进程能打开足够的socket。
调整网络核心参数,提升包处理效率当攻击流量到达网卡时,如果内核的软中断处理不过来,即使连接跟踪还有余量,也会导致丢包。我们需要调整网卡队列和软中断相关的参数,让CPU能更高效地处理网络数据包。
# 增加网卡接收队列的长度,让网卡能缓存更多待处理的包 sysctl -w net.core.netdev_max_backlog=5000 # 增大socket的接收和发送缓冲区最大值 sysctl -w net.core.rmem_max=16777216 sysctl -w net.core.wmem_max=16777216 # 调整TCP读写缓冲区的最小、默认和最大值 sysctl -w net.ipv4.tcp_rmem="4096 87380 16777216" sysctl -w net.ipv4.tcp_wmem="4096 65536 16777216"
在多核服务器上,确保网卡的中断请求均匀分布到各个CPU核心,避免单核过载。这通常需要结合硬件队列和irqbalance服务进行调整,但从内核层面,可以开启RPS和RFS来分散负载。
# 开启接收数据包转向(RPS),将处理分散到多个CPU # 以下示例为eth0网卡设置RPS,具体值取决于CPU核心数 echo f > /sys/class/net/eth0/queues/rx-0/rps_cpus # 开启接收流转向(RFS),确保同一流的数据包在同一CPU上处理 sysctl -w net.core.rps_sock_flow_entries=32768使用iptables限制连接速率
内核参数优化提供了更大的缓冲池和更快的回收速度,但要精准拦截恶意源,还需要在netfilter层面进行速率限制。利用iptables的recent和hashlimit模块,可以对单个IP的连接频率进行控制,将攻击流量阻挡在连接跟踪表之前。
# 使用hashlimit模块限制每个源IP到80端口的新建连接速率 iptables -A INPUT -p tcp --dport 80 -m state --state NEW -m hashlimit \ --hashlimit-name http_limit --hashlimit-above 50/sec --hashlimit-burst 100 \ --hashlimit-mode srcip -j DROP # 使用recent模块记录并封禁短时间内发起大量请求的IP 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 60 --hitcount 30 -j DROP
这些规则能在攻击流量进入协议栈之前就将其丢弃,极大地减轻了内核协议栈和连接跟踪模块的压力。需要注意的是,hashlimit和recent模块本身也会消耗少量内存和CPU,要合理设置阈值,避免误伤正常用户。
持久化配置与监控验证所有通过sysctl命令调整的参数在重启后都会失效,必须写入配置文件。在Debian系统中,将参数写入/etc/sysctl.conf或者/etc/sysctl.d/目录下的自定义配置文件,例如/etc/sysctl.d/99-anti-ddos.conf。
# 将以上所有优化参数汇总写入配置文件 cat >> /etc/sysctl.d/99-anti-ddos.conf << EOF net.netfilter.nf_conntrack_max = 2097152 net.netfilter.nf_conntrack_tcp_timeout_syn_recv = 10 net.netfilter.nf_conntrack_tcp_timeout_syn_sent = 10 net.ipv4.tcp_timestamps = 1 net.ipv4.tcp_tw_reuse = 1 net.ipv4.ip_local_port_range = 1024 65535 net.ipv4.tcp_max_tw_buckets = 262144 net.ipv4.tcp_syncookies = 1 net.ipv4.tcp_max_syn_backlog = 16384 net.ipv4.tcp_max_orphans = 65536 fs.file-max = 6553560 net.core.netdev_max_backlog = 5000 net.core.rmem_max = 16777216 net.core.wmem_max = 16777216 net.ipv4.tcp_rmem = 4096 87380 16777216 net.ipv4.tcp_wmem = 4096 65536 16777216 net.core.rps_sock_flow_entries = 32768 EOF # 应用配置 sysctl -p /etc/sysctl.d/99-anti-ddos.conf
优化完成后,必须持续监控连接跟踪表的使用情况、TIME_WAIT状态的数量以及CPU软中断的占用率。使用conntrack -S命令查看统计,ss -s查看socket概要,mpstat -P ALL 1观察每个CPU核心的软中断分布。如果发现某个核心的si占用率持续超过20%,需要进一步调整网卡队列和RPS配置。如果conntrack表使用率仍然接近100%,说明单纯的参数调整已经不足以应对攻击规模,此时应考虑在上游引入专业的DDoS清洗设备或服务,但在绝大多数场景下,上述内核级优化已经能够将服务器的抗短连接攻击能力提升数倍,为后续的自动化防御策略争取宝贵的反应时间。
