🛡️ 第14课:防火墙(iptables/nftables)

阶段三:网络配置第2/6课

📚 课程目标

一、Netfilter框架

数据包进入 → PREROUTING → 路由判断 → FORWARD → POSTROUTING → 离开
                │                        │           │
                └──→ INPUT → 本地进程 → OUTPUT ──┘

1.1 iptables五链

挂载点用途
PREROUTING路由前DNAT、路由判断
INPUT进入本机过滤到达本机的包
FORWARD转发过滤转发的包
OUTPUT本机发出过滤本机发出的包
POSTROUTING路由后SNAT

1.2 iptables四表

功能可用链
filter过滤(默认表)INPUT/FORWARD/OUTPUT
nat地址转换PREROUTING/OUTPUT/POSTROUTING
mangle包修改全部五链
raw连接追踪豁免PREROUTING/OUTPUT

二、iptables规则管理

$ sudo iptables -L -n | head -20
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
YJ-FIREWALL-INPUT  0    --  0.0.0.0/0            0.0.0.0/0           

Chain FORWARD (policy DROP)
target     prot opt source               destination         
DOCKER-USER  0    --  0.0.0.0/0            0.0.0.0/0           
DOCKER-FORWARD  0    --  0.0.0.0/0            0.0.0.0/0           

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         

Chain DOCKER (2 references)
target     prot opt source               destination         
ACCEPT     6    --  0.0.0.0/0            172.18.0.2           tcp dpt:80
DROP       0    --  0.0.0.0/0            0.0.0.0/0           
DROP       0    --  0.0.0.0/0            0.0.0.0/0           

Chain DOCKER-BRIDGE (1 references)
target     prot opt source               destination
# 查看规则
sudo iptables -L -n -v           # 详细信息
sudo iptables -L -n --line-numbers  # 显示行号

# 添加规则
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT    # 允许SSH
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT    # 允许HTTP
sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT   # 允许HTTPS
sudo iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
sudo iptables -A INPUT -j DROP                         # 默认拒绝

# 插入规则(指定位置)
sudo iptables -I INPUT 1 -s 10.0.0.0/8 -j ACCEPT

# 删除规则
sudo iptables -D INPUT -p tcp --dport 22 -j ACCEPT    # 按规则删除
sudo iptables -D INPUT 1                                # 按行号删除

# 清空所有规则
sudo iptables -F

# 设置默认策略
sudo iptables -P INPUT DROP
sudo iptables -P FORWARD DROP
sudo iptables -P OUTPUT ACCEPT

三、NAT地址转换

# SNAT (源地址转换,内网访问外网)
sudo iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth0 -j MASQUERADE

# DNAT (目的地址转换,外网访问内网)
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 192.168.1.10:80

# 开启IP转发
echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.conf

四、nftables(iptables替代)

