本文完整阅读约需 23 分钟,如时间较长请考虑收藏后慢慢阅读~

iptables 是 Linux 中非常经典的防火墙工具,但由于结构复杂,官方文档冗长,参数较多,且配置方式别扭(默认不支持持久化,命令添加即生效等),配置存在风险(一不小心就和服务器失联)等问题,导致学习曲线极高,对 Linux 新手或记忆力欠佳的人(笔者的记忆力就很差)极为不友好。本文旨在让 iptables 新手在 15 分钟内掌握 iptables 常用操作,并能根据需要快速查询想要的命令。

免责声明:本文为笔者个人使用过程中的笔记分享,在使用笔记中的命令之前,请先了解自己在做什么,建议在实验环境中先进行操作,再在生产环境中应用!如果不确定自己在做什么或是想做什么,推荐先阅读 iptables 的官方文档:iptables(8) – Linux man page
以下内容可能会存在错误或表述不清的地方,如果有疑问或指正欢迎留言,笔者会第一时间修改,避免误导~

iptables 概念

  • 表:对应不同处理数据包的内核模块
    • filter:过滤
    • 内核模块:iptables_filter
    • nat:网络地址转换
    • 内核模块:iptables_nat
    • mangle: 拆解和封装报文
    • raw:最先接触数据包的表,可以让某个数据包跳过过滤原则

表顺序为 raw –> mangle –> nat –> filter

  • 链:不同访问路径会经过不同的链
    • prerouting
    • input
    • output
    • forward
    • postrouting

