OVS CT连接跟踪(connection tracking)
CT连接跟踪中所说的“连接”,概念和 TCP/IP 协议中“面向连接”( connection oriented)的“连接”并不完全相同 TCP/IP 协议中,连接是一个四层(Layer 4)的概念。 TCP 是有连接的,或称面向连接的(connection oriented),发送出去的包都要求对端应答(ACK),并且有重传机制 UDP 是无连接的,发送的包无需对端应答,也没有重传机制
CT 中,一个元组(tuple)定义的一条数据流(flow )就表示一条连接(connection)。 UDP 甚至是 ICMP 这种三层协议在 CT 中也都是有连接记录的 但不是所有协议都会被连接跟踪,目前只支持以下六种协议:TCP、UDP、ICMP、DCCP、SCTP、GRE conntrack是一种状态跟踪和记录的机制,本身并不能过滤数据包,只是提供包过滤的依据,分为3个步骤: 1、拦截(或称过滤)流经这台机器的每一个数据包,并进行分析。 2、根据这些信息建立起这台机器上的连接信息数据库(conntrack table)。 3、根据拦截到的包信息,不断更新数据库。 rel:当icmp request发出后若网络不可达是相关报文 rpl:只有icmp reply是icmp request的回复报文
TCP三次握手
①:A -> B -trk ②:A -> B +trk+new ③:B -> A -trk ④:B -> A +trk+est ⑤:A -> B +trk+est
A发送syn报文:①+② B回复syn+ack报文:③+④ A回复ack报文:①+⑤ A和B数据传输:A-B:①+⑤,B-A:③+④ 四次挥手 A发送fin报文:①+⑤ B回复ack和fin报文:③+④ A回复ack:①+⑤
NAT应用:
NAT 网关(NAT Gateway)是一种支持 IP 地址转换服务,提供 SNAT 和 DNAT 能力,可为私有网络(VPC)内的资源提供安全、高性能的 Internet 访问服务。 NAT 网关可为 VPC 内多个无公网 IP 的服务器提供主动访问公网的能力,同时也支持将公网 IP 和端口映射到云服务器内网 IP 和端口,使得 VPC 内的服务器可被公网访问。 SNAT 支持 VPC 内多个服务器通过同一公网 IP 主动访问互联网。 DNAT 将外网 IP、协议、端口映射到 VPC 内的云服务器内网 IP、协议、端口,使得云服务器上的服务可被外网访问。
搭建环境验证
核心流表
ovs-ofctl add-flow br-int 'table=0,priority=10,ip,ct_state=-trk,action=ct(nat,table=1)'
ovs-ofctl add-flow br-int 'table=1,in_port=1,ip,ct_state=+trk+new-est-inv-rel,action=ct(nat(src=172.93.74.5-172.93.74.15:5000-50000),commit),mod_dl_src:xx:xx:xx:xx:xx:xx,mod_dl_dst:xx:xx:xx:xx:xx:xx,3'
ovs-ofctl add-flow br-int 'table=1,in_port=1,ip,ct_state=+trk+est-new-inv-rel,action=mod_dl_src:xx:xx:xx:xx:xx:xx,mod_dl_dst:xx:xx:xx:xx:xx:xx,3'
ovs-ofctl add-flow br-int 'table=1,in_port=3,ip,ct_state=+trk+est-new-inv-rel,action=mod_dl_src:xx:xx:xx:xx:xx:xx,mod_dl_dst:xx:xx:xx:xx:xx:xx,1'
环境准备
ip netns add ns1
ip netns add ns2
ovs-vsctl add-br br-int
ovs-vsctl add-br net-br
ovs-vsctl add-port br-int vif_1 -- set Interface vif_1 type=internal
ip link set vif_1 netns ns1
ip netns exec ns1 ip link set dev vif_1 up
ovs-vsctl add-port br-int vif_2 -- set Interface vif_2 type=internal
ip link set vif_2 netns ns2
ip netns exec ns2 ip link set dev vif_2 up
ip netns exec ns1 ip addr add 192.168.1.102/24 dev vif_1
ip netns exec ns2 ip addr add 192.168.1.1/24 dev vif_2
ip netns exec ns1 ip link set lo up
ip netns exec ns2 ip link set lo up
ip netns exec ns1 ping -c 1 192.168.1.102
ip netns exec ns1 ping -c 1 192.168.1.1
ovs-vsctl add-port br-int patch-ovs-0 -- set Interface patch-ovs-0 type=patch options:peer=patch-sw-1
ovs-vsctl add-port net-br patch-sw-1 -- set Interface patch-sw-1 type=patch options:peer=patch-ovs-0
ovs-vsctl add-port net-br eth0
ifconfig anet-br 172.93.73.4/16 up
route add default gw 172.93.1.1 dev net-br
route add 172.93.0.0 dev anet-br
ip addr flush dev eth0
NS1_MAC=ip netns exec ns1 ip a | grep ether | awk '{print $2}'
NS2_MAC=ip netns exec ns2 ip a | grep ether | awk '{print $2}'
NET_BR_MAC=ip a | grep net-br: -A1 | grep ether | awk '{print $2}'
HOST_MAC="00:50:56:95:b0:b2"
NS1_PORT=ovs-ofctl show br-int | grep vif_1 | awk -F '(' '{print $1}' | awk '{print $NF}'
NS2_PORT=ovs-ofctl show br-int | grep vif_2 | awk -F '(' '{print $1}' | awk '{print $NF}'
PATCH_PORT=ovs-ofctl show br-int | grep patch-ovs | awk -F '(' '{print $1}' | awk '{print $NF}'
ovs-ofctl add-flow br-int "table=0,priority=10,ip,ct_state=-trk,action=ct(nat,table=1)"
ovs-ofctl add-flow br-int "table=1,in_port=${NS1_PORT},ip,ct_state=+trk+new,action=ct(nat(src=172.93.73.4-172.93.73.4:5000-50000),commit,exec(set_field:0x2->ct_label)),mod_dl_src:${NET_BR_MAC},mod_dl_dst:${HOST_MAC},${PATCH_PORT}"
ovs-ofctl add-flow br-int "table=1,priority=10,in_port=${NS1_PORT},ip,ct_state=+trk+est,action=mod_dl_src:${NET_BR_MAC},mod_dl_dst:${HOST_MAC},${PATCH_PORT}"
ovs-ofctl add-flow br-int "table=1,priority=1,ct_label=0x2,ip,ct_state=+trk+est,action=mod_dl_src:${NET_BR_MAC},mod_dl_dst:${NS1_MAC},${NS1_PORT}"
03:57:56.625643 b2:68:6b:f5:f5:bf > 00:50:56:95:59:53, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 64, id 41522, offset 0, flags [DF], proto ICMP (1), length 84)
192.168.1.102 > 172.93.74.28: ICMP echo request, id 1355, seq 9, length 64
03:57:56.626220 00:50:56:95:59:53 > b2:68:6b:f5:f5:bf, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 64, id 65244, offset 0, flags [none], proto ICMP (1), length 84)
172.93.74.28 > 192.168.1.102: ICMP echo reply, id 1355, seq 9, length 64
03:57:48.459408 00:50:56:95:59:53 > 00:50:56:95:b0:b2, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 64, id 40494, offset 0, flags [DF], proto ICMP (1), length 84)
172.93.73.4 > 172.93.74.28: ICMP echo request, id 15933, seq 1, length 64
03:57:49.461041 00:50:56:95:b0:b2 > 00:50:56:95:59:53, ethertype IPv4 (0x0800), length 98: (tos 0x0, ttl 64, id 64042, offset 0, flags [none], proto ICMP (1), length 84)
172.93.74.28 > 172.93.73.4: ICMP echo reply, id 15933, seq 2, length 64
ovs-appctl dpctl/dump-conntrack -m | grep 172.93.74.28
icmp,orig=(src=192.168.1.102,dst=172.93.74.28,id=2167,type=8,code=0),reply=(src=172.93.74.28,dst=172.93.73.4,id=8934,type=0,code=0),status=SEEN_REPLY|CONFIRMED|SRC_NAT|SRC_NAT_DONE,labels=0x1
|