$ sudo nft list ruleset | head -20
table ip nat {
	chain DOCKER {
		iifname != "br-0ce8d170b79f" tcp dport 8080 counter packets 0 bytes 0 dnat to 172.18.0.2:80
	}

	chain PREROUTING {
		type nat hook prerouting priority dstnat; policy accept;
		fib daddr type local counter packets 60631 bytes 2137922 jump DOCKER
	}

	chain OUTPUT {
		type nat hook output priority dstnat; policy accept;
		ip daddr != 127.0.0.0/8 fib daddr type local counter packets 0 bytes 0 jump DOCKER
	}

	chain POSTROUTING {
		type nat hook postrouting priority srcnat; policy accept;
		ip saddr 172.17.0.0/16 oifname != "docker0" counter packets 47 bytes 3017 masquerade
		ip saddr 172.18.0.0/16 oifname != "br-0ce8d170b79f" counter packets 0 bytes 0 masquerade
	}
# nftables优势:
# - 更简洁的语法
# - 更好的性能(合并规则)
# - 统一的IPv4/IPv6处理
# - 原子性规则更新

# 创建表
sudo nft add table inet myfirewall

# 创建链
sudo nft add chain inet myfirewall input { type filter hook input priority 0 \; policy drop \; }

# 添加规则
sudo nft add rule inet myfirewall input tcp dport 22 accept
sudo nft add rule inet myfirewall input tcp dport { 80, 443 } accept
sudo nft add rule inet myfirewall input ct state established,related accept

# 列出规则
sudo nft list table inet myfirewall

五、UFW(Ubuntu简化防火墙)

$ sudo ufw status
Status: inactive
# 启用UFW
sudo ufw enable

# 允许/拒绝服务
sudo ufw allow ssh
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw deny 3306

# 限制连接速率
sudo ufw limit ssh

# 允许特定IP
sudo ufw allow from 10.0.0.0/8
sudo ufw allow from 192.168.1.100 to any port 22

# 查看规则
sudo ufw status numbered

# 删除规则
sudo ufw delete 2

# 重置
sudo ufw reset

六、firewalld(RHEL/CentOS)

# 查看状态
sudo firewall-cmd --state

# 查看开放的服务
sudo firewall-cmd --list-all

# 开放端口
sudo firewall-cmd --add-port=8080/tcp --permanent
sudo firewall-cmd --add-service=http --permanent
sudo firewall-cmd --reload

# 查看区域
sudo firewall-cmd --get-zones
sudo firewall-cmd --get-default-zone

七、防火墙安全策略

📋 最小权限原则

  1. 默认拒绝所有入站流量(Policy DROP)
  2. 仅开放必要端口
  3. 限制源IP范围
  4. 使用连接状态追踪
  5. 记录被拒绝的包
  6. 定期审计规则
# 安全基线脚本
sudo iptables -F
sudo iptables -X
sudo iptables -P INPUT DROP
sudo iptables -P FORWARD DROP
sudo iptables -P OUTPUT ACCEPT
sudo iptables -A INPUT -i lo -j ACCEPT
sudo iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT
sudo iptables -A INPUT -j LOG --log-prefix "IPTables-Dropped: "

# 持久化
sudo apt install iptables-persistent
sudo netfilter-persistent save

八、练习

📝 防火墙配置实战

# 1. 查看当前防火墙规则
sudo iptables -L -n -v

# 2. 使用UFW配置安全策略
sudo ufw enable
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw allow http
sudo ufw allow https

# 3. 验证
sudo ufw status verbose
🏆

成就解锁:防火墙卫士

✅ 理解Netfilter框架

✅ 掌握iptables规则管理

✅ 了解NAT地址转换

✅ 学会nftables和UFW

✅ 掌握防火墙安全策略

九、连接追踪(conntrack)

Netfilter的连接追踪功能是状态防火墙的基础,记录每个连接的状态。

# 查看连接追踪表
sudo conntrack -L | head -20
sudo conntrack -C     # 连接数统计

# 修改最大连接数
sudo sysctl -w net.netfilter.nf_conntrack_max=655360

# 查看当前连接数
sudo sysctl net.netfilter.nf_conntrack_count

# 连接追踪状态
# NEW: 新连接
# ESTABLISHED: 已建立
# RELATED: 关联连接(如FTP数据连接)
# INVALID: 无效包

十、防火墙日志分析

# 记录被拒绝的包
sudo iptables -A INPUT -j LOG --log-prefix "IPTABLES-DROP: " --log-level 4
sudo iptables -A INPUT -j DROP

# 分析防火墙日志
grep "IPTABLES-DROP" /var/log/syslog | tail -20
grep "IPTABLES-DROP" /var/log/kern.log | awk '{print $1,$2,$3,$NF}' | sort | uniq -c | sort -rn | head -10

# 使用ulogd替代LOG(性能更好)
sudo apt install ulogd2

十一、云环境安全组

云服务器(AWS/阿里云/腾讯云)使用安全组(Security Group)替代传统防火墙。安全组在虚拟化层实现,优先于iptables。

云环境中,安全组和iptables同时生效——流量必须两者都允许才能通过。调试时注意两层都要检查。

十二、iptables持久化与脚本化

# 方法1:iptables-persistent (Debian/Ubuntu)
sudo apt install iptables-persistent
sudo netfilter-persistent save    # 保存当前规则
sudo netfilter-persistent reload  # 重载规则

# 方法2:iptables-services (RHEL/CentOS)
sudo yum install iptables-services
sudo service iptables save        # 保存到 /etc/sysconfig/iptables

# 方法3:自写脚本
#!/bin/bash
# /etc/network/if-pre-up.d/iptables
#!/bin/bash
/sbin/iptables-restore < /etc/iptables/rules.v4
/sbin/ip6tables-restore < /etc/iptables/rules.v6

# 导出/导入规则
sudo iptables-save > /tmp/iptables-backup.txt
sudo iptables-restore < /tmp/iptables-backup.txt

十三、容器网络与防火墙

# Docker修改iptables规则
# Docker自动添加NAT和FORWARD规则
sudo iptables -t nat -L -n | grep DOCKER
sudo iptables -L DOCKER -n

# 注意:Docker的FORWARD策略是ACCEPT,可能绕过防火墙
# 安全建议:在DOCKER-USER链中添加规则
sudo iptables -I DOCKER-USER -s 10.0.0.0/8 -j ACCEPT
sudo iptables -I DOCKER-USER -j DROP

十四、防火墙规则自动化

#!/bin/bash
# firewall-setup.sh - 自动化防火墙配置
# 适用于新服务器初始化

set -euo pipefail

# 定义允许的服务
ALLOWED_TCP_PORTS="22 80 443"
ALLOWED_UDP_PORTS=""
TRUSTED_NETWORKS="10.0.0.0/8 192.168.0.0/16"

echo "配置防火墙..."

# 清空现有规则
iptables -F
iptables -X
iptables -t nat -F
iptables -t mangle -F

# 设置默认策略
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT

# 允许回环接口
iptables -A INPUT -i lo -j ACCEPT

# 允许已建立的连接
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# 允许ICMP(ping)
iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT

# 允许信任网络
for net in $TRUSTED_NETWORKS; do
    iptables -A INPUT -s $net -j ACCEPT
done

# 允许指定TCP端口
for port in $ALLOWED_TCP_PORTS; do
    iptables -A INPUT -p tcp --dport $port -j ACCEPT
    echo "  允许 TCP/$port"
done

# 允许指定UDP端口
for port in $ALLOWED_UDP_PORTS; do
    iptables -A INPUT -p udp --dport $port -j ACCEPT
    echo "  允许 UDP/$port"
done

# 记录拒绝的包
iptables -A INPUT -j LOG --log-prefix "FW-DROP: " --log-level 4

echo "防火墙配置完成"
iptables -L -n --line-numbers