iptables 速描

  • iptables 速描,一些长期更新的内容.

  • 资料来源:

    https://www.zsythink.net/

  • 更新

    1
    2
    3
    20.01.08 初始化
    20.01.16 是个大坑😥
    20.07.24 填了这个大坑

导语

投入了不少时间重新啃一遍 iptables ,勉强理解下来了.这是一篇记录,并非完全的讲解.

来源

  • 内容几乎来自于 朱双印的blog,非常感谢如此深入浅出的讲解.
  • 引用了 朱双印的blog 的图片,需要授权,在blog留言申请,但不知道为什么关闭了评论…😂…
  • 一些关键词翻译参考维基.

概述

iptables 其实是一个用户空间控制 linux 内核 netfilter 的接口.其前身是 ipchains (大概),实际上 iptables 也在linux 3.13 以后被 nftables 取代了,现在还在使用的实际上是 nftables 的兼容接口.

nftables是取代 {ip,ip6,arp,eb}tables框架.比较好的资料是 Nftables HOWTO 中文翻译 ,有机会再写吧.

iptable

开局一张图,剩下全靠编.

021217_0051_6.png

一切对 iptables 的调整都是根据这张图标明的数据流向进行的.

  • PREROUTING : 路由前链.数据包在处理路由规则前通过此链.通常用于目的地址转换(DNAT)
  • INPUT: 输入链.所有达到本机的数据包都有通过输入链.
  • OUTPUT: 输出链.本机向外的的数据包都经过输出链输出,但是 注意 从本机到本机的数据包不经过输出链,直接回到本机.
  • FORWARD: 转发链.经过路由判断,所有不流向本机的数据包全部经过转化链.默认情况下转发并没有开启.
  • POSTROUTING: 路由后链.所有流出本机的完成路由规则后通过此链,通常用于源地址转换(SNAT).

来个例子?

  • 仅本机,例如打开网页.

    • 首先是查询 DNS 获得网站 ip 地址.
      • 出向: OUTPUT->POSTROUTING
      • 入向: PREROUTING->INPUT.
    • 请求网页与上面相同.
  • 路由器,除了处理本机流量还有转发局域网的其他流量到公网.通常路由器都有两个以上的网卡,一个有局域网地址,一个有公网的地址.这个时候就计到路由判断了.还是上面的过程,在路由器的处理.

    • 查询 DNS
      • 出向: 本机 OUTPUT->POSTROUTING 到路由器 PREROUTING(DNAT)->路由判断->FORWARD->POSTROUTING(SNAT) 到公网.
      • 入向: 公网 到 路由器 PREROUTING(DNAT)->路由判断->FORWARD->POSTROUTING(SNAT) 到本机 PREROUTING->INPUT.

对应不同链上,都要设置一些规则实现对数据包的过滤转发, iptables 将这些相同功能的规则归到了一起,称为一个表.

  • filter: 通常用于过滤数据包.
  • nat: 用于处理地址转换nat.
  • mangle: 用于处理数据包,例如拆包重装,修改报文的某个标志位什么的.
  • raw: 与连接追踪机制有关,待后续细察.

注意:

  • 链上并不是全部的4种规则表都有.具体见那张图.
  • 数据包依次经过不同的链,这样不同的链就有有优先级.相同的链上,数据包按照上图的顺序,依次经过不同的表,这样相同链上不同表的优先级也不同.所以每次调整 iptables 都要依照实际的优先级调整不同的链和表.
  • 在上文描述中,看似是 表寄生在链上.但恰恰相反,在 iptables 的实际使用中,我们直接操作的是表,然后修改表挂着的链上的某个规则.链是寄生在表上.

一个典型的 iptables 命令(具体的命令在下一节).

1
2
# 在            nat表 添加 路由前链     wlan1流出  数据包进行 nat 的规则
sudo iptables -t nat -A POSTROUTING -o wlan1 -j MASQUERADE

iptables 可以干什么?

  • 我们可以通过 iptables 对任何来源去向的数据包可以做任何事,丢弃,重定向,修改内容等等,这是 iptables 功能强大也是如此复杂的原因.
  • iptables 典型的应用是防火墙(预防ddos也是一种),端口映射,服务器的负载均衡等.

