第一次接触iptables是在2013年维护公司的一台CentOS服务器时。当时服务器频繁遭受端口扫描攻击,运维主管只用了几条iptables命令就构建起了防护墙。从那时起,我就意识到这个看似简单的工具蕴含着巨大的能量。
iptables是Linux内核集成的包过滤系统,它就像网络流量的交通警察,能够根据预设规则对进出系统的数据包进行精细控制。不同于防火墙硬件设备,iptables直接运行在内核空间,处理效率极高。根据2022年W3Techs的统计,全球79%的Web服务器运行在Linux系统上,这意味着掌握iptables几乎是服务器管理员的必备技能。
提示:即使你使用firewalld或ufw等前端工具,它们底层仍然依赖iptables/nftables。理解iptables的工作原理能让你在复杂网络环境中游刃有余。
iptables的核心设计可以概括为"四表五链"。初次接触时这个概念可能令人困惑,但理解它就像理解快递分拣系统:
五个内置链对应数据包的生命周期节点:
当一个数据包到达系统时,iptables会按照特定顺序检查各个表和链。这个过程就像快递通过多层检查:
这个流程中,一旦某个规则匹配成功,就会执行对应的动作(ACCEPT/DROP等),后续规则不再检查。理解这个顺序对正确配置规则至关重要。
iptables命令的基本格式如下:
bash复制iptables [-t 表名] 命令选项 链名 匹配条件 -j 目标动作
常用命令选项:
-A:追加规则(最常用)-I:插入规则(可指定位置)-D:删除规则-L:列出规则-F:清空链一个简单的允许SSH连接示例:
bash复制iptables -A INPUT -p tcp --dport 22 -j ACCEPT
以下是我在服务器上实际使用的基准规则模板:
bash复制# 清空所有规则
iptables -F
iptables -X
# 设置默认策略(默认拒绝所有)
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
# 允许本地回环
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
# 允许已建立的连接
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# 允许SSH(限制尝试次数)
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -m recent --set
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -m recent --update --seconds 60 --hitcount 4 -j DROP
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
# 允许Ping(限速)
iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 1/s -j ACCEPT
注意:应用新规则前,务必确保有另外的终端连接,或者设置默认策略为ACCEPT测试后再改为DROP,否则可能立即失去服务器连接。
iptables的强大之处在于其丰富的匹配扩展:
bash复制iptables -A INPUT -p tcp -m multiport --dports 22,80,443 -j ACCEPT
bash复制iptables -A INPUT -m iprange --src-range 192.168.1.100-192.168.1.200 -j DROP
bash复制iptables -A INPUT -p tcp -m conntrack --ctstate INVALID -j DROP
bash复制iptables -A INPUT -p tcp --dport 80 -m string --string "SELECT * FROM" --algo bm -j DROP
bash复制iptables -A INPUT -p tcp --dport 22 -m time --timestart 09:00 --timestop 18:00 --weekdays Mon,Tue,Wed,Thu,Fri -j ACCEPT
假设你的Linux服务器有两个网卡:
让内网机器通过服务器上网的配置:
bash复制# 启用IP转发
echo 1 > /proc/sys/net/ipv4/ip_forward
# 设置SNAT规则
iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to-source 203.0.113.1
# 或者使用MASQUERADE(动态IP适用)
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
将公网IP的8080端口映射到内网192.168.1.100的80端口:
bash复制iptables -t nat -A PREROUTING -p tcp --dport 8080 -j DNAT --to-destination 192.168.1.100:80
iptables -t nat -A POSTROUTING -p tcp -d 192.168.1.100 --dport 80 -j SNAT --to-source 192.168.1.1
以下是一个企业级NAT网关的完整配置示例:
bash复制# 启用转发
sysctl -w net.ipv4.ip_forward=1
# 清空规则
iptables -F
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 conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# NAT配置
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
# 允许内网访问外网
iptables -A FORWARD -i eth1 -o eth0 -j ACCEPT
# 允许外网返回的数据
iptables -A FORWARD -i eth0 -o eth1 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# 特定端口映射(Web服务器)
iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 192.168.1.100:80
iptables -A FORWARD -p tcp -d 192.168.1.100 --dport 80 -j ACCEPT
高频规则前置:
将匹配频率高的规则放在链的前面。例如,对Web服务器应该把80/443端口的规则放在前面。
使用ipset管理大批量IP:
当需要屏蔽成百上千个IP时,ipset比直接写在iptables中更高效:
bash复制# 创建ipset
ipset create blacklist hash:ip
# 添加IP到集合
ipset add blacklist 192.168.1.100
# 在iptables中引用
iptables -A INPUT -m set --match-set blacklist src -j DROP
bash复制iptables -A INPUT -p tcp --dport 80 -m connlimit --connlimit-above 50 -j DROP
bash复制iptables -N LOGGING
iptables -A INPUT -j LOGGING
iptables -A LOGGING -m limit --limit 2/min -j LOG --log-prefix "IPTables-Dropped: " --log-level 4
iptables -A LOGGING -j DROP
bash复制# 查看规则命中计数
iptables -L -v -n
# 查看NAT表状态
iptables -t nat -L -v -n
bash复制iptables-save > /etc/iptables.rules
bash复制iptables-restore < /etc/iptables.rules
bash复制apt install iptables-persistent
netfilter-persistent save
iptables -L -n --line-numbersiptables -Ssysctl net.ipv4.ip_forwardconntrack -Llsmod | grep xt_问题1:内网机器可以ping通外网但无法上网
iptables -L FORWARD -v -n问题2:端口映射后外网无法访问
iptables -t nat -L PREROUTING -n -v连接跟踪表满会导致新连接被丢弃,表现为随机连接失败:
bash复制# 查看当前连接数
cat /proc/sys/net/netfilter/nf_conntrack_count
# 查看最大连接数
cat /proc/sys/net/netfilter/nf_conntrack_max
# 临时增加限制
echo 524288 > /proc/sys/net/netfilter/nf_conntrack_max
虽然iptables仍然广泛使用,但它的后继者nftables已经逐渐成为主流。两者主要区别:
一个简单的nftables配置示例:
bash复制# 清空现有规则
nft flush ruleset
# 创建filter表
nft add table ip filter
# 创建input链
nft add chain ip filter input { type filter hook input priority 0 \; }
# 添加规则(允许SSH)
nft add rule ip filter input tcp dport 22 accept
迁移工具iptables-translate可以帮助转换现有规则:
bash复制iptables-translate -A INPUT -p tcp --dport 22 -j ACCEPT
# 输出:nft add rule ip filter input tcp dport 22 accept
在实际生产环境中,我建议先使用nftables的iptables兼容模式运行:
bash复制iptables-nft -A INPUT -p tcp --dport 80 -j ACCEPT
这样可以在保持现有iptables规则的同时,逐步熟悉nftables的新特性。