基于 netfilter 的技术
参考网址: https://en.wikipedia.org/wiki/Iptables
用于匹配packets的规则称为链(chain) 对匹配的packets执行的动作称为目标(target)
iptables-save的输出:
:PREROUTING ACCEPT [225:64427]
方括号左边的是数据包的个数
方括号右边的是数据包的byte数
1. iptables
1.1 iptables的原理
iptables 只是一个操作 Linux 内核 Netfilter 子系统的“界面”。 顾名思义,Netfilter 子系统的作用,就是 Linux 内核里挡在“网卡”和“用户态进程”之间的一道“防火墙”。 它们的关系,可以用如下的示意图来表示:
+---------------+
| User Process |
User Space | ^ | |
| | V |
+----|-----|----+
+----|-----|----+
| NetFilter |
| | | |
| | | |
Kernel Space | | | |
| | | |
| ^ V |
| { eth0 } |
+----|-----|----+
IP包在上图"一进一出"的两条路径上,有几个关键的"检查点",他们正是Netfilter设置"防火墙"的地方。 在iptables中,这些"检查点"被称为:链(Chain)。这是因为这些"检查点"对应的iptables规则,是按照 定义顺序依次进行匹配的。这些"检查点"的具体工作原理,可以用如下所示的示意图进行描述:
Input Path Forward Path Output Path
+-------------------------+----------------------------+---------------------+ 用户空间方向
+-+-------------------------+----------------------------+---------------------+-+ ^
| 上层协议栈(比如: 传输层) | |
+-+------------------^------+----------------------------+-----------V---------+-+
| | | | | |
| | | | (路由) |
| | | | | |
| ^ | | V |
| INPUT | | OUTPUT |
| ^ | | | |
| 第一种 | | | | |
| |第二种| | | |
->|PREROUTING---->(路由)--->|FORWARD-------------------->|------POSTROUTING ---+-->
+-------------------------+----------------------------+---------------------+
PREROUTING: raw->mangle->nat
INPUT: mangle->filter
OUTPUT: raw->mangle->nat->filter
FORWARD: mangle->filter
POSTROUTING: mangle->nat
表:目前有五个独立的表(这些表是否存在取决于内核配置选项和对应模块存在)。
-t, --table table
指定数据包所匹配的表。在内核配置了自动模块加载的前提下,如果该表不存在,将尝试为该表加载适当的模块。
目前的linux内核共支持5个表:
* filter: (默认值)
其内置(built-in)的chain:
INPUT: 对于发往本地套接字的数据包
FORWARD: 用于通过box路由的数据包
OUTPUT: 对于本地生成的数据包(用于修改路由之前本地生成的数据包)
* nat: 当遇到创建新连接的数据包时会查询此表
其内置的chain:
PREROUTING: 用于在数据包进入时立即更改数据包
OUTPUT:
POSTROUTING: 用于更改即将发出的数据包
kernel 3.7之后支持IPv6 NAT
* mangle: 此表用于专门的数据包更改
其内置的chain:
kernel == 2.4.17:
PREROUTING:
OUTPUT:
kernel >= 2.4.18(额外支持的chain):
INPUT:
FORWARD:
POSTROUTING:
* raw: 此表主要用于结合 NOTRACK 目标配置连接跟踪的豁免。
它在具有更高优先级的 netfilter 挂钩(hook)上注册,因此在 ip_conntrack 或任何其他 IP 表之前被调用。
其内置的chain:
PREROUTING:
OUTPUT:
* security: 此表用于强制访问控制 (MAC: Mandatory Access Control) 网络规则,例如由 SECMARK 和 CONNSECMARK 目标启用的规则。MAC由linux安全模块例如selinux实现。严禁使用security表,因为它使用了selinux,使用它可能会导致意料之外的事情。
security表在filter表之后调用,允许filter表中的任意 自主访问控制(DAC: Discretionary Access Control) 规则在 MAC 规则之前生效。
其内置的chain:
INPUT:
OUTPUT:
FORWARD:
可以看到,当一个 IP 包通过网卡进入主机之后,它就进入了 Netfilter 定义的流入路径(Input Path)里。 在这个路径中,IP 包要经过路由表路由来决定下一步的去向。而在这次路由之前,Netfilter 设置了一个名叫 PREROUTING 的“检查点”。在 Linux 内核的实现里,所谓“检查点”实际上就是内核网络协议栈代码里的 Hook(比如,在执行路由判断的代码之前,内核会先调用 PREROUTING 的 Hook)。
而在经过路由之后,IP 包的去向就分为了两种:
-
第一种,继续在本机处理;
这时候,IP 包将继续向上层协议栈流动。在它进入传输层之前,Netfilter 会设置一个名叫 INPUT 的“检查点”。到这里,IP 包流入路径(Input Path)结束。 接下来,这个 IP 包通过传输层进入用户空间,交给用户进程处理。而处理完成后,用户进程会通过本机发出返回的 IP 包。这时候,这个 IP 包就进入了流出路径(Output Path)。 此时,IP 包首先还是会经过主机的路由表进行路由。路由结束后,Netfilter 就会设置一个名叫 OUTPUT 的“检查点”。然后,在 OUTPUT 之后,再设置一个名叫 POSTROUTING“检查点”。
-
第二种,被转发到其他目的地。
这个 IP 包不会进入传输层,而是会继续在网络层流动,从而进入到转发路径(Forward Path)。在转发路径中,Netfilter 会设置一个名叫 FORWARD 的“检查点”。 而在 FORWARD“检查点”完成后,IP 包就会来到流出路径。而转发的 IP 包由于目的地已经确定,它就不会再经过路由,也自然不会经过 OUTPUT,而是会直接来到 POSTROUTING“检查点”。 所以说,POSTROUTING 的作用,其实就是上述两条路径,最终汇聚在一起的“最终检查点”。这就是为什么在流出路径结束后,Netfilter 会连着设置两个“检查点”(OUTPUT和POSTROUTING)的原因。
-
需要注意的是,在有网桥参与的情况下,上述 Netfilter 设置“检查点”的流程,实际上也会出现在链路层(二层),并且会跟我在上面讲述的网络层(三层)的流程有交互。
这些链路层的“检查点”对应的操作界面叫作 ebtables。所以,准确地说,数据包在 Linux Netfilter 子系统里完整的流动过程,其实应该如下所示(https://en.wikipedia.org/wiki/Iptables#/media/File:Netfilter-packet-flow.svg)
上图中的绿色部分,就是网络层的iptables链的工作流程,其中的每个白色的"检查点"上,还有一个绿色的"标签",比如: raw,nat,filter等等。在iptables里,这些标签叫做:表。比如,同样是 OUTPUT 这个“检查点”,filter Output 和 nat Output 在 iptables 里的语法和参数,就完全不一样,实现的功能也完全不同。
filter: 用来过滤数据包; nat: 转换包的源或目标地址或端口(分为目的地址转换DNAT,源地址转换SNAT); mangle: 给数据打标记以根据标记去操作包。
所以说,iptables 表的作用,就是在某个具体的“检查点”(比如 Output)上,按顺序执行几个不同的检查动作(比如,先执行 nat,再执行 filter)。
1.2 iptables的jump策略
iptables定义了一套链式处理的结构,在网络包传输的各个阶段可以使用不同的策略对包进行加工、传送或丢弃。 在容器虚拟化的技术中,经常会用到两种策略MASQUERADE和DNAT,用于容器和宿主机外部的网络通信。
- MASQUERADE iptables中的MASQUERADE,这是一个特殊的target,它会修改符合条件的数据包的源IP地址为出站接口的IP地址。SNAT需要指定IP,而MASQUERADE可以自动检测出口接口的IP。
比如某个Namespace中的网络设备地址是172.18.0.2,这个地址虽然在宿主机上可以路由到br0的网桥,但是到达宿主机外部之后, 是不知道如何路由到这个IP地址的,所以如果请求外部地址的话,需要先通过MASQUERADE策略将这个IP转换为宿主机出口网卡的IP,
如下:
|
|
在Namespace中请求宿主机外部地址时,将Namespace中的源地址转换成宿主机的地址作为源地址,就可以在Namespace中访问宿主机外的网络了。
- DNAT
iptables中的DNAT策略也是做网络地址的转换,不过它是要更换目的地址,经常用于将内部网络地址的端口映射到外部去。
比如某个Namespace中,需要提供服务给宿主机之外的应用去请求,要怎么办呢?
docker run -p80:80
外部应用没有办法直接路由到172.18.0.2这个地址,这时候就可以用到DNAT策略:
这样就可以把宿主机上80端口的TCP请求转发到Namespace中的地址172.18.0.2:80,从而实现外部的应用调用。
snat:出去的时候(POSTROUTING)改变源地址
dnat:进来的时候(PREROUTING)改变目的地址
1.3 CentOS通过raw表实现iptables日志输出和调试
当系统上iptables规则过多时,如果有出现丢包或者网络不通需要查看原因时,调试iptables规则就成了一个绕不过的问题。 raw表在所有iptables规则中优先级是最高的,raw表有两条链,prerouting和output,分别作为输入和输出的第一必经点,因此作为调试是最合适不过。
这里以调试两个docker容器间发送的ICMP报文为例,进行日志的采集:
通过上面的设置,就可以在/var/log/messages里面看到数据包传输的日志了。
由于iptables的调试日志输出依赖于内核模块,这些内核模块并不是开机就加载的,因此我们需要手动加载
|
|
清空/var/log/messages文件之后,记得重启下rsyslog
1.4 常用iptables命令
|
|
1.5 iptables 规则的持久化
service iptables save 等同于 /usr/libexec/iptables/iptables.init save
,iptables.init文件中save函数的代码如下:
|
|
restorecon的安装: yum install -y policycoreutils selinux-policy
restorecon 是 SELinux(Security-Enhanced Linux)生态系统中的一个重要命令,主要用于恢复文件或目录的安全上下文标签。正确设置这些标签对于确保 SELinux 策略的有效执行至关重要。
要启用这个持久化,需要开启iptables开机自启: systemctl enable iptables
但是,一般不推荐启用iptables的默认持久化,因为像firewalld和docker等,都会自动维护一套iptables链,这些链都不会使用iptables的默认持久化。
如果启用iptables的默认持久化,那么在执行 service iptables save命令后,会把firewalld和docker生成的iptables链也持久化到 /etc/sysconfig/iptables 文件里面,而firewalld和docker维护的那部分iptables规则是动态的,持久化到 /etc/sysconfig/iptables里面不太合适。
如果一定要启用iptables的默认持久化,那就禁用 service iptables save 命令,采用手动维护 /etc/sysconfig/iptables 的方式,避免把firewalld和docker生成的链带入到/etc/sysconfig/iptables文件里。
/etc/sysconfig/iptables文件的默认内容:
|
|
在这个例子中:
*filter
标志着 filter 表的开始。:INPUT ACCEPT [0:0]
等定义了链的默认策略,这里表示如果没有任何规则匹配,那么默认接受所有流入的数据包。-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
添加了一条规则到 INPUT 链,这条规则接受所有已建立连接或相关联的数据包。-A INPUT -p icmp -j ACCEPT
接受所有的 ICMP 数据包(通常用于 ping 请求)。-A INPUT -i lo -j ACCEPT
接受所有通过本地回环接口(lo)的数据包。-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
接受所有新的 TCP 连接请求到达 SSH 服务(端口 22)。-A INPUT -j REJECT --reject-with icmp-host-prohibited 和 -A FORWARD -j REJECT --reject-with icmp-host-prohibited
拒绝所有其他未匹配的数据包,并发送主机禁止的消息作为回应。COMMIT
表明 filter 表的规则已经结束。
1.6 iptables 表的优先级
在 iptables 中,不同表的优先级从高到低分别是:
- raw 表:原始表,优先级最高。此表用于进行连接跟踪之前的处理,例如对数据包进行标记
- mangle 表:数据修改表,优先级次高。此表用于对数据包进行修改,例如修改TTL(Time To Live)、修改数据包的标记等
- nat 表:网络地址转换表,优先级较高。此表用于网络地址转换,例如端口转发、SNAT和DNAT等
- filter 表: 过滤表,优先级较低。此表用于过滤数据包,例如允许或阻止特定的数据包通过
- security表: 安全表,优先级最低。此表用于SELinux安全策略的处理,仅在SELinux启用时才使用
当一个网络数据包到达时,iptables 会按照这个顺序依次匹配每个表,找到第一个匹配的规则,并根据规则的动作进行处理。如果没有匹配任何规则,则默认执行 ACCEPT 操作。
1.7 经典iptables防火墙的写法
-A INPUT -j SUPERWHITE
-A INPUT -j SUPERBLACK
-A INPUT -j SPORD
...
-A SPORD -i lo -j ACCEPT
-A SPORD -m state --state RELATED,ESTABLISHED,UNTRACKED -j ACCEPT
-A SPORD -p tcp -m multiport --dports 9090 -j SPORD_tcp_9090
-A SPORD -p icmp -j ACCEPT
-A SPORD -j DROP
-A SPORD_tcp_9090 -s 172.31.0.11/32 -j ACCEPT
-A SPORD_tcp_9090 -j DROP
-A SUPERWHITE -s 172.0.0.1/21 - ACCEPT
-A SUPERWHITE -s 10.61.191.3/32 -j ACCEPT
1.8 -s-d和-i-o的区别
-s(源地址)与-d(目标地址):
- 作用:匹配数据包的IP地址或网段。
- 适用范围:可用于所有链(如INPUT、OUTPUT、FORWARD、PREROUTING、POSTROUTING)
-i(输入接口)与-o(输出接口):
- 作用:匹配数据包流经的网络接口(如eth0、docker0)
- 适用范围:
- -i:匹配数据包进入的网卡(仅用于INPUT、FORWARD、PREROUTING链)
- -o:匹配数据包离开的网卡(仅用于OUTPUT、FORWARD、POSTROUTING链)
1.9 JUMP到自定义链,自定义链跑完后会返回到原链继续匹配后续规则么?
JUMP到自定义链:若未匹配终止型动作,会返回到原链继续匹配后续规则
终止型动作:
- ACCEPT/DROP/REJECT
- MASQUERADE/SNAT/DNAT
2. iptables升级
|
|
3. nftables
4. conntrack-tools
本文发表于 0001-01-01,最后修改于 0001-01-01。
本站永久域名「 jiavvc.top 」,也可搜索「 后浪笔记一零二四 」找到我。