第 13 章:IPv6 防火墙 ip6tables
第 13 章:IPv6 防火墙 ip6tables
本章目标:掌握 ip6tables 的使用方法,理解 IPv6 与 IPv4 防火墙的差异,能够为双栈服务器配置完整的防火墙策略。
13.1 为什么需要 IPv6 防火墙
13.1.1 常见误区
❌ “IPv6 地址空间大,不需要防火墙”
事实:IPv6 地址虽然大,但通过 DNS、扫描工具(如 ZMapv6)和 IPv6 邻居发现协议,攻击者仍能发现目标。
❌ “我在 iptables 中配了规则,IPv6 也自动生效了”
事实:iptables 只处理 IPv4,ip6tables 才处理 IPv6,两者完全独立。
❌ “我的服务器没有 IPv6 地址,不需要管”
事实:大多数现代 Linux 发行版默认启用 IPv6,可能已经有 link-local 地址甚至全局地址。
13.1.2 检查 IPv6 状态
# 查看 IPv6 地址
ip -6 addr show
# 查看 IPv6 路由
ip -6 route show
# 检查 IPv6 是否启用
cat /proc/sys/net/ipv6/conf/all/disable_ipv6
# 0 = 启用,1 = 禁用
# 测试 IPv6 连通性
ping6 ::1 # 回环地址
ping6 fe80::1%eth0 # link-local 地址
ping6 2001:db8::1 # 全局地址
13.2 ip6tables 语法
13.2.1 与 iptables 的相似性
ip6tables 的语法与 iptables 几乎完全相同,主要区别在于:
| 差异 | iptables (IPv4) | ip6tables (IPv6) |
|---|---|---|
| 命令 | iptables | ip6tables |
| 地址格式 | IPv4(192.168.1.1) | IPv6(2001:db8::1) |
| 网段格式 | CIDR(/24) | CIDR(/64) |
| ICMP | -p icmp | -p ipv6-icmp |
| 特殊地址 | 127.0.0.0/8 | ::1/128, fe80::/10 |
| NAT | 支持 | 有限支持(见下文) |
13.2.2 基本操作
# 查看所有链
sudo ip6tables -L -n -v --line-numbers
# 添加规则
sudo ip6tables -A INPUT -p tcp --dport 22 -j ACCEPT
# 删除规则
sudo ip6tables -D INPUT 1
# 设置默认策略
sudo ip6tables -P INPUT DROP
# 清空规则
sudo ip6tables -F
# 导出/导入规则
sudo ip6tables-save > /tmp/ip6tables.rules
sudo ip6tables-restore < /tmp/ip6tables.rules
13.3 IPv6 特有的协议差异
13.3.1 ICMPv6 的重要性
在 IPv6 中,ICMPv6(Internet Control Message Protocol for IPv6)比 IPv4 中的 ICMP 更加重要,它承担了多项关键功能:
| 功能 | 说明 | 不允许的后果 |
|---|---|---|
| 邻居发现(NDP) | 类似 IPv4 的 ARP | 无法解析链路层地址 |
| 路由通告(RA) | 路由器通告前缀 | 无法获取 IPv6 地址 |
| 路由请求(RS) | 主机请求路由通告 | 延迟获取地址 |
| 路径 MTU 发现 | 确定最大传输单元 | 数据包被分片或丢弃 |
| 重定向 | 路由优化 | 路由次优 |
# ⚠️ 不要完全阻止 ICMPv6,这会导致 IPv6 网络瘫痪
# ❌ 错误做法
# ip6tables -A INPUT -p ipv6-icmp -j DROP
# ✅ 正确做法:允许必要的 ICMPv6 类型
13.3.2 ICMPv6 类型白名单
#!/bin/bash
# ═══════════════════════════════════════════════════
# ICMPv6 安全配置
# ═══════════════════════════════════════════════════
# 邻居请求(135)和邻居通告(136)- 必须允许
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type neighbor-solicitation -j ACCEPT
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type neighbor-advertisement -j ACCEPT
# 路由请求(133)和路由通告(134)- 如果不是路由器,可以限制
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type router-solicitation -j ACCEPT
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type router-advertisement \
-s fe80::/10 -j ACCEPT
# 回显请求(128)和回显回复(129)- ping
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type echo-request \
-m limit --limit 5/sec -j ACCEPT
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type echo-reply -j ACCEPT
# 目标不可达(1)- 路径 MTU 发现需要
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type destination-unreachable -j ACCEPT
# 数据包过大(2)- 路径 MTU 发现必须
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type packet-too-big -j ACCEPT
# 超时(3)
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type time-exceeded -j ACCEPT
# 参数问题(4)
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type parameter-problem -j ACCEPT
# 记录并丢弃其他 ICMPv6
ip6tables -A INPUT -p ipv6-icmp \
-m limit --limit 5/min \
-j LOG --log-prefix "ICMPV6-OTHER: "
ip6tables -A INPUT -p ipv6-icmp -j DROP
13.4 双栈服务器防火墙配置
13.4.1 统一防火墙脚本
#!/bin/bash
# ═══════════════════════════════════════════════════
# IPv4/IPv6 双栈防火墙配置
# ═══════════════════════════════════════════════════
# ─── 辅助函数 ───
apply_rules() {
local cmd=$1 # iptables 或 ip6tables
$cmd -F
$cmd -P INPUT DROP
$cmd -P FORWARD DROP
$cmd -P OUTPUT ACCEPT
# 已建立的连接
$cmd -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# 无效包
$cmd -A INPUT -m conntrack --ctstate INVALID -j DROP
# 回环接口
$cmd -A INPUT -i lo -j ACCEPT
# SSH
$cmd -A INPUT -p tcp --dport 22 \
-m hashlimit \
--hashlimit-above 4/minute \
--hashlimit-burst 4 \
--hashlimit-mode srcip \
--hashlimit-name ssh_${cmd} \
-j DROP
$cmd -A INPUT -p tcp --dport 22 \
-m connlimit --connlimit-above 3 -j DROP
$cmd -A INPUT -p tcp --dport 22 -j ACCEPT
# HTTP/HTTPS
$cmd -A INPUT -p tcp -m multiport --dports 80,443 \
-m hashlimit \
--hashlimit-above 30/sec \
--hashlimit-burst 60 \
--hashlimit-mode srcip \
--hashlimit-name web_${cmd} \
-j DROP
$cmd -A INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT
# 防端口扫描
$cmd -A INPUT -p tcp --tcp-flags ALL FIN,PSH,URG -j DROP
$cmd -A INPUT -p tcp --tcp-flags ALL NONE -j DROP
$cmd -A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
$cmd -A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
# 日志
$cmd -A INPUT \
-m limit --limit 10/min --limit-burst 30 \
-j LOG --log-prefix "${cmd}-DROP: "
}
# ─── 应用 IPv4 规则 ───
echo "Configuring iptables (IPv4)..."
apply_rules iptables
# ICMP(IPv4)
iptables -A INPUT -p icmp --icmp-type echo-request \
-m limit --limit 5/sec -j ACCEPT
# ─── 应用 IPv6 规则 ───
echo "Configuring ip6tables (IPv6)..."
apply_rules ip6tables
# ICMPv6(IPv6)
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type neighbor-solicitation -j ACCEPT
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type neighbor-advertisement -j ACCEPT
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type router-solicitation -j ACCEPT
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type router-advertisement \
-s fe80::/10 -j ACCEPT
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type echo-request \
-m limit --limit 5/sec -j ACCEPT
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type echo-reply -j ACCEPT
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type destination-unreachable -j ACCEPT
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type packet-too-big -j ACCEPT
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type time-exceeded -j ACCEPT
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type parameter-problem -j ACCEPT
ip6tables -A INPUT -p ipv6-icmp -j DROP
echo "Dual-stack firewall configured."
13.5 IPv6 特有安全问题
13.5.1 IPv6 隐私扩展
IPv6 的 SLAAC(无状态地址自动配置)会基于 MAC 地址生成接口标识符,导致设备隐私泄露。隐私扩展(Privacy Extensions)会生成随机的临时地址。
# 检查隐私扩展状态
cat /proc/sys/net/ipv6/conf/all/use_tempaddr
# 启用隐私扩展
# 0 = 禁用
# 1 = 启用(优先临时地址,但也使用固定地址)
# 2 = 启用(只使用临时地址)
sysctl -w net.ipv6.conf.all.use_tempaddr=2
sysctl -w net.ipv6.conf.default.use_tempaddr=2
# 持久化
echo "net.ipv6.conf.all.use_tempaddr = 2" >> /etc/sysctl.conf
echo "net.ipv6.conf.default.use_tempaddr = 2" >> /etc/sysctl.conf
13.5.2 IPv6 路由通告安全
# 防止恶意路由通告(RA 攻击)
# 只接受来自已知路由器的 RA
# 方法 1:ip6tables 过滤
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type router-advertisement \
-s fe80::1 -j ACCEPT # 只接受网关的 RA
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type router-advertisement -j DROP
# 方法 2:内核参数
sysctl -w net.ipv6.conf.all.accept_ra=0 # 完全禁用 RA
sysctl -w net.ipv6.conf.eth0.accept_ra=1 # 只接受来自默认网关的 RA
sysctl -w net.ipv6.conf.all.accept_ra_defrtr=1
sysctl -w net.ipv6.conf.all.accept_ra_pinfo=1
13.5.3 IPv6 隧道安全
IPv6 隧道(如 6to4、Teredo、ISATAP)可能被用于绕过 IPv4 防火墙:
# 如果不需要 IPv6 隧道,禁用它们
ip6tables -A INPUT -p 41 -j DROP # 6to4 隧道
ip6tables -A INPUT -p 4 -j DROP # IPv4 封装
# 禁用 IPv6 隧道内核模块
echo "install sit /bin/true" >> /etc/modprobe.d/disable-ipv6-tunnels.conf
echo "install ip6_tunnel /bin/true" >> /etc/modprobe.d/disable-ipv6-tunnels.conf
13.6 NAT 与 IPv6
13.6.1 IPv6 NAT 的现状
在 IPv6 中,NAT 不再是必需的(因为地址充足),但某些场景仍有需求:
| 场景 | 是否需要 NAT | 说明 |
|---|---|---|
| 地址转换 | 否 | IPv6 地址充足,不需要 NAT |
| 网络隐藏 | 可选 | 防火墙比 NAT 更好 |
| 负载均衡 | 可选 | 有 DNAT 的替代方案 |
| 地址重编号 | 可能 | 站点多宿主场景 |
13.6.2 IPv6 NAT 配置
# ip6tables 支持 IPv6 NAT(内核 ≥ 3.7)
# 需要加载 nf_nat_ipv6 模块
modprobe nf_nat_ipv6
# IPv6 DNAT
ip6tables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 \
-j DNAT --to-destination [2001:db8::10]:80
# IPv6 SNAT
ip6tables -t nat -A POSTROUTING -o eth0 -s 2001:db8:1::/48 \
-j SNAT --to-source 2001:db8::1
# IPv6 MASQUERADE
ip6tables -t nat -A POSTROUTING -o eth0 -s 2001:db8:1::/48 \
-j MASQUERADE
13.7 完整业务场景:Web 服务器双栈防火墙
#!/bin/bash
# ═══════════════════════════════════════════════════
# Web 服务器 IPv4/IPv6 双栈防火墙
# 环境:公网 Web 服务器,双栈接入
# ═══════════════════════════════════════════════════
# ─── 清空规则 ───
iptables -F && iptables -t nat -F && iptables -X
ip6tables -F && ip6tables -X
# ─── IPv4 规则 ───
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
iptables -A INPUT -i lo -j ACCEPT
# SSH(限管理网段)
iptables -A INPUT -p tcp --dport 22 -s 10.0.0.0/8 -j ACCEPT
# HTTP/HTTPS
iptables -A INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT
# ICMP
iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 5/s -j ACCEPT
# 防扫描
iptables -A INPUT -p tcp --tcp-flags ALL FIN,PSH,URG -j DROP
iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP
iptables -A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
iptables -A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
# NAT
iptables -t nat -A POSTROUTING -o eth0 -s 10.0.0.0/24 -j MASQUERADE
# ─── IPv6 规则 ───
ip6tables -P INPUT DROP
ip6tables -P FORWARD DROP
ip6tables -P OUTPUT ACCEPT
ip6tables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
ip6tables -A INPUT -m conntrack --ctstate INVALID -j DROP
ip6tables -A INPUT -i lo -j ACCEPT
# ICMPv6(必须允许关键类型)
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type neighbor-solicitation -j ACCEPT
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type neighbor-advertisement -j ACCEPT
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type router-advertisement -j ACCEPT
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type echo-request -m limit --limit 5/s -j ACCEPT
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type destination-unreachable -j ACCEPT
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type packet-too-big -j ACCEPT
ip6tables -A INPUT -p ipv6-icmp --icmpv6-type time-exceeded -j ACCEPT
ip6tables -A INPUT -p ipv6-icmp -j DROP
# SSH
ip6tables -A INPUT -p tcp --dport 22 -s 2001:db8:1::/48 -j ACCEPT
# HTTP/HTTPS
ip6tables -A INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT
# 防扫描
ip6tables -A INPUT -p tcp --tcp-flags ALL FIN,PSH,URG -j DROP
ip6tables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP
ip6tables -A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
# 日志
ip6tables -A INPUT -m limit --limit 10/min -j LOG --log-prefix "IP6-DROP: "
echo "Dual-stack firewall configured."
13.8 注意事项
⚠️ 不要阻止所有 ICMPv6:ICMPv6 对 IPv6 网络运行至关重要。阻止 ICMPv6 会导致邻居发现、路径 MTU 发现等功能失效,IPv6 网络将无法正常工作。
⚠️ IPv6 没有广播,只有多播:IPv6 使用多播代替广播,邻居发现使用多播地址(ff02::1, ff02::2 等)。
⚠️ 同时配置 iptables 和 ip6tables:防火墙脚本中应同时包含两套规则,避免 IPv6 成为安全盲区。
⚠️ 禁用不需要的 IPv6 功能:如果不需要 IPv6 隧道,应该禁用 6to4、Teredo 等隧道协议。
13.9 扩展阅读
| 资源 | 说明 |
|---|---|
| RFC 4890 - ICMPv6 Filtering | ICMPv6 过滤建议 |
man ip6tables | ip6tables 手册 |
| IPv6 Security (Scott Hogg) | IPv6 安全专著 |
| NIST SP 800-119 | IPv6 安全指南 |
本章小结
| 要点 | 说明 |
|---|---|
| ip6tables | 语法与 iptables 几乎相同 |
| ICMPv6 | 必须允许关键类型,否则 IPv6 网络瘫痪 |
| 双栈 | 同时配置 iptables 和 ip6tables |
| 隐私扩展 | 启用 use_tempaddr 保护隐私 |
| RA 安全 | 过滤恶意路由通告 |
| IPv6 隧道 | 不需要时应禁用 |
下一章:第 14 章:规则持久化,将学习如何使防火墙规则在重启后仍然生效。