网络流量控制的核心:规则、链与NAT
Linux防火墙基于netfilter内核框架,通过iptables或nftables用户态工具配置规则。理解防火墙是网络安全的必备技能——它控制着什么流量可以进出系统。
# 安装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个新连接视为扫描
# 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是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服务器防火墙脚本
#!/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!"