本文目录导读:

- 主机层面(操作系统/IPtables/防火墙软件)
- 网络设备层面(路由器/交换机/负载均衡器)
- 应用层面(WAF / 反向代理 / 中间件)
- 开发框架 / 库层面(代码层处理)
- 关键原则:纵深防御
- 技术实现参考(以 Golang 处理自定义协议为例)
针对“畸形报文”(Malformed Packets)的拦截与丢弃,需要根据你所在的网络层级(如网络层、传输层、应用层)以及控制位置(如主机防火墙、路由器、交换机、Web服务器)来采取不同的策略。
以下是几种常见的拦截与丢弃方案:
主机层面(操作系统/IPtables/防火墙软件)
这是最直接的方式,适用于保护单台服务器或PC。
-
Linux 系统(使用 nftables / iptables):
-
丢弃非法标志位组合:例如同时设置了 SYN 和 FIN 标志,或 SYN 且 RST 标志。
# 丢弃同时设置了 SYN 和 FIN 标志的包 iptables -A INPUT -p tcp --tcp-flags ALL SYN,FIN -j DROP # 丢弃Xmas Tree包(设置了 FIN, URG, PSH) iptables -A INPUT -p tcp --tcp-flags ALL FIN,URG,PSH -j DROP # 丢弃Null包(没有任何标志位) iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP
-
校验和错误检查:Linux内核默认会做TCP/UDP/IP校验和验证,如果硬件网卡不支持校验和卸载(Checksum Offloading)或关闭了该功能,内核会自动丢弃校验和错误的包,通常无需额外配置。
-
太小/太大的包:可以使用
iptables的-m length匹配长度异常的IP报文(例如小于最小IP头长度20字节)。
-
-
Windows 系统(高级安全Windows Defender防火墙):
- 在“入站规则”的属性中,进入“协议及端口”选项卡,点击“ICMP设置”或“TCP设置”,可以指定丢弃不符合特定特征(如特定标志位组合)的报文。
- 更底层的方案:使用 WFP(Windows Filtering Platform)开发的第三方防火墙软件。
网络设备层面(路由器/交换机/负载均衡器)
用于在网络入口处拦截畸形包,防止它们进入内网。
-
常见 ACL(访问控制列表)规则(Cisco/Juniper/华为):
- 丢弃带源路由选项(Source Route)的IP包(这是经典畸形包攻击)。
- 丢弃IP TTL为0或1的包(如果不是期望的)。
- 片段攻击防御:
# 拒绝长度小于特定值的IP片段(如TCP头在片段中被截断) access-list 101 deny ip any 192.168.1.0 0.0.0.255 fragments
- L4端口校验:丢弃源端口或目的端口为0的TCP/UDP包(RFC规定端口0无效)。
-
专用 DDoS/IPS 设备(如 Radware, F5, Palo Alto):
- 协议异常检测:启用“协议异常(Protocol Anomaly)”检测引擎,系统会自动识别并丢弃:
- 畸形TCP标志位组合(如SYN-RST-FIN)。
- 包含非法选项(如重复的TCP SACK选项)的包。
- 重叠IP片段且内容矛盾的报文。
- IP头长度字段与真实计算长度不符的包。
- 协议异常检测:启用“协议异常(Protocol Anomaly)”检测引擎,系统会自动识别并丢弃:
应用层面(WAF / 反向代理 / 中间件)
如果应用协议本身(如HTTP/2, WebSocket)中存在畸形报文,需要在应用层处理。
-
Web 应用防火墙(WAF):
- 请求体校验:丢弃不符合RFC规范的HTTP/1.1请求(如包含
Host头缺失、非法的Chunked编码格式、超长URL、HTTP方法名包含特殊字符)。 - 内容类型匹配:检测请求体声明为
application/json但实际传的是二进制乱码,可直接丢弃。 - HTTP/2 帧校验:丢弃长度异常的帧、流ID为0但携带标志位的控制帧、伪头字段(如
path)包含null字符的帧。
- 请求体校验:丢弃不符合RFC规范的HTTP/1.1请求(如包含
-
API 网关或反向代理(Nginx / Envoy):
- 校验:使用 Lua 或 WASM 插件对请求体进行格式校验。
- 协议版本限制:拒绝不支持的HTTP版本(如HTTP/0.9或异常的HTTP/4.0)。
开发框架 / 库层面(代码层处理)
作为最后一道防线,特别是在解析用户输入时。
- 序列化/反序列化库:使用强类型库(如
protobuf、flatbuffers)时,畸形报文通常会被直接丢弃或抛出解析异常。 - 输入验证:对接收到的原始字节流的边界、长度、格式进行严格校验。
- 检查接收到的数据是否至少包含完整的协议头(如最小TLV长度)。
- 如果报文字段指示“后续还有100字节”,而实际接收只有20字节,应直接丢弃整个包或发起连接重置。
关键原则:纵深防御
只在一层拦截是不安全的,建议采用分层拦截策略:
- 网络设备(最外层):丢弃明显的畸形包(标志位组合、长度异常)。
- 主机防火墙:丢弃校验和错误、非法片段的包。
- 应用层WAF:解析HTTP/SIP/WebRTC等应用协议,丢弃格式不合规的请求。
- 代码层:在解析逻辑中,捕获异常并主动重置/丢弃连接。
技术实现参考(以 Golang 处理自定义协议为例)
如果你是自己编程处理原始报文:
// 伪代码:丢弃畸形报文
func HandlePacket(data []byte) {
// 1. 检查最小长度
if len(data) < HeadSize {
fmt.Println("丢弃:报文长度小于头部", HeadSize)
return
}
header := ParseHead(data)
// 2. 校验魔数
if header.Magic != 0xAABB {
fmt.Println("丢弃:魔数无效")
return
}
// 3. 校验长度一致性(防止溢读)
if len(data) < int(header.TotalLength) {
fmt.Println("丢弃:实际长度小于声明长度")
return
}
// 4. 端口/协议字段有效性
if header.PayloadType < 1 || header.PayloadType > 10 {
fmt.Println("丢弃:非法协议类型")
return
}
// ... 继续解析Payload ...
}
- 核心思路:验证一切! 不要信任网络传来的任何字段。
- 最快速度:网络设备上的 ACL 和 IPS 引擎(通常基于 P4/硬件 Offload)处理最快。
- 最细粒度:应用层 WAF 或代码逻辑处理最精确。
- 掉落策略:对于异常包,推荐使用 DROP(直接丢弃,不回复 RST/ICMP),这种策略会减慢攻击者的探测速度(因为它需要等待超时,而不是立刻得到响应)。