iptables 命令

**严重警告!!**不要轻易在服务器上实验,最好开个虚拟机,一旦远程服务器的 iptables 配置错误,只能进 vnc 急救,没有 vnc 那只能重装了.

iptables 命令模式上是非常相似的.

  • -t 指定对那个表操作,没有-t默认是 filter 表.
  • 具体的动作 A/I/D/F/R/L 头部添加/尾部添加/删除/全部删除/修改/查询
  • POSTROUTING 等是指定对那个链操作.
  • 后面是匹配的条件 -o -i 是数据包从那里来,到哪里去,ip地址,网卡都可以作为条件.还可以通过 iptables 的模块实现基于数据包内容的过滤.
  • -j 匹配后的操作,基本的有 ACCEPT /DROP/REJECT /SNAT /MASQUERADEDNAT /REDIRECT 等.

动作

目前只需要知道 2 个动作.

  • ACCEPT: 允许数据包通过
  • DROP: 丢弃数据包

命令

-L: 即列出规则,实际上与之配合的还有其他命令.

  • -n: 表示不解析IP地址
  • -v: 显示计数器信息
  • -x: 显示计数器的精确值
  • –line: 这个命令比较特殊,需要跟在 iptables 之后.相似规则的编号,在修改某条规则时有用.

这些命令可以合并为 iptables --line |xxx| -nvxL 查询规则时常用.

查询 nat 表

1
iptables --line -t nat -nvxL

-A: 在对应链的末尾添加规则.

在 nat表 INPUT链 末尾插入一条允许流向 192.168.0.1 的规则

1
iptbles -t nat -A INPUT -s 192.168.0.1 -j ACCEPT

-I: 在对应链的头部添加规则,还可以通过-I 实现在在某个具体位置插入规则.

在 nat表 INPUT链 头部插入一条允许流向 192.168.0.2 的规则

1
iptbles -t nat -I INPUT -s 192.168.0.2 -j ACCEPT

-D: 删除规则,可以是按照某条规则的编号,也可以按照规则具体的匹配条件与动作删除.

删除 nat表 INPUT链 的编号为 1 的规则

1
iptables -t nat -D INPUT 1

删除 nat表 INPUT链 允许流向 192.168.0.2 的规则

1
iptbles -t nat -D INPUT -s 192.168.0.2 -j ACCEPT

-F: 清空指定表链的规则,类似rm -rf 需要慎用.没有指定表时,清空 filter 表.当没有指定链时,清空整个表.

-R: 更改规则的动作.需要指定对应的表->链->序号和匹配的条件.要更改一个规则另一个更为通用的做法是先删除此规则,再在原位置插入一个新的规则.

把 nat表 INPUT链 允许流向 192.168.0.2 的规则改为丢弃

1
iptbles -t nat -R INPUT -s 192.168.0.2 -j DROP

-P: 指定链的默认动作.在一个数据包经过对应的链依次匹配,但最后没有任何规则与之匹配时的默认动作.默认情况下都是 ACCEPT 允许通过.不需要 -j

修改 nat表 INPUT链 默认动作为 DROP

1
iptbles -t nat -P INPUT DROP

规则的匹配

在进入规则的具体匹配之前,我们先来看看 iptables 的规则可以对数据包进行的基本动作,方便接下来的讲解.

  • ACCEPT: 允许数据包通过.是 iptables -F后的所有表和链的默认动作.
  • DROP: 丢弃数据包,在发送方看来数据包石沉大海,没有任何回应.一个例子是把发向本机的 icmp 直接丢弃.这样从发送 ping 的一方看来是目标主机无回应.!!

回到规则的匹配,规则的匹配有两种

  • 一是最基本的基于地址的基本匹配.
  • 二是基于模块的匹配,可以提供更加丰富的匹配规则,需要通过 -m 应用具体的模块.

基本匹配条件

基于 ip 地址

