iptables 防火墙
iptables 是 Linux 最经典的防火墙工具,用来控制网络数据包的进出。白话说就是"给服务器装一道门,决定谁能进、谁能出、谁被挡在外面"。
核心知识点
| 概念 | 说明 |
|---|
| 表(table) | 按功能分组的规则集合:filter(过滤)、nat(地址转换)、mangle(修改包) |
| 链(chain) | 数据包经过的检查点:INPUT(进来)、OUTPUT(出去)、FORWARD(转发) |
| 规则(rule) | 具体的匹配条件 + 动作(接受/拒绝/丢弃) |
| ACCEPT | 允许数据包通过 |
| DROP | 丢弃数据包(不回应,对方不知道被拒绝了) |
| REJECT | 拒绝数据包(回应"不行",对方知道被拒绝了) |
| 默认策略 | 不匹配任何规则时的默认处理(建议 DROP) |
数据包流向:
外部 → INPUT 链 → 本机应用(进来的流量)
本机应用 → OUTPUT 链 → 外部(出去的流量)
外部A → FORWARD 链 → 外部B(转发流量,路由器场景)
安装配置
# iptables 是 Linux 内核自带的,通常已预装
which iptables # 确认命令存在
# Ubuntu/Debian 安装持久化工具
sudo apt install iptables-persistent # 让规则重启后不丢失
# CentOS 7+ 使用 firewalld,如果想用 iptables:
sudo systemctl stop firewalld # 停止 firewalld
sudo systemctl disable firewalld # 禁用 firewalld
sudo yum install iptables-services # 安装 iptables 服务
sudo systemctl enable iptables # 启用 iptables
sudo systemctl start iptables # 启动 iptables
基本使用
查看当前规则
# 查看所有规则(最常用)
sudo iptables -L -n -v # -L 列出 -n 不解析域名 -v 详细模式
# 查看规则并显示行号(方便删除)
sudo iptables -L --line-numbers # 每条规则前面加编号
# 查看 NAT 表的规则
sudo iptables -t nat -L -n -v # -t nat 指定 NAT 表
添加规则
# 允许 SSH 连接(端口 22)
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# -A INPUT 追加规则到 INPUT 链
# -p tcp 协议为 TCP
# --dport 22 目标端口 22
# -j ACCEPT 动作:允许通过
# 允许 HTTP 和 HTTPS
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT # 允许 HTTP
sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT # 允许 HTTPS
# 允许 ping(ICMP)
sudo iptables -A INPUT -p icmp -j ACCEPT # 允许 ping 请求
# 允许已建立连接的回包(重要!不加这条很多东西会断)
sudo iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# 已建立连接和相关连接的包都允许
# 允许本地回环(localhost)
sudo iptables -A INPUT -i lo -j ACCEPT # -i lo 指定回环网卡
# 拒绝所有其他入站流量(放在最后)
sudo iptables -A INPUT -j DROP # 不匹配前面规则的全部丢弃
删除规则
# 按行号删除
sudo iptables -L --line-numbers # 先看行号
sudo iptables -D INPUT 3 # 删除 INPUT 链的第 3 条规则
# 按规则内容删除
sudo iptables -D INPUT -p tcp --dport 80 -j ACCEPT # 删除允许 80 端口的规则
# 清空所有规则(危险!确保有其他方式连接服务器)
sudo iptables -F # 清空所有链的规则
高级用法
限制 IP 访问
# 允许指定 IP 访问
sudo iptables -A INPUT -s 192.168.1.100 -j ACCEPT # 只允许这个 IP
# 拒绝指定 IP
sudo iptables -A INPUT -s 10.0.0.50 -j DROP # 丢弃这个 IP 的所有包
# 允许指定网段
sudo iptables -A INPUT -s 192.168.1.0/24 -j ACCEPT # 允许整个子网
# 只允许指定 IP 访问 SSH
sudo iptables -A INPUT -p tcp --dport 22 -s 192.168.1.0/24 -j ACCEPT
# 只有 192.168.1.x 网段能 SSH
端口转发(NAT)
# 开启内核转发
echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward # 临时开启
# 永久开启:编辑 /etc/sysctl.conf 加入 net.ipv4.ip_forward=1
# 端口转发:外部访问 8080 转到内部 80
sudo iptables -t nat -A PREROUTING -p tcp --dport 8080 -j REDIRECT --to-port 80
# 访问本机 8080 端口时,自动转到 80 端口
# DNAT:转发到另一台机器
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 192.168.1.10:80
# 外部访问本机 80 端口,转发到 192.168.1.10 的 80 端口
# SNAT:内网机器通过本机上网
sudo iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth0 -j MASQUERADE
# 192.168.1.x 网段通过 eth0 网卡上网(动态 IP 用 MASQUERADE)
防暴力破解(限速)
# 限制 SSH 连接频率(防止暴力破解)
sudo iptables -A INPUT -p tcp --dport 22 -m recent --set --name ssh_brute
sudo iptables -A INPUT -p tcp --dport 22 -m recent --update --seconds 60 --hitcount 4 --name ssh_brute -j DROP
# 60 秒内超过 4 次连接尝试就封掉
# 使用 limit 模块限速
sudo iptables -A INPUT -p tcp --dport 80 -m limit --limit 25/minute --limit-burst 100 -j ACCEPT
# 每分钟最多 25 个新连接,突发最多 100 个
保存和恢复规则
# Ubuntu/Debian:保存规则
sudo iptables-save > /etc/iptables/rules.v4 # 保存到文件
sudo ip6tables-save > /etc/iptables/rules.v6 # IPv6 规则
# Ubuntu/Debian:恢复规则
sudo iptables-restore < /etc/iptables/rules.v4 # 从文件恢复
# CentOS/RHEL:保存规则
sudo service iptables save # 保存到 /etc/sysconfig/iptables
# 或者手动
sudo iptables-save > /etc/sysconfig/iptables # 保存
sudo iptables-restore < /etc/sysconfig/iptables # 恢复
实用服务器规则模板
#!/bin/bash
# 服务器基础防火墙脚本
# 清空所有规则
iptables -F # 清空 filter 表
iptables -t nat -F # 清空 nat 表
iptables -X # 删除自定义链
# 设置默认策略:拒绝所有入站,允许所有出站
iptables -P INPUT DROP # 默认拒绝入站
iptables -P FORWARD DROP # 默认拒绝转发
iptables -P OUTPUT ACCEPT # 默认允许出站
# 允许回环
iptables -A INPUT -i lo -j ACCEPT # 本地通信必须放行
# 允许已建立的连接
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# 允许 SSH(可以限制来源 IP)
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 -j ACCEPT
# 记录被拒绝的包(方便排查问题)
iptables -A INPUT -j LOG --log-prefix "IPTables-DROP: " --log-level 4
echo "防火墙规则已设置完成"
常见报错
| 问题 | 原因 | 解决 |
|---|
| SSH 连不上了 | 设置了 DROP 默认策略但没放行 22 端口 | 通过控制台登录,加规则 iptables -I INPUT -p tcp --dport 22 -j ACCEPT |
| 规则重启后消失 | 没有保存规则 | 安装 iptables-persistent 或手动 iptables-save |
| 服务器上不了网 | OUTPUT 链被限制了 | iptables -P OUTPUT ACCEPT |
| 规则顺序导致不生效 | iptables 从上到下匹配,先匹配的优先 | 用 -I INPUT 1 插入到最前面 |
iptables: No chain/target/match | 内核模块没加载 | modprobe ip_tables |
速查表
# === 查看规则 ===
sudo iptables -L -n -v # 查看所有规则
sudo iptables -L --line-numbers # 带行号
sudo iptables -t nat -L -n # 查看 NAT 规则
# === 添加规则 ===
iptables -A INPUT -p tcp --dport 端口 -j ACCEPT # 允许端口
iptables -A INPUT -s IP地址 -j DROP # 封禁 IP
iptables -I INPUT 1 -p tcp --dport 端口 -j ACCEPT # 插入到最前面
# === 删除规则 ===
iptables -D INPUT 行号 # 按行号删除
iptables -D INPUT -p tcp --dport 端口 -j ACCEPT # 按内容删除
iptables -F # 清空所有规则
# === 默认策略 ===
iptables -P INPUT DROP # 默认拒绝入站
iptables -P OUTPUT ACCEPT # 默认允许出站
iptables -P FORWARD DROP # 默认拒绝转发
# === 保存恢复 ===
iptables-save > 文件 # 保存规则
iptables-restore < 文件 # 恢复规则
# === 常用动作 ===
-j ACCEPT # 允许
-j DROP # 丢弃(对方不知道)
-j REJECT # 拒绝(对方知道)
-j LOG # 记录日志