iptables 速描
iptables 速描,一些长期更新的内容.
资料来源:
https://www.zsythink.net/
更新
1
2
320.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
开局一张图,剩下全靠编.
一切对 iptables 的调整都是根据这张图标明的数据流向进行的.
- PREROUTING : 路由前链.数据包在处理路由规则前通过此链.通常用于目的地址转换(DNAT)
- INPUT: 输入链.所有达到本机的数据包都有通过输入链.
- OUTPUT: 输出链.本机向外的的数据包都经过输出链输出,但是 注意 从本机到本机的数据包不经过输出链,直接回到本机.
- FORWARD: 转发链.经过路由判断,所有不流向本机的数据包全部经过转化链.默认情况下转发并没有开启.
- POSTROUTING: 路由后链.所有流出本机的完成路由规则后通过此链,通常用于源地址转换(SNAT).
来个例子?
仅本机,例如打开网页.
- 首先是查询 DNS 获得网站 ip 地址.
- 出向: OUTPUT->POSTROUTING
- 入向: PREROUTING->INPUT.
- 请求网页与上面相同.
- 首先是查询 DNS 获得网站 ip 地址.
路由器,除了处理本机流量还有转发局域网的其他流量到公网.通常路由器都有两个以上的网卡,一个有局域网地址,一个有公网的地址.这个时候就计到路由判断了.还是上面的过程,在路由器的处理.
- 查询 DNS
- 出向: 本机 OUTPUT->POSTROUTING 到路由器 PREROUTING(DNAT)->路由判断->FORWARD->POSTROUTING(SNAT) 到公网.
- 入向: 公网 到 路由器 PREROUTING(DNAT)->路由判断->FORWARD->POSTROUTING(SNAT) 到本机 PREROUTING->INPUT.
- 查询 DNS
对应不同链上,都要设置一些规则实现对数据包的过滤转发, iptables 将这些相同功能的规则归到了一起,称为一个表.
- filter: 通常用于过滤数据包.
- nat: 用于处理地址转换nat.
- mangle: 用于处理数据包,例如拆包重装,修改报文的某个标志位什么的.
- raw: 与连接追踪机制有关,待后续细察.
注意:
- 链上并不是全部的4种规则表都有.具体见那张图.
- 数据包依次经过不同的链,这样不同的链就有有优先级.相同的链上,数据包按照上图的顺序,依次经过不同的表,这样相同链上不同表的优先级也不同.所以每次调整 iptables 都要依照实际的优先级调整不同的链和表.
- 在上文描述中,看似是 表寄生在链上.但恰恰相反,在 iptables 的实际使用中,我们直接操作的是表,然后修改表挂着的链上的某个规则.链是寄生在表上.
一个典型的 iptables 命令(具体的命令在下一节).
1 | # 在 nat表 添加 路由前链 wlan1流出 数据包进行 nat 的规则 |
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 | #丢弃 192.168.0.1 来的数据包 |
基于协议类型
基本
- 可以通过 -p 选项指定匹配的数据包类型.
- 包括不限于 tcp,udp,udplite,icmp,esp,ah,sctp等.(当然常用就 tcp,udp,icmp)
- 可用取反,只允许某种协议通过.
- 当不指定 -p 时默认等同于 -p all.即所有协议.
例:
1 | # 接受192.168.0.1 来的 tcp 数据包. |
基于网卡
基本
- -i: 数据包流入的网卡.
- -o: 数据包流出的网卡.
- 一个计算机可能有多个网卡,而且结合第一节的图应该会想到一个问题,有的链并不能使用 -i 和 -o.
- -i : PREROUTING链 INPUT链 FORWARD链
- -o : FORWARD链 OUTPUT链 POSTROUTING链
- 可以取反
注意:
- 本机的数据包并不通过 iptables ,过滤本机数据包无意义.
- 同一个表上的链的规则之间是逻辑与的关系,符合才处理,不符合进入下一条规则,最后进入默认的动作.
例:
1 | # 允许 wlan0 向外 ping(icmp) |
拓展匹配条件/模块
简单的应用,基本匹配条件已足够应付,但是如果有过滤端口,或者基于报文内容的过滤,此时基本的匹配条件就很难满足.需要拓展的匹配条件.
拓展的匹配条件需要安装对应的 iptables 模块,并通过 -m module
引用.
可以与基本匹配条件连用.
tcp模块
基本
- 匹配 tcp 的端口.区分流入,流出.
- 可以指定具体端口,或者端口范围,但不能同时使用.
- 可取反
- –sports: 源端口
- –dports: 目的地端口
- –tcp-flags: 与 tcp 的三次握手有关,详情见后.
-m tcp
与-p tcp
并不冲突,不要混淆,仅仅是模块名也是 tcp.当与-p tcp
连用时可以省略-m tcp
.
例:
1 | # 允许连接到 192.168.0.1 的 22端口 |
multiport 模块
基本
- 作用与 tcp 模块相同,但可以指定离散的多个端口,一个端口范围且可以混合使用.中间用
,
隔开. - –sports: 源端口
- –dports: 目的地端口
- 可取反(觉得都没必要写了,基本都支持取反)
- 例:
1 | # 不允许 tcp 连接到 192.168.0.2 的 22 25 80到443端口 |
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 | # 丢弃192.168.0.1-192.168.0.5的所有入向数据包 |
string
- 匹配报文的特定字符串(对https无效?)
- –algo: 指定匹配的算法有 kmp 与 bm 两种
- –string:指定需要匹配的字符串
time
基本
- 与时间有关的拓展,一般用于禁止孩子上网?😂?..而且拓展较多…
- –timestart --timestop: 指定一个时间范围 不可取反
- –datestart --datestop: 指定一个日期范围 不可取反
- –weekdays: 指定星期几 可取反
- –monthdays:指定几号 可取反
- 可以组合使用,条件是 与.
例:
1 | # 丢弃 21点到23点 的数据包 断网.. |
其他
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 | # 允许 RELATED ESTABLISHED 的数据包进入 |
iptables 黑白名单机制
黑白名单不必多言,只提一点.
- 实现白名单时,绝对不应该修改链的默认动作为 DROP,如果清空规则后,远程直接挂掉了.
- 最佳的实现是在规则的最后一条添加一个全部 DROP 的动作.
自定义链
所谓自定义链也只是为了方便管理,将一类的规则整理成链,最后一定要挂到某个默认链上才能生效.
自定义链上的规则完全不变.
创建自定义链
1 | iptables -t filter -N IN_WEB |
引用自定义链
1 | #示例:在INPUT链中引用刚才创建的自定义链 |
重命名自定义链
1 | #示例:将IN_WEB自定义链重命名为WEB |
删除自定义链
- 自定义链没有被引用
- 自定义链中没有任何规则
1 | #示例:删除引用计数为0并且不包含任何规则的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,但是效率要低一点.
后记
- 内容实在是太多了…