基本(如果没有指定源地址或者目的地址,即为 0.0.0.0,表示全部 ip)

  • -s: 数据包的源地址,从 iptables 看来数据包的来源 ip 地址.
  • -d: 数据包的目的地址,从 iptables 看来是数据包的目的地的 ip 地址.
  • 可以匹配多个 ip 地址,在 -s -d 后面以 , 号隔开.
  • 还可以匹配一个 ip 段,例如 -s 192.168.0.0/8.
  • 还可以进行取反操作,即表示除指定 ip 或 ip 段以外的 ip 地址怎样.可以实现只允许特定 ip 访问.

要注意这两种方式不能混合使用.

1
2
3
4
5
6
7
8
#丢弃 192.168.0.1 来的数据包
iptbles -t nat -A INPUT -s 192.168.0.1 -j DROP
#丢弃除 192.168.0.1 外其他来源的数据包
iptbles -t nat -A INPUT ! -s 192.168.0.1 -j DROP
#丢弃 192.168.0.1 192.168.0.2 来的数据包
iptbles -t nat -A INPUT -s 192.168.0.1,192.168.0.2 -j DROP
#丢弃 192.168.0.0/8 段来源的数据包
iptbles -t nat -A INPUT -s 192.168.0.0/8 -j DROP
基于协议类型

基本

  • 可以通过 -p 选项指定匹配的数据包类型.
  • 包括不限于 tcp,udp,udplite,icmp,esp,ah,sctp等.(当然常用就 tcp,udp,icmp)
  • 可用取反,只允许某种协议通过.
  • 当不指定 -p 时默认等同于 -p all.即所有协议.

例:

1
2
3
4
# 接受192.168.0.1 来的 tcp 数据包.
iptbles -t nat -A INPUT -p tcp -s 192.168.0.1 -j ACCEPT
# 丢弃192.168.0.1 除 tcp 以外的其他流量
iptbles -t nat -A INPUT ! -p tcp -s 192.168.0.1 -j DROP
基于网卡

基本

  • -i: 数据包流入的网卡.
  • -o: 数据包流出的网卡.
  • 一个计算机可能有多个网卡,而且结合第一节的图应该会想到一个问题,有的链并不能使用 -i 和 -o.
  • -i : PREROUTING链 INPUT链 FORWARD链
  • -o : FORWARD链 OUTPUT链 POSTROUTING链
  • 可以取反

注意:

  • 本机的数据包并不通过 iptables ,过滤本机数据包无意义.
  • 同一个表上的链的规则之间是逻辑与的关系,符合才处理,不符合进入下一条规则,最后进入默认的动作.

例:

1
2
3
4
5
6
# 允许 wlan0 向外 ping(icmp)
iptbles -t nat -A OUTPUT -p icmp -o wlan0 -j ACCEPT
# 丢弃流入 eth0 的 icmp
iptbles -t nat -A INPUT -p icmp -i eth0 -j DROP
# 只允许 wlan1 响应 ping(丢弃其他流入的icmp数据包)
iptbles -t nat -A INPUT -p icmp !-i wlan1 -j DROP

拓展匹配条件/模块

简单的应用,基本匹配条件已足够应付,但是如果有过滤端口,或者基于报文内容的过滤,此时基本的匹配条件就很难满足.需要拓展的匹配条件.

拓展的匹配条件需要安装对应的 iptables 模块,并通过 -m module 引用.

可以与基本匹配条件连用.

tcp模块

基本

  • 匹配 tcp 的端口.区分流入,流出.
  • 可以指定具体端口,或者端口范围,但不能同时使用.
  • 可取反
  • –sports: 源端口
  • –dports: 目的地端口
  • –tcp-flags: 与 tcp 的三次握手有关,详情见后.
  • -m tcp-p tcp 并不冲突,不要混淆,仅仅是模块名也是 tcp.当与-p tcp连用时可以省略 -m tcp.

例:

