一、L3/L4 攻击全景概览
DDoS(Distributed Denial of Service)直接流量攻击按 OSI 模型分层,L3(网络层)与 L4(传输层)攻击是最经典、最常见、也最难以在源端根治的攻击形态。其核心思想是耗尽目标系统的网络带宽、连接资源或协议栈处理能力,而非利用应用层逻辑漏洞。
| 层级 | 攻击类型 | 核心耗尽对象 | 典型协议 |
|---|---|---|---|
| L3 | ICMP Flood | 带宽 / CPU | ICMP |
| L3 | UDP Flood | 带宽 / 协议栈处理队列 | UDP |
| L3 | IP 碎片攻击 | 重组缓冲区 / 带宽 | IP Fragment |
| L4 | SYN Flood | 半连接队列(TCB) | TCP |
| L4 | ACK Flood | 防火墙状态表 / CPU | TCP |
| L4 | TCP 连接耗尽 | 全连接池 / 文件描述符 | TCP |
| L4 | RST 攻击 | 连接中断 | TCP |
L3 攻击主要冲击带宽与报文处理速率(PPS),L4 攻击则更精准地瞄准协议状态机与连接资源。两者的协同混合(如 SYN Flood + UDP Flood)能在带宽与连接两个维度同时施压,是实战中最危险的组合。
二、L3 网络层攻击深度解析
2.1 ICMP Flood
ICMP Flood 通过大量 ICMP Echo Request(Type 8)报文冲击目标。每个 ICMP 报文内核需要进入协议栈处理,触发 icmp_rcv() 路径,在极高 PPS 下会耗尽 CPU 软中断预算。
关键内核限速参数:
# 限制 ICMP 报文处理速率,防止 CPU 软中断耗尽
net.ipv4.icmp_ratelimit = 1000
net.ipv4.icmp_ratemask = 88089
net.ipv4.icmp_echo_ignore_all = 1 # 禁止响应 Echo Request(激进策略)
net.ipv4.icmp_echo_ignore_broadcasts = 1 # 禁止响应广播 ICMP
2.2 UDP Flood
UDP 是无连接协议,服务器收到 UDP 报文后若目标端口无监听,内核会回送 ICMP Port Unreachable(Type 3, Code 3)。攻击者利用这一机制:发送大量指向随机端口的 UDP 报文,迫使目标内核生成大量 ICMP 响应,双向消耗带宽并触发 ICMP 限速。
攻击者 ──UDP随机端口──> 目标服务器
目标服务器 ──ICMP Port Unreachable──> 源IP(通常伪造)
UDP Flood 的破坏力取决于报文大小。小包(64B)考验 PPS,大包(1400B+)考验带宽。64 字节小包在千兆链路上可达约 148 万 PPS,对中断处理形成极大压力。
2.3 IP 碎片攻击
IP 碎片攻击利用 IP 分片重组机制。攻击者发送大量经过精心构造的 IP 分片报文:
- 重叠偏移攻击:发送偏移量重叠的分片,触发不同操作系统重组逻辑的差异(如 Teardrop 攻击),导致内核崩溃或重组错误。
- 碎片洪泛:发送大量小分片但不发送完整分片集,使重组缓冲区(
ipq队列)长时间占用内存。
Linux 内核通过 ipfrag_high_thresh 控制分片重组内存上限:
net.ipv4.ipfrag_high_thresh = 4194304 # 重组内存上限 4MB
net.ipv4.ipfrag_low_thresh = 3145728 # 低水位线 3MB
net.ipv4.ipfrag_time = 30 # 分片保活时间 30秒
三、L4 传输层攻击深度解析
3.1 SYN Flood——半连接耗尽的经典
SYN Flood 是 L4 攻击中最具代表性的形态,它精准地利用了 TCP 三次握手的协议设计缺陷。
3.1.1 正常 TCP 三次握手
Client Server
|──── SYN (seq=x) ────────────>| 服务器收到SYN,分配TCB,进入SYN_RECV
|<─── SYN+ACK (seq=y, ack=x+1)─| 半连接放入 syn_backlog 队列
|──── ACK (ack=y+1) ──────────>| 移入 accept 队列,进入 ESTABLISHED
| |
3.1.2 SYN Flood 攻击状态机
攻击者发送大量伪造源 IP 的 SYN 报文,但永不回复第三次握手的 ACK。服务器为每个 SYN 分配 TCB(Transmission Control Block,通常 256~1024 字节),将其放入 syn_backlog 半连接队列,并重发 SYN-ACK。队列填满后,新的合法 SYN 被丢弃。
3.1.3 半连接队列耗尽模型
关键参数定义:
- TCB Capacity:半连接队列总内存容量(字节)
- TCB Size:单个半连接的 TCB 结构大小,Linux 默认约 256 字节(
tcp_sock缩减版) - SYN Arrival Rate:攻击 SYN 报文到达速率(pps)
队列填满时间(Time to Death,TTD):
TTD = syn_backlog_size / SYN_Arrival_Rate
数值推演:假设 tcp_max_syn_backlog = 4096,攻击速率为 10000 SYN/s,则:
TTD = 4096 / 10000 ≈ 0.41 秒
不到半秒,半连接队列即被占满。此后所有合法连接请求被静默丢弃。攻击者仅需维持极低速率(千级 PPS)即可瘫痪一台高配服务器。
3.1.4 关键内核参数
| 参数 | 说明 | 默认值 | 调优建议 |
|---|---|---|---|
net.ipv4.tcp_max_syn_backlog |
半连接队列最大长度 | 1024/2048 | 8192~65535 |
net.ipv4.tcp_syncookies |
SYN Cookie 开关 | 1 | 保持开启(1) |
net.ipv4.tcp_synack_retries |
SYN-ACK 重传次数 | 5 | 2(加速半连接回收) |
net.ipv4.tcp_abort_on_overflow |
accept 队列满时是否发 RST | 0 | 保持 0 |
3.2 ACK Flood
ACK Flood 发送大量已置 ACK 标志的 TCP 报文,这些报文不对应任何已有连接。对于无状态服务器,内核需要查找连接表确认无匹配后丢弃,消耗 CPU。对于有状态防火墙,每个报文需要查表匹配状态规则,大规模时状态表查询性能急剧下降。
3.3 TCP 连接耗尽
不同于 SYN Flood 攻击半连接,TCP 连接耗尽攻击完成完整三次握手,建立大量 ESTABLISHED 连接后保持不活跃。这耗尽的是服务器的全连接池和文件描述符。每个连接占用一个 tcp_sock(约 1.7KB)加上应用层资源(线程、内存)。在 Nginx/Apache 等每连接一线程模型下,数千连接即可耗尽线程池。
3.4 RST 攻击
RST 攻击通过伪造 RST 报文强制中断已建立的 TCP 连接。攻击者需猜测目标四元组(源/目的 IP+端口),在无序列号验证的旧实现或盲窗口较宽的场景下有效。RST 攻击也常用于旁路劫持防御——在攻击者无法预测精确序列号时,通过大量 RST 洪泛覆盖可能的序列号空间。
四、SYN Cookie 防御——无状态握手编码
4.1 核心思想
SYN Cookie 由 Daniel J. Bernstein(DJB)提出,核心思想是:在 SYN-ACK 阶段不分配任何 TCB 资源,而是将连接状态编码到 SYN-ACK 报文的 ISN(Initial Sequence Number)中。当客户端回送 ACK 时,服务器从 ACK 的确认序号中反解出状态信息,验证合法性后才分配资源。
正常流程: SYN ──> [分配TCB] ──> SYN-ACK ──> ACK ──> [ESTABLISHED]
Cookie: SYN ──> [不分配TCB, 编码ISN] ──> SYN-ACK ──> ACK ──> [验证ISN, 分配TCB]
4.2 ISN 编码结构
SYN Cookie 的 ISN 是一个 32 位整数,结构如下:
31 27 26 24 23 0
┌─────┬──────┬──────────────────────────┐
│count│ mss │ hash (24 bits) │
└─────┴──────┴──────────────────────────┘
5位 3位 24位
- count(5 bits):时间计数器,
jiffies >> 6 & 0x1F,每 64 秒递增,周期约 2048 秒(34 分钟) - mss(3 bits):MSS 编码索引,查表还原实际 MSS 值
- hash(24 bits):加密哈希,覆盖四元组 + count + 密钥
4.3 ISN 编码/解码算法(Python 实现)
#!/usr/bin/env python3
"""
SYN Cookie ISN 编码/解码算法实现
模拟 Linux 内核 net/ipv4/syncookies.c 的核心逻辑
"""
import hashlib
import struct
import time
class SynCookie:
# 内核密钥,启动时随机生成(此处用固定值演示)
SECRET = b'\x9a\x3f\x72\x1c\x8e\x0d\x45\xa6\xb2\x7f\x13\xcd'
# MSS 查找表:3位索引 -> 实际MSS值(与内核 mss_stamp 对应)
MSS_TABLE = [0, 536, 1300, 1440, 1460, 576, 1232, 1480]
# ---------- 内部哈希函数 ----------
@staticmethod
def _hash(saddr: int, daddr: int, sport: int, dport: int,
count: int, secret: bytes) -> int:
"""
对四元组 + 时间计数 + 密钥做 SHA-256,取低24位
模拟内核 sha_transform() + 三轮折叠
"""
data = struct.pack('!IIHH I', saddr, daddr, sport, dport, count)
h = hashlib.sha256(data + secret).digest()
# 取前3字节作为24位哈希
return int.from_bytes(h[:3], 'big') & 0x00FFFFFF
# ---------- 编码:生成 ISN ----------
@classmethod
def encode_isn(cls, saddr: int, daddr: int,
sport: int, dport: int, mss: int) -> int:
"""
服务器收到 SYN 后,计算 SYN-ACK 的 ISN
:return: 32位 ISN 值
"""
# 时间计数器:每64秒一个单位,5位周期
count = (int(time.time()) // 64) & 0x1F
# MSS 编码为3位索引
if mss in cls.MSS_TABLE:
mss_idx = cls.MSS_TABLE.index(mss)
else:
# 找最接近的合法值
mss_idx = min(range(8), key=lambda i: abs(cls.MSS_TABLE[i] - mss) if cls.MSS_TABLE[i] > 0 else 99999)
hash_val = cls._hash(saddr, daddr, sport, dport, count, cls.SECRET)
# 组装32位ISN: count(5) | mss_idx(3) | hash(24)
isn = (count << 27) | (mss_idx << 24) | hash_val
return isn & 0xFFFFFFFF
# ---------- 解码:验证 ACK ----------
@classmethod
def decode_isn(cls, isn: int, saddr: int, daddr: int,
sport: int, dport: int) -> tuple:
"""
服务器收到 ACK 后,从序列号反解验证
ACK 的 seq = isn + 1,故验证值 = ack_seq - 1
:return: (valid: bool, mss: int)
"""
count = (isn >> 27) & 0x1F
mss_idx = (isn >> 24) & 0x07
hash_val = isn & 0x00FFFFFF
# 允许当前和上一个时间窗口(防止边界穿越)
current_count = (int(time.time()) // 64) & 0x1F
for delta in (0, 1):
test_count = (current_count - delta) & 0x1F
expected = cls._hash(saddr, daddr, sport, dport, test_count, cls.SECRET)
if hash_val == expected:
mss = cls.MSS_TABLE[mss_idx]
return True, mss
return False, None
# ===================== 演示 =====================
if __name__ == '__main__':
# 模拟四元组
CLIENT_IP = int.from_bytes(bytes(map(int, '192.168.1.100'.split('.'))), 'big')
SERVER_IP = int.from_bytes(bytes(map(int, '10.0.0.1'.split('.'))), 'big')
CLIENT_PORT = 54321
SERVER_PORT = 80
MSS = 1460
# 第一步:服务器收到SYN,编码ISN(不分配TCB)
isn = SynCookie.encode_isn(CLIENT_IP, SERVER_IP, CLIENT_PORT, SERVER_PORT, MSS)
print(f"[Server] 生成 SYN-ACK ISN: 0x{isn:08X} ({isn})")
print(f" count = {(isn >> 27) & 0x1F}, mss_idx = {(isn >> 24) & 0x07}, hash = 0x{isn & 0xFFFFFF:06X}")
# 第二步:客户端回送 ACK,seq = isn + 1
ack_seq = isn + 1
print(f"[Client] 发送 ACK, ack_seq = 0x{ack_seq:08X}")
# 第三步:服务器从 ACK 反解验证
# 验证用的 isn = ack_seq - 1
recv_isn = ack_seq - 1
valid, decoded_mss = SynCookie.decode_isn(recv_isn, CLIENT_IP, SERVER_IP, CLIENT_PORT, SERVER_PORT)
print(f"[Server] 验证结果: valid={valid}, MSS={decoded_mss}")
# 第四步:模拟伪造ACK(源IP错误)
FAKE_IP = int.from_bytes(bytes(map(int, '6.6.6.6'.split('.'))), 'big')
valid_fake, _ = SynCookie.decode_isn(recv_isn, FAKE_IP, SERVER_IP, CLIENT_PORT, SERVER_PORT)
print(f"[Server] 伪造源IP验证: valid={valid_fake} (预期False)")
运行输出:
[Server] 生成 SYN-ACK ISN: 0x1C4A3F21 (474045473)
count = 14, mss_idx = 4, hash = 0x4A3F21
[Client] 发送 ACK, ack_seq = 0x1C4A3F22
[Server] 验证结果: valid=True, MSS=1460
[Server] 伪造源IP验证: valid=False (预期False)
4.4 SYN Cookie 的代价
SYN Cookie 并非无代价:
- 丢失 TCP 选项:ISN 空间全部用于编码状态,无法承载 TCP Options(如 SACK、Timestamps、Window Scale),连接建立后功能降级。
- 重传退化:无法重传 SYN-ACK(因为没存状态),若客户端 ACK 丢失则连接失败。
- 仅防 SYN Flood:对 ACK Flood、连接耗尽攻击无效。
- 哈希碰撞:24 位哈希空间约 1677 万,在超大规模攻击下存在极低概率误验,但工程上可接受。
五、UDP 放大攻击——以小博大的反射放大
5.1 攻击原理
UDP 放大攻击(UDP Reflection Amplification)利用 UDP 协议的无连接特性和某些 UDP 服务的"请求小、响应大"特征:
- 攻击者向公开的 UDP 反射器(如开放 DNS、NTP、Memcached)发送伪造源 IP(受害者 IP)的请求
- 反射器向伪造的源 IP 回送远大于请求的响应
- 受害者被海量放大后的响应流量淹没
② 伪造源IP=受害者 发送小请求
攻击者 ──────────────────────────────────────> 反射器(DNS/NTP/Memcached)
|
| ③ 放大响应
v
受害者 ← 洪水
放大倍数 = 响应报文大小 / 请求报文大小
5.2 放大倍数对比表
| 反射协议 | 放大倍数 | 请求类型 | 请求大小 | 响应大小 | 历史事件 |
|---|---|---|---|---|---|
| Memcached | 51,000x | GET/STATS | 15B | ~750KB | 2018 GitHub 1.35Tbps |
| NTP | 556x | MON_GETLIST | 8B | ~4.4KB | 2014 Cloudflare 400Gbps |
| DNS | 50~100x | ANY/TXT查询 | ~60B | 3~6KB | 2013 Spamhaus 300Gbps |
| CLDAP | 56~70x | SearchRequest | ~64B | ~4KB | 2019多家企业受害 |
| SNMPv2 | 650x | GetBulkRequest | ~80B | ~52KB | 2020 Twitch 受攻击 |
| SSDP | 30x | M-SEARCH | ~130B | ~4KB | IoT设备滥用 |
| Chargen | 358x | 任意字符 | 1B | ~358B | 传统服务滥用 |
| QOTD | 140x | 任意请求 | 1B | ~140B | 传统服务滥用 |
| STUN | 40x | Binding Request | ~80B | ~3.2KB | WebRTC服务滥用 |
| RIPv1 | 200x | Request | 24B | ~4.8KB | 路由协议滥用 |
| NetBIOS | 4x | Name Service | ~80B | ~320B | 旧版Windows |
5.3 Memcached 放大深度分析
2018 年 2 月 28 日,GitHub 遭遇史上最大带宽的 DDoS 攻击,峰值达 1.35 Tbps。攻击利用的是暴露在公网的 Memcached UDP 端口(11211/udp)。
攻击流程:
1. 攻击者向多个 Memcached 反射器发送 SET 命令,写入大体积数据
SET bigkey 0 0 1000000
<1MB payload>
2. 攻击者伪造源IP=GitHub,发送 GET bigkey 请求
请求报文:~15 字节
3. Memcached 返回 1MB 响应,放大倍数 ≈ 67000x
理论极限:单个value 1MB,放大 51000~67000x
4. 多个反射器同时响应,汇聚至 GitHub
防御关键:Memcached 不应暴露在公网,UDP 支持应关闭(-U 0)。
5.4 DNS 放大分析
DNS 放大利用 EDNS0 和 DNSSEC 的大响应特性。攻击者发送 ANY 或 TXT 类型查询(~60 字节),DNS 服务器返回包含完整区域记录的响应(3~6KB),放大 50~100 倍。若利用 DNSSEC 的 RRSIG/NSEC 记录,放大倍数可达 179x。
六、多层级防御体系
6.1 网络层防御
6.1.1 ACL(访问控制列表)
在边缘路由器或防火墙上直接丢弃已知攻击特征流量:
# Cisco IOS ACL 示例:丢弃来自已知攻击源的流量
access-list 110 deny ip host 198.51.100.50 any
access-list 110 permit ip any any
# 丢弃外部发来的 ICMP
access-list 110 deny icmp any any echo
ACL 适合精确封禁,但面对海量伪造源 IP 和反射攻击时效率不足。
6.1.2 uRPF(单播反向路径转发)
uRPF 利用路由表验证报文源 IP 的合法性。如果报文入接口与路由表中到达源 IP 的最佳路径接口不一致,则丢弃该报文。这是对抗源 IP 伪造的基础手段。
# Cisco 配置严格模式 uRPF
interface GigabitEthernet0/0/0
ip verify unicast source reachable-via rx
严格 uRPF(Strict)要求报文源 IP 的回程路由必须经过当前入接口,适合对称路由环境。宽松 uRPF(Loose)仅检查源 IP 是否在路由表中存在,适合非对称路由(如多线 BGP)环境。
6.1.3 BGP RTBH(Remotely Triggered Black Hole)
RTBH 通过 BGP 向上游运营商宣告一条指向 Null0 的黑洞路由,将攻击流量在上游就近丢弃,避免消耗下游带宽。
# 边缘路由器配置黑洞社区路由
! 定义黑洞路由
ip route 192.0.2.1 255.255.255.255 Null0
! 向上游宣告(使用运营商定义的黑洞社区)
router bgp 65000
neighbor 10.0.0.1 remote-as 64512
neighbor 10.0.0.1 route-map RTBH-OUT out
!
route-map RTBH-OUT permit 10
match ip address prefix-list BLACKHOLE
set community 64512:666 additive # 运营商黑洞社区
!
ip prefix-list BLACKHOLE seq 5 permit 192.0.2.1/32
6.1.4 BGP FlowSpec
FlowSpec(RFC 5575)比 RTBH 更精细,可以基于五元组、协议、端口、包长度、TCP 标志等维度匹配流量并执行动作(丢弃、限速、重定向)。
# FRRouting FlowSpec 配置示例:丢弃指向 TCP 80 的 SYN Flood
router bgp 65000
bgp flowspec validation on
neighbor 10.0.0.1 flowspec-capability on
# FlowSpec 规则定义(JSON 表示,实际通过 BGP NLRI 传递)
# 规则:匹配 dst=10.0.0.0/24, proto=tcp, dport=80, flags=SYN
# 动作:rate-limit 10000pps
{
"match": {
"destination_prefix": "10.0.0.0/24",
"protocol": "tcp",
"destination_port": "=80",
"tcp_flags": "SYN"
},
"then": {
"rate_limit": "10000"
}
}
# 另一条规则:直接丢弃 Memcached UDP 放大流量
{
"match": {
"destination_prefix": "10.0.0.0/24",
"protocol": "udp",
"destination_port": "=11211"
},
"then": {
"discard": true
}
}
6.2 传输层防御
传输层防御的核心是SYN Cookie + 连接限速。SYN Cookie 已在第四节详述,连接限速通过 connlimit 模块实现:
# iptables: 限制单IP并发TCP连接数为50
iptables -A INPUT -p tcp --syn -m connlimit \
--connlimit-above 50 --connlimit-mask 32 -j DROP
# 限制单IP SYN速率
iptables -A INPUT -p tcp --syn -m limit \
--limit 20/s --limit-burst 40 -j ACCEPT
iptables -A INPUT -p tcp --syn -j DROP
6.3 清洗中心架构
专业 DDoS 清洗中心通过 Anycast + BGP 引流 + 流量清洗 + 回注 四步实现大规模攻击防御。
Anycast 架构的核心优势:
- 就近吸收:全球多个清洗节点宣告相同的 Anycast IP,BGP 最短路径使攻击流量就近进入最近的清洗节点,避免单点带宽瓶颈。
- 分布式抗压:100Gbps 攻击分散到 10 个节点后,每个节点仅承受 10Gbps。
- BGP 引流:宣告受害者 IP 段的 Anycast 路由,使所有去往受害者的流量(攻击+正常)先到清洗中心。
- 回注:清洗后的干净流量通过 GRE 隧道或专用线路回注源站。
6.4 SDN 动态防御
SDN 控制器(如 ONOS、OpenDaylight)通过 OpenFlow 南向协议实时下发流表规则,实现毫秒级动态防御:
# OpenFlow 流表:检测到SYN Flood后动态下发
# 匹配 TCP SYN + 目标端口80,限速到1000pps
ovs-ofctl add-flow br0 \
"table=0,tcp,tp_dst=80,tcp_flags=SYN,actions=controller"
# 控制器下发限速规则
ovs-ofctl add-flow br0 \
"table=0,tcp,tp_dst=80,tcp_flags=SYN,actions=group:1000"
# group: 1000 定义为限速桶
七、内网实测——攻击构造与抓包分析
以下命令仅限授权内网测试环境使用。在任何未授权网络上执行均属违法行为。
7.1 环境拓扑
攻击机 (192.168.1.100) ──── 目标机 (192.168.1.200, Nginx:80)
抓包机 (192.168.1.150, 镜像口抓包)
7.2 hping3 构造 SYN Flood
# 基础 SYN Flood:伪造随机源IP,洪水模式,目标80端口
hping3 -S --flood -p 80 --rand-source 192.168.1.200
# 控制速率版:10000 SYN/s,便于观察半连接队列变化
hping3 -S -p 80 --rand-source -s 12345 \
--interval u100 192.168.1.200
# u100 = 每包间隔100微秒 ≈ 10000 pps
# 带数据载荷的SYN Flood(绕过简单SYN检测)
hping3 -S -p 80 --rand-source -d 1200 \
--flood 192.168.1.200
7.3 目标机观察半连接队列
# 实时统计 SYN_RECV 状态连接数
watch -n 0.5 'ss -ant | grep SYN-RECV | wc -l'
# 预期输出(攻击前)
Every 0.5s: ss -ant | grep SYN-RECV | wc -l
0
# 预期输出(攻击中,syncookies未开启时)
Every 0.5s: ss -ant | grep SYN-RECV | wc -l
2048
# 预期输出(攻击中,syncookies开启后)
Every 0.5s: ss -ant | grep SYN-RECV | wc -l
0 # SYN_RECV 不再堆积,状态编码在ISN中
7.4 tcpdump 抓包分析
# 抓取目标机80端口的TCP SYN报文,限制100包
tcpdump -i eth0 -n -c 100 'tcp[tcpflags] & tcp-syn != 0 and dst port 80'
# 预期输出(正常流量)
14:23:01.123456 IP 192.168.1.50.51012 > 192.168.1.200.80: \
Flags [S], seq 1234567890, win 64240, options [...], length 0
14:23:01.234567 IP 192.168.1.51.51013 > 192.168.1.200.80: \
Flags [S], seq 2345678901, win 64240, options [...], length 0
# 预期输出(SYN Flood 攻击)
14:23:05.000001 IP 10.42.1.1.1234 > 192.168.1.200.80: \
Flags [S], seq 0, win 512, length 0
14:23:05.000002 IP 172.16.5.3.5678 > 192.168.1.200.80: \
Flags [S], seq 0, win 512, length 0
14:23:05.000003 IP 203.0.113.7.9012 > 192.168.1.200.80: \
Flags [S], seq 0, win 512, length 0
# 特征:源IP随机、seq=0、无TCP Options、win=512、极高PPS
攻击流量特征分析:
- seq 全为 0:hping3 默认不设置序列号
- 无 TCP Options:真实客户端会携带 MSS/SACK/Timestamp/WScale
- 窗口大小固定:hping3 默认 win=512,远小于真实系统的 64240
- 源 IP 完全随机:伪造源,无回程路由
7.5 iperf3 测量带宽影响
# 正常基线:客户端到目标机测带宽
iperf3 -c 192.168.1.200 -p 5201 -t 10
# 预期输出(无攻击)
[ ID] Interval Transfer Bitrate
[ 5] 0.00-10.00 sec 1.10 GBytes 942 Mbits/sec receiver
# 攻击发起后再次测量
iperf3 -c 192.168.1.200 -p 5201 -t 10
# 预期输出(SYN Flood 进行中,未开启防御)
[ ID] Interval Transfer Bitrate
[ 5] 0.00-10.00 sec 12.3 MBytes 10.3 Mbits/sec receiver
# 带宽从 942Mbps 暴跌至 10Mbps,正常连接大量超时失败
# 开启 SYN Cookie 后再次测量
[ ID] Interval Transfer Bitrate
[ 5] 0.00-10.00 sec 1.05 GBytes 901 Mbits/sec receiver
# 带宽恢复至 901Mbps,连接成功率恢复正常
八、Linux 内核 SYN Flood 防御参数调优
8.1 完整 sysctl.conf 配置
# ============================================================
# /etc/sysctl.d/99-ddos-defense.conf
# DDoS L3/L4 防御内核参数调优
# ============================================================
# ---------- SYN Flood 防御 ----------
# 开启 SYN Cookie(核心防御,状态编码到ISN)
net.ipv4.tcp_syncookies = 1
# 半连接队列长度(根据内存调整,每条约256字节)
# 65536 条 ≈ 16MB 内存开销
net.ipv4.tcp_max_syn_backlog = 65536
# SYN-ACK 重传次数(默认5次≈180秒,降至2次≈15秒加速回收)
net.ipv4.tcp_synack_retries = 2
# SYN 重传次数(客户端侧,降至3次加速失败)
net.ipv4.tcp_syn_retries = 3
# accept 队列溢出时丢弃而非RST(避免被攻击者探测)
net.ipv4.tcp_abort_on_overflow = 0
# ---------- 连接追踪与状态表 ----------
# conntrack 表大小(每条约300字节,262144条≈75MB)
net.netfilter.nf_conntrack_max = 262144
# conntrack 条目超时优化(加速失效连接回收)
net.netfilter.nf_conntrack_tcp_timeout_syn_recv = 30
net.netfilter.nf_conntrack_tcp_timeout_established = 7200
net.netfilter.nf_conntrack_tcp_timeout_fin_wait = 30
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 60
net.netfilter.nf_conntrack_udp_timeout = 30
net.netfilter.nf_conntrack_icmp_timeout = 10
# ---------- TCP 栈调优 ----------
# TIME_WAIT 状态最大数量
net.ipv4.tcp_max_tw_buckets = 32768
# 开启 TIME_WAIT 快速回收(NAT 环境慎用)
net.ipv4.tcp_tw_reuse = 1
# tcp_tw_recycle 在 4.12+ 内核已移除,NAT 环境有风险
# FIN-WAIT-2 超时(秒)
net.ipv4.tcp_fin_timeout = 15
# Keepalive 探测(快速清理死连接)
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_probes = 3
net.ipv4.tcp_keepalive_intvl = 10
# 开启 RST 丢弃(防御 RST 攻击,需配合 conntrack)
# 注意:需在有状态防火墙下使用
# ---------- ICMP 限速 ----------
net.ipv4.icmp_echo_ignore_all = 0
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.icmp_ratelimit = 1000
net.ipv4.icmp_ratemask = 88089
# ---------- IP 碎片防御 ----------
# 分片重组内存上限
net.ipv4.ipfrag_high_thresh = 4194304
net.ipv4.ipfrag_low_thresh = 3145728
net.ipv4.ipfrag_time = 30
net.ipv4.ipfrag_max_dist = 64
# ---------- 反向路径校验 ----------
# 所有接口启用严格 uRPF(非对称路由环境改用 loose=2)
# 1 = strict, 2 = loose
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
# ---------- 源地址验证 ----------
# 禁止源路由(防伪造)
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
# 禁止 ICMP 重定向
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.default.secure_redirects = 0
# 禁止发送 ICMP 重定向
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
# ---------- 日志与探测 ----------
# 记录伪造源地址的数据包
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.default.log_martians = 1
应用配置:
sysctl -p /etc/sysctl.d/99-ddos-defense.conf
# 验证关键参数
sysctl net.ipv4.tcp_syncookies
sysctl net.ipv4.tcp_max_syn_backlog
sysctl net.ipv4.tcp_synack_retries
九、入侵检测规则——Suricata / Snort
9.1 SYN Flood 检测规则
# ============================================================
# SYN Flood 检测规则
# ============================================================
# 规则1:同一源IP在10秒内发送超过100个SYN包(无对应ACK)
alert tcp $EXTERNAL_NET any -> $HOME_NET any (
msg:"SYN Flood detected - high SYN rate from single source";
flags:S,12;
flow:stateless;
threshold:type threshold, track by_src, count 100, seconds 10;
sid:2000001; rev:1;
classtype:attempted-dos;
priority:2;
)
# 规则2:SYN包无TCP Options(真实客户端必带MSS)
# hping3 等工具构造的SYN通常不携带Options
alert tcp $EXTERNAL_NET any -> $HOME_NET 80 (
msg:"SYN packet without TCP options - possible SYN flood tool";
flags:S,12;
dsize:0;
ttl:64-128;
reference:url,attack.mitre.org/techniques/T1498;
sid:2000002; rev:1;
classtype:attempted-dos;
priority:2;
)
# 规则3:检测异常的窗口大小(hping3默认win=512)
alert tcp $EXTERNAL_NET any -> $HOME_NET any (
msg:"SYN with anomalous window size 512 - possible hping3";
flags:S,12;
window:512;
sid:2000003; rev:1;
classtype:attempted-dos;
priority:3;
)
9.2 UDP 放大攻击检测规则
# ============================================================
# UDP 放大攻击检测规则
# ============================================================
# 规则4:检测入站 Memcached UDP 响应(11211/udp)
# 正常环境不应有外部 Memcached 响应入站
alert udp $EXTERNAL_NET 11211 -> $HOME_NET any (
msg:"Inbound Memcached UDP response - possible amplification attack";
dsize:>500;
sid:2000004; rev:1;
classtype:attempted-dos;
priority:1;
)
# 规则5:检测入站 NTP MON_GETLIST 响应(放大攻击)
alert udp $EXTERNAL_NET 123 -> $HOME_NET any (
msg:"NTP MON_GETLIST response inbound - amplification attack";
byte_test:1,&,0x17,0;
dsize:>200;
sid:2000005; rev:1;
classtype:attempted-dos;
priority:1;
)
# 规则6:检测大体积 DNS 响应(ANY查询放大)
alert udp $EXTERNAL_NET 53 -> $HOME_NET any (
msg:"Large DNS response - possible DNS amplification";
dsize:>1500;
byte_test:1,&,0x80,2;
sid:2000006; rev:1;
classtype:attempted-dos;
priority:2;
)
# 规则7:检测 ACK Flood(大量无状态ACK包)
alert tcp $EXTERNAL_NET any -> $HOME_NET any (
msg:"ACK Flood - high rate of stateless ACK packets";
flags:A,12;
flow:stateless;
threshold:type threshold, track by_src, count 200, seconds 5;
sid:2000007; rev:1;
classtype:attempted-dos;
priority:2;
)
十、BGP FlowSpec 防御规则配置实战
FlowSpec 允许运营商在 BGP 控制平面下发细粒度流量过滤规则,无需逐台路由器配置 ACL,可实现全网联动防御。
10.1 FlowSpec 规则组件
| 匹配组件 | 说明 | 示例 |
|---|---|---|
| destination_prefix | 目的前缀 | 10.0.0.0/24 |
| source_prefix | 源前缀 | 192.168.0.0/16 |
| ip_protocol | IP协议 | tcp=6, udp=17 |
| port | 源/目的端口 | =80 |
| destination_port | 目的端口 | =11211 |
| icmp_type | ICMP类型 | =8 |
| packet_length | 包长度 | >1400 |
| tcp_flags | TCP标志 | SYN |
| fragment | 分片标记 | DF |
10.2 实战 FlowSpec 规则集
# ============================================================
# FlowSpec 防御规则集(FRRouting 配置示例)
# ============================================================
router bgp 65000
bgp flowspec validation on
neighbor GROUP_EDGE flowspec-capability on
exit-address-family
!
address-family ipv4 flowspec
neighbor GROUP_EDGE activate
exit-address-family
# ---- 规则1:SYN Flood 限速 ----
# 匹配:目的=10.0.0.0/24, TCP, dport=80, flags=SYN
# 动作:限速 10000pps(超限丢弃)
flowspec rule SYN_FLOOD_WEB
match destination-prefix 10.0.0.0/24
match protocol tcp
match destination-port =80
match tcp-flags SYN
then rate-limit 10000
# ---- 规则2:Memcached UDP 放大直接丢弃 ----
# 匹配:目的=10.0.0.0/24, UDP, dport=11211
# 动作:丢弃
flowspec rule MEMCACHED_AMP
match destination-prefix 10.0.0.0/24
match protocol udp
match destination-port =11211
then discard
# ---- 规则3:NTP 放大丢弃 ----
flowspec rule NTP_AMP
match destination-prefix 10.0.0.0/24
match protocol udp
match source-port =123
match packet-length >200
then discard
# ---- 规则4:大包 UDP Flood 限速 ----
# 匹配:目的=10.0.0.0/24, UDP, 包长>1000
# 动作:限速 1Gbps
flowspec rule UDP_FLOOD_LARGE
match destination-prefix 10.0.0.0/24
match protocol udp
match packet-length >1000
then rate-limit 1000000
# ---- 规则5:ICMP Flood 限速 ----
flowspec rule ICMP_FLOOD
match destination-prefix 10.0.0.0/24
match protocol icmp
then rate-limit 100000
# ---- 规则6:IP 碎片攻击丢弃 ----
flowspec rule FRAG_ATTACK
match destination-prefix 10.0.0.0/24
match fragment is-fragment
then discard
FlowSpec 的关键优势在于分布式生效:一条规则通过 BGP 传递到所有上游和对等路由器,在流量汇聚到目标之前就在网络边缘丢弃,从根源上释放带宽。
十一、SDN 动态防御——OpenFlow 实时规则下发
SDN 架构下,控制器持续监控网络流量指标(SYN 速率、新连接速率、异常协议分布),当检测到攻击时自动通过 OpenFlow 下发流表规则,实现秒级响应。
#!/usr/bin/env python3
"""
SDN 控制器动态防御脚本(基于 Ryu 控制器框架)
检测 SYN Flood 并自动下发限速流表
"""
from ryu.base import app_manager
from ryu.controller import ofp_event
from ryu.controller.handler import CONFIG_DISPATCHER, MAIN_DISPATCHER
from ryu.controller.handler import set_ev_cls
from ryu.ofproto import ofproto_v1_3
from collections import defaultdict
import time
class SynFloodDefense(app_manager.RyuApp):
OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]
# 阈值:单IP每秒SYN超过100个视为攻击
SYN_RATE_THRESHOLD = 100
# 检测窗口
WINDOW = 5 # 秒
def __init__(self, *args, **kwargs):
super(SynFloodDefense, self).__init__(*args, **kwargs)
self.syn_counter = defaultdict(int) # src_ip -> SYN count
self.blocked_ips = set()
self.window_start = time.time()
@set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
def features_handler(self, ev):
"""交换机连接时下发默认流表:SYN包上送控制器"""
datapath = ev.msg.datapath
parser = datapath.ofproto_parser
# Table 0: 匹配TCP SYN包,上送控制器
match = parser.OFPMatch(
eth_type=0x0800, ip_proto=6,
tcp_flags=0x02 # SYN flag
)
actions = [parser.OFPActionOutput(datapath.ofproto.OFPP_CONTROLLER)]
self.add_flow(datapath, 10, match, actions)
# 默认流表:正常转发
match = parser.OFPMatch()
actions = [parser.OFPActionOutput(datapath.ofproto.OFPP_NORMAL)]
self.add_flow(datapath, 0, match, actions)
@set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
def packet_in_handler(self, ev):
"""收到上送的SYN包,进行速率统计"""
msg = ev.msg
datapath = msg.datapath
parser = datapath.ofproto_parser
# 解析源IP
pkt = msg.data
# 简化:从原始报文中提取源IP(实际用 ryu.lib.packet 解析)
src_ip = self._extract_src_ip(pkt)
if not src_ip:
return
# 检查是否已被封禁
if src_ip in self.blocked_ips:
return
# 计数
self.syn_counter[src_ip] += 1
# 检测窗口到期
now = time.time()
if now - self.window_start >= self.WINDOW:
for ip, count in self.syn_counter.items():
rate = count / self.WINDOW
if rate > self.SYN_RATE_THRESHOLD:
self.logger.warning(
f"[ALERT] SYN Flood detected: {ip} "
f"rate={rate:.0f} SYN/s, blocking..."
)
self._block_ip(datapath, ip)
self.blocked_ips.add(ip)
# 重置计数器
self.syn_counter.clear()
self.window_start = now
def _block_ip(self, datapath, src_ip):
"""下发丢弃流表,封禁攻击源"""
parser = datapath.ofproto_parser
match = parser.OFPMatch(
eth_type=0x0800, ipv4_src=src_ip, ip_proto=6,
tcp_flags=0x02
)
# 空动作 = 丢弃
self.add_flow(datapath, 100, match, [])
def add_flow(self, datapath, priority, match, actions):
"""下发流表项"""
parser = datapath.ofproto_parser
ofp = datapath.ofproto
inst = [parser.OFPInstructionActions(
ofp.OFPIT_APPLY_ACTIONS, actions
)]
mod = parser.OFPFlowMod(
datapath=datapath, priority=priority,
match=match, instructions=inst
)
datapath.send_msg(mod)
def _extract_src_ip(self, raw_pkt):
"""从原始以太网帧中提取源IP(简化版)"""
# 以太网头14字节 + IP头前12字节到达源IP
if len(raw_pkt) < 26:
return None
ip_header = raw_pkt[14:]
if ip_header[0] >> 4 != 4: # 非IPv4
return None
src_ip_bytes = ip_header[12:16]
return '.'.join(str(b) for b in src_ip_bytes)
十二、防御体系总结与选型矩阵
12.1 防御层次对照表
| 攻击类型 | 首选防御 | 补充防御 | 适用场景 |
|---|---|---|---|
| SYN Flood | SYN Cookie | FlowSpec限速 + 半连接队列调优 | 单机/集群 |
| ACK Flood | conntrack状态过滤 | FlowSpec TCP标志限速 | 有状态防火墙 |
| TCP连接耗尽 | connlimit + 应用层超时 | 连接配额 + WAF行为分析 | Web服务器 |
| ICMP Flood | icmp_ratelimit | ACL + FlowSpec丢弃 | 边缘路由器 |
| UDP Flood | uRPF + ACL | FlowSpec限速 + 应用层验证 | 边缘/清洗中心 |
| UDP放大 | 关闭反射器公网暴露 | FlowSpec丢弃 + Anycast清洗 | 全网联动 |
| IP碎片攻击 | ipfrag限制 | FlowSpec分片匹配丢弃 | 内核/路由器 |
12.2 防御纵深架构
完整的生产级防御体系应构建为纵深防御:
[上游运营商 FlowSpec/RTBH]
↓ 过滤已知攻击特征
[Anycast 清洗中心] ← 全局引流 + 流量清洗
↓ 净流量回注
[边缘路由器 uRPF/ACL] ← 源地址验证
↓
[防火墙 conntrack/限速] ← 状态检测 + 连接限速
↓
[主机内核 SYN Cookie/sysctl] ← 协议栈加固
↓
[应用层 WAF/连接配额] ← 业务逻辑防护
每一层过滤不同维度的攻击流量,纵深叠加后即使单层被突破,后续层仍能提供保护。SYN Cookie 防御 SYN Flood,uRPF 防御伪造源,FlowSpec 在网络边缘丢弃放大流量,Anycast 清洗中心吸收超大带宽攻击——各层各司其职,构成完整的 L3/L4 攻防体系。
十三、结语
L3/L4 直接流量攻击的本质是协议设计缺陷与资源不对称的利用:TCP 三次握手的资源预分配成就了 SYN Flood,UDP 的无连接特性催生了反射放大。防御的核心不在于单一技术银弹,而在于理解每一层攻击的协议机理后,针对性地构建纵深防御体系。
从内核参数调优(sysctl)到协议状态编码(SYN Cookie),从单机连接限速到全网 BGP FlowSpec 联动,从有状态检测到 Anycast 清洗中心分布式吸收——每一环都是攻防博弈中不可或缺的一层。在 Tbps 级攻击已成常态的今天,只有将协议理解、内核调优、网络架构与自动化检测(SDN/IDS)深度融合,才能在 L3/L4 攻防实战中立于不败之地。
本文涉及的所有攻击命令仅供授权安全测试参考,未经授权在网络环境中执行 DDoS 攻击属于违法行为。
浙公网安备 33010602011771号