🧱 防火墙 — iptables与netfilter

网络流量控制的核心:规则、链与NAT

📖 Linux防火墙体系

Linux防火墙基于netfilter内核框架,通过iptables或nftables用户态工具配置规则。理解防火墙是网络安全的必备技能——它控制着什么流量可以进出系统。

Linux防火墙数据包处理流程 ┌──────────────┐ 网络接口 ──────→│ PREROUTING │←── DNAT/端口转发 └──────┬───────┘ │ ┌──────▼───────┐ │ 路由决策 │ └──┬───────┬──┘ │ │ 发往本机 │ │ 转发到其他主机 │ │ ┌──────▼──┐ ┌─▼──────────┐ │ INPUT │ │ FORWARD │ │ (入站过滤)│ │ (转发过滤) │ └──────┬──┘ └─┬──────────┘ │ │ ┌──────▼──┐ ┌─▼──────────┐ │ 本地进程 │ │ POSTROUTING │←── SNAT/MASQUERADE └──────┬──┘ └──────────────┘ │ ┌──────▼──┐ │ OUTPUT │ │ (出站过滤)│ └─────────┘

📋 iptables基础

# 安装iptables
apt install iptables    # Debian/Ubuntu
yum install iptables    # CentOS/RHEL

# 查看当前规则
iptables -L                    # 列出所有规则
iptables -L -n                 # 不解析域名(更快)
iptables -L -n -v              # 详细信息(包计数、字节计数)
iptables -L INPUT -n -v        # 只看INPUT链
iptables -L -n --line-numbers  # 显示规则编号

# 表和链
# filter表(默认): INPUT, FORWARD, OUTPUT
# nat表: PREROUTING, OUTPUT, POSTROUTING
# mangle表: 所有链
# raw表: PREROUTING, OUTPUT

# 查看nat表
iptables -t nat -L -n

基本规则操作

# 规则语法:
# iptables -A/-I 链名 匹配条件 -j 动作

# 动作(target):
# ACCEPT  → 允许通过
# DROP    → 丢弃(不回应,攻击者不知道被阻止)
# REJECT  → 拒绝(返回ICMP错误)
# LOG     → 记录日志
# DNAT    → 目标地址转换
# SNAT    → 源地址转换
# MASQUERADE → 动态源地址转换

# 允许SSH
iptables -A INPUT -p tcp --dport 22 -j ACCEPT

# 允许HTTP/HTTPS
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT

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

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

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

# 默认拒绝所有其他入站
iptables -A INPUT -j DROP

# 查看规则(验证)
iptables -L INPUT -n -v
# Chain INPUT (policy ACCEPT)
# target  prot opt source  destination
# ACCEPT  tcp  --  0.0.0.0/0  0.0.0.0/0  tcp dpt:22
# ACCEPT  tcp  --  0.0.0.0/0  0.0.0.0/0  tcp dpt:80
# ACCEPT  tcp  --  0.0.0.0/0  0.0.0.0/0  tcp dpt:443
# ACCEPT  all  --  0.0.0.0/0  0.0.0.0/0  lo
# ACCEPT  all  --  0.0.0.0/0  0.0.0.0/0  ctstate RELATED,ESTABLISHED
# DROP    all  --  0.0.0.0/0  0.0.0.0/0

🔧 高级规则配置

# 按来源IP过滤
iptables -A INPUT -s 192.168.1.0/24 -j ACCEPT     # 允许内网
iptables -A INPUT -s 10.0.0.0/8 -j ACCEPT          # 允许VPN
iptables -A INPUT -s 203.0.113.50 -j DROP          # 阻止恶意IP

# 按网络接口过滤
iptables -A INPUT -i eth0 -p tcp --dport 22 -j ACCEPT   # 只在eth0允许SSH
iptables -A INPUT -i eth1 -j DROP                         # eth1拒绝所有

# 多端口匹配
iptables -A INPUT -p tcp -m multiport --dports 80,443,8080 -j ACCEPT

# 连接速率限制(防暴力破解/DoS)
iptables -A INPUT -p tcp --dport 22 \
  -m conntrack --ctstate NEW \
  -m recent --set --name ssh
iptables -A INPUT -p tcp --dport 22 \
  -m conntrack --ctstate NEW \
  -m recent --update --seconds 60 --hitcount 4 --name ssh \
  -j DROP
# 60秒内超过3次新连接则DROP

# 限制ICMP速率
iptables -A INPUT -p icmp --icmp-type echo-request \
  -m limit --limit 1/s --limit-burst 4 -j ACCEPT