1
2
3
4
5
6
# 允许连接到 192.168.0.1 的 22端口
iptbles -t nat -A OUTPUT -d 192.168.0.1 -p tcp -m tcp --sport 22 -j REJECT
# 允许连接到 192.168.0.1 的 22端口(省略 -m tcp)
iptbles -t nat -A OUTPUT -d 192.168.0.1 -p tcp --sport 22 -j REJECT
# 允许连接到 192.168.0.1 的 22到50 端口
iptbles -t nat -A OUTPUT -d 192.168.0.1 -p tcp -m tcp --sport 22:50 -j REJECT
multiport 模块

基本

  • 作用与 tcp 模块相同,但可以指定离散的多个端口,一个端口范围且可以混合使用.中间用 , 隔开.
  • –sports: 源端口
  • –dports: 目的地端口
  • 可取反(觉得都没必要写了,基本都支持取反)
  • 例:
1
2
# 不允许 tcp 连接到 192.168.0.2 的 22 25 80到443端口
iptables -t nat -I OUTPUT -d 192.168.1.146 -p tcp -m multiport --sports 22,25,80:443 -j DROP
udp 模块
  • –sport 与 –dport 与 tcp 完全相同
  • 指定多个离散端口,同样使用 multiport.
icmp 模块

题外话: ping 是 icmp 的应用,实际上我们 ping 对方是,向对方发送了 type为8 code为0 的 icmp 报文,如果正常,对方回复我们的是 type 0 的报文,这样就完成了一次 ping 和响应的过程.

  • iptables -t filter -I INPUT -p icmp -m icmp --icmp-type 8/0 -j REJECT: INPUT 表拒绝 type 8 code 0 的icmp 进入,直观效果就是别人无法 ping 通我们.我们可以 ping 别人.
  • iptables -t filter -I INPUT -p icmp --icmp-type 8 -j REJECT: type为8的类型下只有一个code为0的类型,所以我们可以省略对应的code.
  • iptables -t filter -I INPUT -p icmp --icmp-type "echo-request" -j REJECT: --icmp-type "echo-request"--icmp-type 8/0 的效果完全相同,我们可以用 icmp 报文的描述名称去匹配对应类型的报文.
iprange

基本

  • 可以指定连续的一段ip地址以 -连接.主要拓展 -s 与 -d.
  • –src-range: 源地址
  • –dst-range: 目标地址
  • 可取反

例:

1
2
# 丢弃192.168.0.1-192.168.0.5的所有入向数据包
iptables -t nat -I INPUT -m iprange --src-range 192.168.0.1-192.168.0.5 -j DROP
string
  • 匹配报文的特定字符串(对https无效?)
  • –algo: 指定匹配的算法有 kmp 与 bm 两种
  • –string:指定需要匹配的字符串
time

基本

  • 与时间有关的拓展,一般用于禁止孩子上网?😂?…而且拓展较多..
  • –timestart –timestop: 指定一个时间范围 不可取反
  • –datestart –datestop: 指定一个日期范围 不可取反
  • –weekdays: 指定星期几 可取反
  • –monthdays:指定几号 可取反
  • 可以组合使用,条件是 .

例:

1
2
3
4
5
6
# 丢弃 21点到23点 的数据包 断网..
iptables -t nat -I OUTPUT -p tcp -m time --timestart 21:00:00 --timestop 23:00:00 -j DROP
# 2020链1月1号到31号断网
iptables -t nat -I OUTPUT -p tcp -m time --datestart 2020-01-01 --datestop 2020-01-31 -j DROP
# 月末的星期六星期天的21到23点断网
iptables -t nat -I OUTPUT -p tcp -m time --monthdays 28,29,30,31 --weekdays 6,7 --timestart 21:00:00 --timesto23:00:00 -j DROP
其他

connlimit

  • 限制单个 ip 的连接数量
  • 还没太尝试

limit

  • 限制连接的速度
  • 还没太尝试

state

state 属于 iptables 模块,但是比较特殊,拿出来单独说.

思考一个问题,如何拒绝恶意流量进入?

  • 可以限制端口,但是只恶意流量换个通的端口一样进入.
  • 可以限制 ip,但是维护 ip 白/黑名单的情况下,如果面对海量 ip 几乎是个人难以承受的.
  • 针对 tcp 链接可以从链接状态下手,拒绝首次链接,仅允许本机向外的连接.但是 udp? icmp?

