本文为 calico 3.7 版本
名词解释
endpoint: 接入到calico网络中的网卡称为endpoint
AS: 网络自治系统,通过BGP协议与其它AS网络交换路由信息
ibgp: AS内部的BGP Speaker,与同一个AS内部的ibgp、ebgp交换路由信息。
ebgp: AS边界的BGP Speaker,与同一个AS内部的ibgp、其它AS的ebgp交换路由信息。workloadEndpoint: 虚拟机、容器使用的 endpoint
hostEndpoints: 物理机(node)的地址
引用网上图片
基本步骤如下:
1. 数据包到达网络接口比 eth0
2. 进入 raw 表的 PREROUTING 链,这个链的作用是在连接跟踪之前处理数据包
3. 如果进行了连接跟踪,则进行处理
4. 进入 mangle 表的 PREROUTING 链,可以修改数据包,比如 TOS 等
5. 进入 nat 表的 PREROUTING 链,可以在此做 DNAT
6.
决定路由,看是交给本地主机
还是
转发给其它主机
一种情况就是数据包要
转发给其它主机
- 进入 mangle 表的 FORWARD 链,这里也比较特殊,这是在第一次路由决定之后,在进行最后的路由决定之前,仍然可以对数据包进行某些修改
- 进入 filter 表的 FORWARD 链,可以对所有转发的数据包进行过滤。需要注意的是:经过这里的数据包是转发的,方向是双向的。
- 进入 mangle 表的 POSTROUTING 链,到这里已经做完了所有的路由决定,但数据包仍然在本地主机,还可以进行某些修改。
- 进入 nat 表的 POSTROUTING 链,在这里一般都
是用来做 SNAT
- 进入出去的网络接口。完毕。
另一种情况是,数据包就是
发给本地主机的
7. 进入 mangle 表的 INPUT 链,这里是在路由之后,交由本地主机之前,也可以进行一些相应的修改
8. 进入 filter 表的 INPUT 链,在这里可以对流入的所有数据包进行过滤,无论它来自哪个网络接口
9. 交给本地主机的应用程序进行处理
10. 处理完毕后进行路由决定,看该发往哪里
11. 进入 raw 表的
OUTPUT 链
,这里是在连接跟踪处理本地的数据包之前12. 连接跟踪对本地的数据包进行处理。
13. 进入 mangle 表的 OUTPUT 链,在这里我们可以修改数据包
14. 进入 nat 表的 OUTPUT 链,可以对防火墙自己发出的数据做 NAT
15. 再次进行路由决定
16. 进入 filter 表的 OUTPUT 链,可以对本地出去的数据包进行过滤
17. 进入 mangle 表的 POSTROUTING 链,同上一种情况的第9步。注意,这里不光对经过防火墙的数据包进行处理,还对防火墙自己产生的数据包进行处理。
18. 进入 nat 表的 POSTROUTING 链
19. 进入出去的网络接口。完毕
node的报文处理过程
报文处理过程中使用的标记位:使用了3个标记位,0xf0000 对应的标记位
- 0x10000: 报文的处理动作,置1表示放行,默认0表示拒绝
- 0x20000: 是否已经经过了policy规则检测,置1表示已经过
- 0x40000: 报文来源,置1,表示来自 host-endpoint
流入的报文在路由决策之前的处理过程相同的,路由决策之后,分别进入
INPUT规则链和FORWARD链
- raw.PREROUTING -> mangle.PREROUTING -> nat.PREROUTING -> mangle.INPUT -> filter.INPUT
- raw.PREROUTING -> mangle.PREROUTING -> nat.PREROUTING -> mangle.FORWARD -> filter.FORWARD -> mangle.POSTROUTING -> nat.POSTROUTING
一. 路由决策之前:流入node的报文的处理
1. raw PREROUTING
*raw
:PREROUTING ACCEPT [18225340:4127986808]
:OUTPUT ACCEPT [18262870:4463777302]
:OUTPUT_direct – [0:0]
:PREROUTING_ZONES – [0:0]
:PREROUTING_ZONES_SOURCE – [0:0]
:PREROUTING_direct – [0:0]
:cali-from-host-endpoint – [0:0]
:cali-to-host-endpoint – [0:0]
-A PREROUTING -m comment –comment “cali:6gwbT8clXdHdC1b1” -j cali-PREROUTING
- -A cali-PREROUTING -m comment –comment “cali:XFX5xbM8B9qR10JG” -j MARK –set-xmark 0x0/0xf0000
- -A cali-PREROUTING -i cali+ -m comment –comment “cali:EWMPb0zVROM-woQp” -j MARK –set-xmark 0x40000/0x40000
- -A cali-PREROUTING -m comment –comment “cali:Ek_rsNpunyDlK3sH” -m mark –mark 0x0/0x40000 -j cali-from-host-endpoint
- -A cali-PREROUTING -m comment –comment “cali:nM-DzTFPwQbQvtRj” -m mark –mark 0x10000/0x10000 -j ACCEPT
规则1. 清除所有规则
规则2. 从网卡 cali+ 进入的数据包,设置 mark 0x40000/0x40000
规则3. 从非 cali+ 网卡进入的数据包,mark 为 0x0/0x40000 流转至 cali-from-host-endpoint 规则链
规则4. 从非 cali+ 网卡进入的数据包,mark 为 0x10000/0x10000 则允许数据包通过
2. nat PREROUTING
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [1:60]
:POSTROUTING ACCEPT [1:60]
-A PREROUTING -m comment –comment “cali:6gwbT8clXdHdC1b1” -j cali-PREROUTING
跳转至规则链 cali-PREROUTING
-A cali-POSTROUTING -m comment –comment “cali:Z-c7XtVd2Bq7s_hA” -j cali-fip-snat
-A cali-POSTROUTING -m comment –comment “cali:nYKhEzDlr11Jccal” -j cali-nat-outgoing
-A cali-PREROUTING -m comment –comment “cali:r6XmIziWUJsdOK6Z” -j cali-fip-dnat
-A cali-nat-outgoing -m comment –comment “cali:Dw4T8UWPnCLxRJiI” -m set –match-set cali40masq-ipam-pools src -m set ! –match-set cali40all-ipam-pools dst -j MASQUERADE
经过nat表之后,会进行路由决策:
二. 路由决策之后:发送到本机的 host endpoint 或 workload endpoint
3. INPUT filter
*filter
:INPUT ACCEPT [494:126858]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [493:130161]
-A INPUT -m comment –comment “cali:Cz_u1IQiXIMmKD4c” -j cali-INPUT
filter 表中 INPUT 规则链跳转至规则链 cali-INPUT
- -A cali-INPUT -m comment –comment “cali:d4znnv6_6rx6sE6M” -j MARK –set-xmark 0x0/0xfff00000
-
-A cali-INPUT -m comment –comment “cali:YHXh2XvaasL3jbTp” -j
cali-forward-check
- -A cali-INPUT -m comment –comment “cali:eL3eAQBTXQrID5PB” -m mark ! –mark 0x0/0xfff00000 -j RETURN
-
-A cali-INPUT -i cali+ -m comment –comment “cali:hwvMPJWpIRFo77b4” -g
cali-wl-to-host
- -A cali-INPUT -m comment –comment “cali:c3dtuPGUL9TVsB6Y” -m mark –mark 0x10000/0x10000 -j ACCEPT
- -A cali-INPUT -m comment –comment “cali:czgL26xl8reOnh13” -j MARK –set-xmark 0x0/0xf0000
-
-A cali-INPUT -m comment –comment “cali:EylNwA1nPRRCgK9T” -j
cali-from-host-endpoint
- -A cali-INPUT -m comment –comment “cali:JEbIi4mUTjL17qKC” -m comment –comment “Host endpoint policy accepted packet.” -m mark –mark 0x10000/0x10000 -j ACCEPT
-A
cali-forward-check
-m comment –comment “cali:Pbldlb4FaULvpdD8” -m conntrack –ctstate RELATED,ESTABLISHED -j RETURN
-A
cali-forward-check
-p tcp -m comment –comment “cali:ZD-6UxuUtGW-xtzg” -m comment –comment “To kubernetes NodePort service”
-m multiport –dports 30000:32767
-m set –match-set cali40this-host dst -g cali-set-endpoint-mark
-A
cali-forward-check
-p udp -m comment –comment “cali:CbPfUajQ2bFVnDq4” -m comment –comment “To kubernetes NodePort service”
-m multiport –dports 30000:32767
-m set –match-set cali40this-host dst -g cali-set-endpoint-mark
-A cali-forward-check -m comment –comment “cali:jmhU0ODogX-Zfe5g” -m comment –comment “To kubernetes service” -m set ! –match-set cali40this-host dst -j cali-set-endpoint-mark
三. 路由决策之后:需要转发的报文
fiter FORWARD
-A FORWARD -m comment –comment “cali:wUHhoiAYhphO9Mso” -j cali-FORWARD
nat POSTROUTING
-A cali-POSTROUTING -m comment –comment “cali:Z-c7XtVd2Bq7s_hA” -j cali-fip-snat
-A cali-POSTROUTING -m comment –comment “cali:nYKhEzDlr11Jccal” -j cali-nat-outgoing-A cali-nat-outgoing -m comment –comment “cali:Dw4T8UWPnCLxRJiI” -m set –match-set
cali40masq-ipam-pools
src -m set ! –match-set
cali40all-ipam-pools
dst -j MASQUERADE
Name:
cali40masq-ipam-pools
Type: hash:net
Revision: 3
Header: family inet hashsize 1024 maxelem 1048576
Size in memory: 16816
References: 1
Members:
192.170.0.0/16
Name:
cali40all-ipam-pools
Type: hash:net
Revision: 3
Header: family inet hashsize 1024 maxelem 1048576
Size in memory: 16816
References: 1
Members:
192.170.0.0/16
四. node本地发出的报文
nat OUTPUT
-A OUTPUT -m comment –comment “cali:tVnHkvAo15HuiPy0” -j cali-OUTPUT
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype –dst-type LOCAL -j DOCKER
-A cali-OUTPUT -m comment –comment “cali:GBTAv2p5CwevEyJm” -j cali-fip-dnat
filter OUTPUT
-A OUTPUT -m comment –comment “cali:tVnHkvAo15HuiPy0” -j cali-OUTPUT
-A cali-OUTPUT -m comment –comment “cali:Mq1_rAdXXH3YkrzW” -m mark –mark 0x10000/0x10000 -j ACCEPT
-A cali-OUTPUT -m comment –comment “cali:5Z67OUUpTOM7Xa1a” -m mark ! –mark 0x0/0xfff00000 -g cali-forward-endpoint-mark
-A cali-OUTPUT -o cali+ -m comment –comment “cali:M2Wf0OehNdig8MHR” -j RETURN
-A cali-OUTPUT -m comment –comment “cali:qO3aVIhjZ5EawFCC” -j MARK –set-xmark 0x0/0xf0000
-A cali-OUTPUT -m comment –comment “cali:3KrxsMf75t8rkLZn” -j cali-to-host-endpoint
-A cali-OUTPUT -m comment –comment “cali:fc01z4huRzkD5TWj” -m comment –comment “Host endpoint policy accepted packet.” -m mark –mark 0x10000/0x10000 -j ACCEPT
nat POSTROUTING
-A POSTROUTING -m comment –comment “cali:O3lYWMrLQYEMJtB5” -j cali-POSTROUTING
-A POSTROUTING -s 192.170.80.0/24 ! -o docker0 -j MASQUERADE
-A cali-POSTROUTING -m comment –comment “cali:Z-c7XtVd2Bq7s_hA” -j cali-fip-snat
-A cali-POSTROUTING -m comment –comment “cali:nYKhEzDlr11Jccal” -j cali-nat-outgoing
-A cali-nat-outgoing -m comment –comment “cali:Dw4T8UWPnCLxRJiI” -m set –match-set cali40masq-ipam-pools src -m set ! –match-set cali40all-ipam-pools dst -j MASQUERADE
iptables 规则
格式:iptables [-t table] COMMAND chain CRETIRIA -j ACTION
- COMMAND:定义如何对规则进行管理
- chain:指定你接下来的规则到底是在哪个链上操作的,当定义策略的时候,是可以省略的
- CRETIRIA:指定匹配标准
- -j ACTION :指定如何进行处理
通用匹配:源地址目标地址的匹配
-s:指定作为源地址匹配,这里不能指定主机名称,必须是IP
-d:表示匹配目标地址
-p:用于匹配协议的(这里的协议通常有3种,TCP/UDP/ICMP)
-i eth0:从这块网卡流入的数据
-m multiport:表示启用多端口扩展
状态检测
TCP协议是一个有连接的协议,三次握手中,第一次握手,我们就叫
NEW
连接,第二次握手以后的,ack 都为1,这是正常的数据传输,和 tcp 的第二次第三次握手,叫做已建立的连接(
ESTABLISHED
),还有一种状态,比较诡异的,比如:SYN=1 ACK=1 RST=1,对于这种无法识别的,为
INVALID
无法识别的。还有第四种,FTP这种古老的拥有的特征,每个端口都是独立的,21号和20号端口都是一去一回,他们之间是有关系的,这种关系我们称之为
RELATED
- NEW:主机连接目标主机,在目标主机上看到的第一个想要连接的包
- ESTABLISHED: 主机已与目标主机进行通信,判断标准只要目标主机回应了第一个包,就进入该状态。
- RELATED: 主机已与目标主机进行通信,目标主机发起新的链接方式,例如ftp
- INVALID: 无效的封包,例如数据破损的封包状态
-m 模块
常用规则匹配器 | 说明 |
---|---|
-p tcp/udp/icmp/all | 匹配协议,all会匹配所有协议 |
-s addr[/mask] | 匹配源地址 |
-d addr[/mask] | 匹配目标地址 |
–sport port1[:port2] | 匹配源端口(可指定连续的端口) |
–dport port1[:port2] | 匹配目的端口(可指定连续的端口) |
-o interface | 匹配出口网卡,只适用FORWARD、POSTROUTING、OUTPUT(例:iptables -A FORWARD -o eth0) |
-i interface | 匹配入口网卡,只使用PREROUTING、INPUT、FORWARD。 |
–icmp-type | 匹配icmp类型(使用iptables -p icmp -h可查看可用的ICMP类型) |
–tcp-flags mask comp | 匹配TCP标记,mask表示检查范围,comp表示匹配mask中的哪些标记。(例:iptables -A FORWARD -p tcp –tcp-flags ALL SYN,ACK -j ACCEPT 表示匹配SYN和ACK标记的数据包) |
目标动作 | 说明 |
---|---|
ACCEPT | 允许数据包通过 |
DROP | 丢弃数据包 |
REJECT | 丢弃数据包,并且将拒绝信息发送给发送方 |
SNAT | 源地址转换(在nat表上)例:iptables -t nat -A POSTROUTING -d 192.168.0.102 -j SNAT –to 192.168.0.1 |
DNAT | 目标地址转换(在nat表上)例:iptables -t nat -A PREROUTING -d 202.202.202.2 -j DNAT –to-destination 192.168.0.102 |
REDIRECT | 目标端口转换(在nat表上)例:iptables -t nat -D PREROUTING -p tcp –dport 8080 -i eth2.2 -j REDIRECT –to 80 |
MARK | 将数据包打上标记;例:iptables -t mangle -A PREROUTING -s 192.168.1.3 -j MARK –set-mark 60 |
[!] –match-set
setname flag [, flag ].. ,其中flag是用逗号分隔的src或dst规范的列表,其中最多只能有6个。
|
mark值有何意义
mark字段的值是一个无符号的整数,在32位系统上最大可以是4294967296(就是2的32次方),这足够用的了。比如对一个流或从某台机子发出的所有的包设置了mark值,就可以利用高级路由功能来对它们进行流量控制等操作了。
mark值不是包本身的一部分,
而是在包穿越计算机的过程中由内核分配的
和它相关联的一个字段
。它可能被用来改变包的传输路径或过滤。
mark值只在本机有意义
!
在本机给包设置关联的mark值后,可通过该值对包后续的传输进行控制(排队,流量控制等)。
mark的格式是
–mark value[/mask]
,如上面的例子是没有掩码的,带掩码的例子如
–mark 1/1
。如果指定了掩码,就先把mark值和掩码取逻辑与,然后再和包的mark值比较