深色模式
防火墙实战:iptables 与 nftables 默认拒绝策略
摘要:主机防火墙的核心不是写多少条放行规则,而是把默认策略设成拒绝(drop),再逐条加白名单。本文分别给出 nftables(新系统推荐)与 iptables(老系统)的可复制配置,并把"别把自己关在外面"写进每一步。
适用环境
bash
cat /etc/os-release
command -v nft && nft --version
command -v iptables && iptables --version
command -v firewall-cmd && firewall-cmd --version # 若用 firewalld 就不要手改 nft
systemctl is-active firewalld 2>/dev/null1
2
3
4
5
2
3
4
5
不要多套防火墙工具混用
firewalld / ufw / 手写 nft 规则会互相覆盖。先确认哪一个是实际生效的管理器,只维护一套。
操作步骤
1. 清点现有规则,找出口子
bash
nft list ruleset 2>/dev/null | head -50
iptables -S 2>/dev/null | head -50
ss -lntup # 有哪些服务在监听1
2
3
2
3
2. 先给自己留后路
直接设默认 drop 会让所有新连接中断,包括你正在用的 SSH
务必事先放通 SSH 端口,并用 --handle/编号方式预留删除手段;远程操作建议配合 at 定时回滚。
bash
# 10 分钟后自动恢复放行,作为保险(nftables 场景)
echo "nft flush ruleset" | at now + 10 minutes 2>/dev/null || echo "请先安装 at 或手动设好回滚"1
2
2
3. nftables:新建带默认 drop 的基础表
bash
nft add table inet filter
nft add chain inet filter input '{ type filter hook input priority 0; policy drop; }'
nft add chain inet filter forward '{ type filter hook forward priority 0; policy drop; }'
nft add chain inet filter output '{ type filter hook output priority 0; policy accept; }'
# 基础放行
nft add rule inet filter input iif lo accept
nft add rule inet filter input ct state established,related accept
nft add rule inet filter input ct state invalid drop
nft add rule inet filter input icmp type echo-request limit rate 5/second accept
# 业务放行(按需增删)
nft add rule inet filter input tcp dport 2222 accept # SSH
nft add rule inet filter input tcp dport {80, 443} accept1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
4. nftables:持久化
bash
nft list ruleset > /etc/nftables.conf
systemctl enable --now nftables # Debian/Ubuntu/RHEL9+1
2
2
5. iptables 老系统:等价写法
bash
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
iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
iptables -A INPUT -p tcp --dport 2222 -j ACCEPT
iptables -A INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT
iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 5/s -j ACCEPT1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
持久化:
bash
# RHEL/CentOS
dnf install -y iptables-services && service iptables save && systemctl enable iptables
# Debian/Ubuntu
apt-get install -y iptables-persistent && netfilter-persistent save1
2
3
4
2
3
4
6. 限制单 IP 连接数,缓解扫描与爆破
bash
nft add rule inet filter input tcp dport 2222 ct state new \
meter ssh-meter { ip saddr limit rate 10/minute } accept1
2
2
7. 不要放过 IPv6
bash
ip6tables -P INPUT DROP 2>/dev/null
ip6tables -A INPUT -i lo -j ACCEPT 2>/dev/null
ip6tables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT 2>/dev/null
ip6tables -A INPUT -p tcp --dport 2222 -j ACCEPT 2>/dev/null1
2
3
4
2
3
4
很多机器 IPv6 是通的但没人管,等于防火墙被绕过。
验证
bash
nft list ruleset | grep -E 'policy|dport'
iptables -L INPUT -n -v --line-numbers 2>/dev/null | head -20
# 从另一台机器验证:应通
nc -zv server 443
# 应被静默丢弃(超时)
nc -zv -w 3 server 80801
2
3
4
5
6
2
3
4
5
6
判定标准:白名单端口通,其它端口超时(不是 connection refused,说明是 drop);重启后规则仍在。
常见坑
默认策略设成 DROP 却没放通 SSH,直接失联
先放通、后改默认;远程操作必须有回滚手段或带外控制台。
用 iptables -F 清空规则当"临时调试"
默认策略若是 ACCEPT 还好,若是 DROP,-F 之后所有链策略仍为 DROP,等于全断。先 -P INPUT ACCEPT 再 flush。
只配 IPv4 忘了 IPv6
ss -lntup 里能看到 tcp6 监听就说明必须同步配 ip6tables 或 nft inet 族(inet 族会同时覆盖 v4/v6,推荐)。
firewalld 与手写 nft 冲突
两者都写 nftables 规则集,firewalld reload 会覆盖你的手改规则。选定一个管理器,另一个彻底停用。
出站全放行导致反弹 Shell 成功
高安全场景应同时收紧 OUTPUT 与 FORWARD,或至少对出站做日志与限速。