iptables 在哪一层

应用前端:ufw / firewalld(高层封装)
              ↓ 生成规则
iptables(用户态工具)
              ↓ 操作
netfilter(内核里的钩子)

新 Linux 内核也支持 nftables(iptables 接班人)—— 但 iptables 命令仍然广泛使用,多数发行版默认兼容。

概念:表 / 链 / 规则

表 (table):filter / nat / mangle / raw
  ↓ 内含多个
链 (chain):INPUT / OUTPUT / FORWARD / PREROUTING / POSTROUTING
  ↓ 内含多条
规则 (rule):匹配条件 + 动作

最常用:filter 表(包过滤),关心三条链:

  • INPUT — 入站到本机
  • OUTPUT — 本机出站
  • FORWARD — 经本机转发(路由器场景)

看现有规则

sudo iptables -L -n -v
sudo iptables -L INPUT -n -v --line-numbers

-n 不解析名字(更快);-v 显示包数 / 字节数。

基础规则

# 允许已建立的连接(保留正在用的)
sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# 允许回环(本机自己通信)
sudo iptables -A INPUT -i lo -j ACCEPT

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

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

# 限制 SSH 暴破(每 IP 每分钟 4 次新连接)
sudo iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW \
    -m recent --set --name SSH
sudo iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW \
    -m recent --update --seconds 60 --hitcount 4 --name SSH -j DROP

# 默认丢弃入站
sudo iptables -P INPUT DROP
sudo iptables -P FORWARD DROP

# 出站不限
sudo iptables -P OUTPUT ACCEPT

改 INPUT 默认策略前先确认 SSH 已允许——否则你下一秒就 SSH 失联。强烈建议在 KVM / VNC 能进的机器上练

常用动作

动作 含义
ACCEPT 放行
DROP 默默丢(对方等超时)
REJECT 主动拒绝(返回 RST 或 ICMP)
LOG 记日志(之后规则继续)
RETURN 跳出当前链
<chain> 跳到自定义链

DROP vs REJECT

  • DROP:对外看像"机器不在",扫描者不知道有没机器
  • REJECT:明确告诉"被拒"

服务器一般 DROP;交互式调试可以 REJECT。

看规则匹配的包数

sudo iptables -L INPUT -n -v --line-numbers
# Chain INPUT (policy DROP 0 packets, 0 bytes)
# num   pkts bytes target     prot opt in     out     source        destination
# 1     1234  5678 ACCEPT     tcp  --  *      *       0.0.0.0/0     0.0.0.0/0    tcp dpt:22

pkts / bytes 显示规则的命中次数——0 的规则可能是没用上 / 顺序不对。

删除规则

# 按行号
sudo iptables -D INPUT 3

# 完整命令(必须和加规则时完全一致)
sudo iptables -D INPUT -p tcp --dport 22 -j ACCEPT

持久化

iptables 规则重启就丢——必须持久化。

# Debian/Ubuntu
sudo apt install iptables-persistent
sudo netfilter-persistent save

# RHEL/CentOS
sudo systemctl enable iptables
sudo service iptables save

或手动:

sudo iptables-save > /etc/iptables/rules.v4
# 开机时
sudo iptables-restore < /etc/iptables/rules.v4

NAT 配置(路由场景)

让内网机器经本机出公网:

# 1. 开启内核转发
sudo sysctl -w net.ipv4.ip_forward=1
# 永久:写进 /etc/sysctl.conf

# 2. NAT 出方向
sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

# 3. 允许 FORWARD
sudo iptables -A FORWARD -i eth0 -o eth1 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
sudo iptables -A FORWARD -i eth1 -o eth0 -j ACCEPT

端口转发

把入站 8080 转到 192.168.1.50:80:

sudo iptables -t nat -A PREROUTING -p tcp --dport 8080 -j DNAT --to 192.168.1.50:80
sudo iptables -A FORWARD -p tcp -d 192.168.1.50 --dport 80 -j ACCEPT

一份生产级模板

#!/bin/bash
set -e

# 清空
iptables -F
iptables -X

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

# 已建立
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# 回环
iptables -A INPUT -i lo -j ACCEPT

# 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 --rttl --name SSH -j DROP
iptables -A INPUT -p tcp --dport 22 -j ACCEPT

# Web
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT

# ICMP(ping)
iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 5/second -j ACCEPT

# 拒绝其他都 LOG 再 DROP
iptables -A INPUT -j LOG --log-prefix "iptables-dropped: "
iptables -A INPUT -j DROP

# 保存
iptables-save > /etc/iptables/rules.v4

下一篇:SELinux 基础。