ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
[TOC] ### **官方文档** ![](https://img.kancloud.cn/b0/bd/b0bd5e445711e3fb83ae965303241dc4_1311x376.png) ### **详细解释** `MARK`这个扩展目标可以用来给数据包(Packet)打标记,由于连接追踪(Conntrack)也有标记,为了区分,约定把数据包的标记叫`nfmark`,把连接的标记叫`ctmark`,这一节我们讲的标记就是`nfmark`。 `nfmark`占四个字节32位,我们可以把它看成是一个长度为32位的无符号整数,一般用16进制来表示。 该目标有可以通过上面的五个选项中的某一个来设置数据包的标记,接下来我们来介绍一下。 * `--set-xmark value[/mask]` 上面的`value`和掩码`mask`都是32位无符号整数,一般用16进制表示。内核设置数据包nfmark值的流程分为两步:(1)首先,内核会先用mask预处理数据包原来的nfmark,处理方法是:如果mask的第N位(二进制)为1,那么将数据包的nfmark第的N位(二进制)设置为0 ,nfmark其他的位保持不变(2)接着,再用上面预处理后的nfmark和value做异或操作,得到数据包最后的nfmark值。 举个例子:假设我们设置了`--set-xmark 0x4000/0xffffffff`,掩码为`0xffffffff`,掩码表示为二进制的话32位都为`1`,那么内核首先会将数据包原来的`nfmark`所有的位都设置为`0`(相当于是先把nfmark置0),然后再和value做异或操作,那么得到的最后的nfmark值就是`0x4000`。所以,数据包经过这条规则后,它的nfmark值就是`0x4000`。 上面的掩码`mask`是个可选项,如果没有设置的话,默认为`0xffffffff`。 通过`--set-xmark value`可以快速设置数据包的nfmark值为`value`,可以自己推导一下(`0 XOR value = value`) * `--set-mark value[/mask]` 该设置方法上面类似,也是两步。第一步预处理和上面一样,第二步不同中,该方法是将预处理的nfmark和value做或(OR)操作。 通过`--set-mark value`可以快速设置数据包的nfmark值为`value`,可以自己推导一下(`0 OR value = value`)。 * `--and-mark bits` `bits`相当于就是上面的`value`,也是32位,16进制表示。该选项的意思就是:直接拿`bits`和数据包原来的nfmark做与(AND)操作,得到数据包新的nfmark。 它的效果和`--set-xmark 0/invbits`的效果是一样的,我们可以来推导一下。 `invbits`就是把`bits`中的位反过来,`1`的位变为`0`,`0`的位变为`1`。假设`bits`有n位为1,分别为第`X1,...,Xn`位,那么`--and-mark bits`的效果就是,**nfmark的第`X1,...,Xn`位保持不变,其他位都变为0**。然后再来看`--set-xmark 0/invbits`的效果:`invbits`的第`X1,...,Xn`位都为0,其他位都为1,那么nfmark经过`invbits`的预处理后,**nfmark的第`X1,...,Xn`位都保持不变,其他位都变成了0**,然后再与0做异或操作,而0与任何值做异或都是该值本身,所以nfmark的最终值就是经过invbits预处理之后的值,和`--and-mark bits`的效果是一样的。 * `--or-mark bits` 该选项的意思就是:直接拿`bits`和数据包原来的nfmark做或(OR)操作,得到数据包新的nfmark。 它的效果和`--set-xmark bits/bits`是一样的,可自己推导一下 * `--xor-mark bits` 该选项的意思就是:直接拿`bits`和数据包原来的nfmark做异或(XOR)操作,得到数据包新的nfmark。 它的效果和`--set-xmark bits/0`是一样的,可自己推导一下 ### **Terminating Or Non-Terminating** Non-Terminating ### **示例1** 上面我们有五种方法来设置数据包的nfmark。比如说,我们添加如下一条规则,把源地址为1.1.1.1的数据包的nfmark值设置为`0x1`,然后查看这条规则 ``` $ iptables -t mangle -A PREROUTING -s 1.1.1.1 -j MARK --set-mark 0x1 $ iptables -t mangle -nL PREROUTING Chain PREROUTING (policy ACCEPT) target prot opt source destination ... MARK all -- 1.1.1.1 0.0.0.0/0 MARK set 0x1 ``` `--set-mark 0x1`的效果就是不管原来的nfmark,直接把nfmark重新设置为`0x1`;所以我们在查看这条规则时,显示的`MARK set 0x1`就是这个意思。 接着,我们再添加如下一条规则,然后再查看 ``` $ iptables -t mangle -A PREROUTING -s 1.1.1.2 -j MARK --set-xmark 0x1/0x1 $ iptables -t mangle -nL PREROUTING Chain PREROUTING (policy ACCEPT) target prot opt source destination ... MARK all -- 1.1.1.2 0.0.0.0/0 MARK or 0x1 ``` 我们知道,`--set-xmark bits/bits`的效果和`--or-mark bits`是一样的,所在我们通过`--set-xmark 0x1/0x1`去设置nfmark,只不过显示的时候是`or 0x1`。 ### **示例2** * 问题 在k8s中,当我们发布一个Pod和一个Service,然后这个从这个Pod中通过CusterIP去访问这个Service,那么请求最终会转发到这个Pod本身。假设Pod的IP为`172.26.190.194`,Pod内服务的监听端口为`80`,ClusterIP为`10.110.161.77`,ServicePort为`80`,当Pod发出这个请求时,数据包四元组为`172.26.0.22:40000 -> 10.110.161.77:80`,那么**期望的回复包应该是`10.110.161.77:80 -> 172.26.0.22:40000`**。当Pod接收到这个请求时,数据包的四元组是`SourceIP:SourcePort -> 172.26.190.194:80`。那么**它的回复包是`172.26.190.194:80 -> SourceIP:SourcePort`**,很明显,实际的回复包与期望的回复包的源地址不一样。 那么问题来了,上面的`SourceIP:SourcePort`是什么?实际回复包`172.26.190.194:80 -> SourceIP:SourcePort`是如何转换成期望的回复包`10.110.161.77:80 -> 172.26.0.22:40000`的? * 验证 我们知道,当从pod里面访问clusterip时,数据包从Pod出来后,会进入到Pod所在的主机,那么此时会经过主机的PREROUTING链,通过查看我们发现在NAT表的PREROUTING链通过引用`KUBE-SERVICES`链最终会引用到如下一条链,该链有如下两条规则: ``` $ iptables -t nat -nL KUBE-SEP-RFYOGXIZRFRZCFLS Chain KUBE-SEP-RFYOGXIZRFRZCFLS (1 references) target prot opt source destination KUBE-MARK-MASQ all -- 172.26.190.195 0.0.0.0/0 DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp to: random persistent random persistent ``` 第一条规则的意思是做如果源地址是Pod的IP,就转到`KUBE-MARK-MASQ`链,我们来看一下这条链的内容,如下: ``` $ iptables -t nat -nL KUBE-MARK-MASQ Chain KUBE-MARK-MASQ (8 references) target prot opt source destination MARK all -- 0.0.0.0/0 0.0.0.0/0 MARK or 0x4000 ``` 可以看出,这条链对数据包进行了MARK:`--or-mark 0x4000`。这个动作的意思是:用数据包原来的nfmark值和`0x4000`进行或操作,那么效果就是nfmark的第18位(二进制从左到右)被设置为了1。这里可以提前说一下,在后面判断的时候,其实就是根据这一位是否为1来判断是否要做Masqurade。 然后我再看DNAT那条规则,它的意思就是做DNAT转换,把 ### **参考** * https://ipset.netfilter.org/iptables-extensions.man.html#lbDD