针对以上问题 state 模块出现,state 模块让 iptable 有了连接的概念.

这个 state 模块连接的概念要比 tcp连接 更底层一点.让我感觉 state 模块应该可以划归到 ip 层,只要是两个 ip 地址之间存在 ip 报文的传输就认为两个主机之间建立了连接.

state 连接

  • NEW: 两个主机之间的第一个数据包.
  • ESTABLISHED: 已建立连接上的后续数据包.
  • RELATED: 关联/联系,数据包是连接的首个数据包,但是这个连接与现有的其他连接有关系.
  • INVALID: 无法识别的数据包.
  • UNTRACKED: 完全不追踪的数据包.

例子:只允许 RELATED ESTABLISHED 的数据包进入

1
2
3
4
# 允许 RELATED ESTABLISHED 的数据包进入
iptables -t filter -I INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
# 默认拒绝数据包进入
iptables -A INPUT -j REJECT

iptables 黑白名单机制

黑白名单不必多言,只提一点.

  • 实现白名单时,绝对不应该修改链的默认动作为 DROP,如果清空规则后,远程直接挂掉了.
  • 最佳的实现是在规则的最后一条添加一个全部 DROP 的动作.

自定义链

所谓自定义链也只是为了方便管理,将一类的规则整理成链,最后一定要挂到某个默认链上才能生效.

自定义链上的规则完全不变.

创建自定义链

1
iptables -t filter -N IN_WEB

引用自定义链

1
2
#示例:在INPUT链中引用刚才创建的自定义链
iptables -t filter -I INPUT -p tcp --dport 80 -j IN_WEB

重命名自定义链

1
2
#示例:将IN_WEB自定义链重命名为WEB
iptables -E IN_WEB WEB

删除自定义链

  • 自定义链没有被引用
  • 自定义链中没有任何规则
1
2
#示例:删除引用计数为0并且不包含任何规则的WEB链
iptables -X WEB

网络防火墙

使用 iptables 作为网络防火墙有几个条件

  • 开启 ip_forward 转发.
  • 配置 路由表
  • 配置 NAT
  • 最后所有规则都要在 FORWARD 链

iptables 动作

与命令类似,对数据包的动作也有基本动作和拓展动作.但是拓展动作不需要额外安装模块.

基础动作: ACCEPT DROP 不再赘述.

REJECT

字面上意思是拒绝接受数据包,与 DROP 不同,会返回拒绝的原因.

使用方式即: REJECT --reject-with + 可选的原因.

  • icmp-net-unreachable
  • icmp-host-unreachable
  • icmp-port-unreachable
  • icmp-proto-unreachable
  • icmp-net-prohibited
  • icmp-host-pro-hibited
  • icmp-admin-prohibited
  • 默认是 icmp-port-unreachable

LOG

LOG 对数据包无任何作用,仅仅是记录.

默认 Log 的记录在 /var/log/message 下,改动默认位置

  • /etc/rsyslog.conf(log 子系统) 添加 kern.warning /var/log/iptables.log.即位置改在 /var/log/iptables.log
  • service rsyslog restart 重启 log 子系统.

选项有两个

  • –log-level: 指定记录 log 的级别 emerg ,alert, crit, error, warning, notice, info, debug
  • –log-prefix: 指定的标记,不超过 19 个字符

REDIRECT

重定向,常用于端口映射.

1
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 8080

本机的 80 端口被重定向到本机的 8080 端口上.

REDIRECT 规则只能定义在 PREROUTING 链或者 OUTPUT 链中.

其他动作

剩余几个都和 NAT 有关

  • SNAT: 源地址转换,简单的理解 -> 从私网到公网的地址转换.
  • DNAT: 目标地址转换,简单的理解 -> 从公网到私网的地址转换
  • MASQUERADE: SNAT 需要指定来源 ip 地址/范围,但有时又无法固定私网 ip,这时使用 MASQUERADE (动态 SNAT),通过指定网卡来执行 NAT,但是效率要低一点.

后记

  • 内容实在是太多了…