iptables -A INPUT -p icmp --icmp-type echo-request -j DROP

# SYN Flood防护
iptables -A INPUT -p tcp --syn -m limit --limit 1/s --limit-burst 3 -j ACCEPT
iptables -A INPUT -p tcp --syn -j DROP

# 端口扫描检测
iptables -A INPUT -m conntrack --ctstate NEW -p tcp \
  -m recent --set --name portscan
iptables -A INPUT -m conntrack --ctstate NEW -p tcp \
  -m recent --update --seconds 60 --hitcount 20 --name portscan \
  -j DROP
# 60秒内超过20个新连接视为扫描

🌐 NAT配置

# SNAT (源地址转换) — 内网共享上网
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
# 适用于动态IP(拨号、DHCP)

iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to-source 203.0.113.1
# 适用于固定IP

# DNAT (目标地址转换) — 端口转发
# 将外部80端口转发到内网Web服务器
iptables -t nat -A PREROUTING -p tcp --dport 80 \
  -j DNAT --to-destination 192.168.1.10:80

# 将外部2222转发到内网SSH
iptables -t nat -A PREROUTING -p tcp --dport 2222 \
  -j DNAT --to-destination 192.168.1.20:22

# 需要开启IP转发
echo 1 > /proc/sys/net/ipv4/ip_forward
# 永久生效:
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
sysctl -p

# 透明代理
iptables -t nat -A PREROUTING -p tcp --dport 80 \
  -j DNAT --to-destination 127.0.0.1:3128
# 将所有HTTP流量重定向到本地代理

💾 规则持久化

# 保存规则
iptables-save > /etc/iptables/rules.v4
ip6tables-save > /etc/iptables/rules.v6

# 恢复规则
iptables-restore < /etc/iptables/rules.v4

# 自动加载(Debian/Ubuntu)
apt install iptables-persistent
# 安装时自动保存当前规则
# 之后修改规则后运行:
netfilter-persistent save

# CentOS/RHEL
yum install iptables-services
systemctl enable iptables
service iptables save

# 使用iptables-persistent的替代方案
# 在/etc/rc.local中添加:
/sbin/iptables-restore < /etc/iptables/rules.v4

🔄 nftables(iptables的继任者)

# nftables是Linux内核新的包过滤框架
# 相比iptables更高效、语法更简洁

# 查看规则
nft list ruleset

# 创建表
nft add table inet firewall

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

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

# 查看规则
nft list table inet firewall

# 删除规则
nft delete rule inet firewall input handle 3

# 配置文件 /etc/nftables.conf
#!/usr/sbin/nft -f
table inet firewall {
  chain input {
    type filter hook input priority 0; policy drop;
    ct state established,related accept
    iif lo accept
    tcp dport { 22, 80, 443 } accept
    icmp type echo-request limit rate 1/second accept
  }
  chain forward {
    type filter hook forward priority 0; policy drop;
  }
  chain output {
    type filter hook output priority 0; policy accept;
  }
}

# 启用nftables
systemctl enable nftables
systemctl start nftables

🏗️ Web服务器防火墙配置示例

# 完整的Web服务器防火墙脚本
#!/bin/bash

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

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

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

# 2. 允许已建立的连接
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# 3. 允许SSH(限制速率)
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW \
  -m recent --set --name ssh
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW \
  -m recent --update --seconds 60 --hitcount 4 --name ssh -j DROP
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT

# 4. 允许HTTP/HTTPS
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT

# 5. 允许ICMP
iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 1/s -j ACCEPT

# 6. 记录被拒绝的包
iptables -A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables-DROP: " --log-level 4

# 7. 拒绝所有其他入站
iptables -A INPUT -j DROP

# 保存规则
iptables-save > /etc/iptables/rules.v4
echo "Firewall configured successfully!"
防火墙 — 你已掌握iptables/nftables规则配置、NAT端口转发、速率限制防DoS和规则持久化!
命令已验证:iptables -A/-L/-D/-t nat/MASQUERADE — 所有命令在Docker沙箱(--cap-add=NET_ADMIN)验证通过
课后思考题:
  1. DROP和REJECT的区别是什么?在什么场景下应该用哪个?
  2. 为什么防火墙规则中"允许已建立连接"的规则应该放在最前面?
  3. iptables的conntrack模块有什么作用?为什么有状态防火墙比无状态防火墙更安全?
  4. nftables相比iptables有哪些改进?为什么Linux要替换iptables?

📚 进阶资源

参考资料:iptables(8) | nft(8) | netfilter.org | Linux Kernel Networking | RFC 3022 (NAT)