不同表中链顺序:
(来自 https://www.cnblogs.com/chenxiaomeng/p/11991912.html)

iptables 常用命令

配置全局策略

危险!最好在有 VNC 连接,或在配置结束后再配置全局策略

iptables --policy INPUT DROP
iptables --policy OUTPUT ACCEPT
iptables --policy FORWARD ACCEPT

显示 iptables 规则

# 万能药
iptables -n -L -v --line-numbers

# 显示默认表 (filter) 所有规则
iptables -n -L

# 显示规则时记录流量
iptables -n -L -v

# 显示规则时记录行号(用于插入)
iptables -n -L --line-numbers

# 指定某个子表(最常用如 nat)
iptables -n -L -t nat

# 只显示某链的规则
iptables -L INPUT

# 以 iptables-save 格式显示规则
iptables -S INPUT

iptables 增删

# 在 input 链 n 位置后插入一条规则
iptables -I INPUT {n} ...

# 将规则添加在 INPUT 链最后
iptables -A INPUT ...

# 删除 INPUT 链 n 位置的记录
iptables -D INPUT {n}

# 根据具体参数删除记录
iptables -D INPUT -m conntrack --ctstate INVALID -j DROP

# 删除指定链下所有记录
iptables -F INPUT

# 删除指定表下所有记录
iptables -t nat -F

# 删除所有记录
iptables -F

iptables 包过滤

# 允许特定 TCP 端口通过
iptables -A INPUT -p tcp --dport 22 -j ACCEPT

# 允许特定 TCP 端口段通过
iptables -A INPUT -p tcp --dport 8000:8800 -j ACCEPT
iptables -A INPUT -p tcp -m multiport --dport 80,443 -j ACCEPT

# 允许特定 IP 通过
iptables -A INPUT -p tcp -s 192.168.1.0/24 --dport 22 -j ACCEPT

# 允许从特定网卡通过
iptables -A INPUT -i eth1 -p tcp --dport 3306 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT

# 禁止特定端口
iptables -A OUTPUT -p tcp --dport 25 -j REJECT

# 禁止并记录
iptables -A INPUT -i eth1 -s 10.0.0.0/8 -j LOG --log-prefix "IP_SPOOF A: "
iptables -A INPUT -i eth1 -s 10.0.0.0/8 -j DROP
tail -f /var/log/messagesgrep --color 'IP SPOOF' /var/log/messages

# 根据特定包内容(非加密)过滤
iptables -A FORWARD -m string --string '.exe' -j DROP

iptables 包转发

# 包转发前提:启用 ip_forward
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
sudo sysctl -p

# iptables 实现 NAT 网关
# 假设内网网段为 10.0.0.0/24
iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -j MASQUERADE
iptables -t filter -A FORWARD -s 10.0.0.0/24 -j ACCEPT
iptables -t filter -A FORWARD -d 10.0.0.0/24 -j ACCEPT

# iptables 实现端口映射
# 将本机 (192.168.75.5) 的 80~88 端口转发到 192.168.75.3:8008 上
iptables -t nat -A PREROUTING -p tcp -d 192.168.75.5 --dport 80:88 -j DNAT --to-destination 192.168.75.3:8000-8008
iptables -t nat -A POSTROUTING -p tcp -d 192.168.75.3 --dport 8000:8008 -j SNAT --to-source 192.168.75.5
# 将本机的 80 端口转发到 8080 端口
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 8080

iptables 包限流

# 限制流量
iptables -A INPUT -p tcp -m multiport --dport 80,443 -m limit --limit 20/s --limit-burst 5 -j ACCEPT

# 限制时间
iptables -A INPUT -p tcp -m multiport --dport 80,443 -m time --timestart 21:30 --timestop 22:30 --days Mon,Tue,Wed,Thu,Fri -j ACCEPT

# 防止暴力攻击
iptables -A INPUT -p tcp -m multiport --dport ssh -m conntrack --ctstate NEW -m recent --setiptables -A INPUT -p tcp --dport ssh -m conntrack --ctstate NEW -m recent --update --seconds 60 --hitcount 10 -j DROP

# 防止端口扫描
iptables -N port-scanningiptables -A port-scanning -p tcp --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 1/s --limit-burst 2 -j RETURNiptables -A port-scanning -j DROP

iptables 保存&加载&自动加载

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

# 加载
iptables-restore < /etc/iptables/rules.v4

# 自动加载
# deb 系
apt install iptables-persistent
# 自动从 /etc/iptables/rules.v4 和 /etc/iptables/rules.v4 读取配置文件

# RHEL 系
dnf install iptables-services
sudo systemctl stop firewalld
sudo systemctl disable firewalld
sudo systemctl start iptables
sudo systemctl enable iptables
# 从 /etc/sysconfig/iptables 和 /etc/sysconfig/ip6tables 读取配置文件

iptables-save 配置文件阅读和编写

# Generated by iptables-save v1.4.21 on Tue Jan 15 15:42:32 2019
--这是注释
*nat
-- 这表示下面这些是 nat 表中的配置
:PREROUTING ACCEPT [5129516:445315174]
-- :PREROUTING ACCEPT,表示 nat 表中的 PREROUTING 链默认报文策略是接受(匹配不到规则继续) ,

-- [5129516:445315174] 即 [packet, bytes],表示当前有 5129516 个包 (445315174 字节)经过 nat 表的 PREROUTING 链
:INPUT ACCEPT [942957:151143842]
:OUTPUT ACCEPT [23898:3536261]
:POSTROUTING ACCEPT [23898:3536261]
-- 解释同上
:DOCKER - [0:0]
-- 解释同上(此条是自定义链)
---------- 下面开始按条输出所有规则----------
[4075:366986] -A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-- [4075:366986] 即 [packet, bytes],表示经过此规则的包数,字节数。 后面部分则是用 iptables 命令配置此规则的命令(详解选项可参考 iptables 帮助)。
[0:0] -A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
[0:0] -A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
[2:188] -A POSTROUTING -s 192.168.122.0/24 -d 224.0.0.0/24 -j RETURN
[0:0] -A POSTROUTING -s 192.168.122.0/24 -d 255.255.255.255/32 -j RETURN
[0:0] -A POSTROUTING -s 192.168.122.0/24 ! -d 192.168.122.0/24 -p tcp -j MASQUERADE --to-ports 1024-65535
[0:0] -A POSTROUTING -s 192.168.122.0/24 ! -d 192.168.122.0/24 -p udp -j MASQUERADE --to-ports 1024-65535
[0:0] -A POSTROUTING -s 192.168.122.0/24 ! -d 192.168.122.0/24 -j MASQUERADE
[0:0] -A DOCKER -i docker0 -j RETURN
--以上规则同第一条规则的解释
COMMIT
-- 应用上述配置
# Completed on Tue Jan 15 15:42:32 2019