searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

openvswitch 中的 ovs-conntrack模块介绍

2024-09-05 09:26:30
92
0

简介:

OVS可以与连接跟踪系统一起使用,其中可以使用OpenFlow流来匹配TCP、UDP、ICMP等连接的状态。(连接跟踪系统支持跟踪全状态和无状态协议)。
本教程演示了OVS如何使用连接跟踪系统来匹配从连接建立到连接断开的TCP段。它将使用带有Linux内核模块的OVS作为本教程的数据路径。(在Linux内核中利用OpenvSwitch内核模块进行报文处理的数据路径)

 

定义:

conntrack是一个用于状态数据包检测的连接跟踪模块

pipeline是数据包处理pineline,它是数据包在遍历与表中流的匹配字段匹配的表时所采用的路径,并执行匹配的流中存在的操作

network namespace:是在Linux内核的单个实例中创建虚拟路由域的一种方法。每个网络命名空间都有自己的网络表实例(ARP、路由)以及与之相连的某些接口

flow:本教程中使用的是指可以使用OpenFlow控制器或OVS命令行工具(如这里使用的ovs-ofctl)编程的OpenFlow流。流将具有匹配的字段和操作。

 

Match Fields 相关字段:

连接跟踪字段摘要

名称 字节数 掩码 可写? 先决条件 NXM/OXM支持
ct_state 4 OVS 2.5+
ct_zone 2 OVS 2.5+
ct_mark 4 OVS 2.5+
ct_label 16 OVS 2.5+
ct_nw_src 4 CT OVS 2.8+
ct_nw_dst 4 CT OVS 2.8+
ct_ipv6_src 16 CT OVS 2.8+
ct_ipv6_dst 16 CT OVS 2.8+
ct_nw_proto 1 CT OVS 2.8+
ct_tp_src 2 CT OVS 2.8+
ct_tp_dst 2 CT OVS 2.8+

连接跟踪概述

Open vSwitch 支持“连接跟踪”功能,它使得双向数据包流能够按状态被分组为连接。例如,OVS的连接跟踪功能能识别TCP数据包的模式,表明一个连接的成功建立或断开。此外,OVS的连接跟踪还可以识别相关联的连接,如从FTP控制连接派生出来的FTP数据连接。

字段解释

  • ct_state: 占4字节,有掩码,不可写,无先决条件。代表连接状态,如新建、已建立或断开。

  • ct_zone: 占2字节,无掩码,不可写,无先决条件。用于标识连接的安全区域。

  • ct_mark: 占4字节,有掩码,可写,无先决条件。用于标记连接,便于进一步过滤或处理。

  • ct_label: 占16字节,有掩码,可写,无先决条件。用于给连接打标签,增加连接的可区分性。

  • ct_nw_src 和 ct_nw_dst: 各占4字节,有掩码,不可写,需要CT功能启用。分别表示连接的源和目的IPv4地址。

  • ct_ipv6_src 和 ct_ipv6_dst: 各占16字节,有掩码,不可写,需要CT功能启用。分别表示连接的源和目的IPv6地址。

  • ct_nw_proto: 占1字节,无掩码,不可写,需要CT功能启用。表示网络层协议类型。

  • ct_tp_src 和 ct_tp_dst: 各占2字节,有掩码,不可写,需要CT功能启用。分别表示传输层的源和目的端口号。

这些字段提供了丰富的信息,使得OVS能够智能地处理和管理连接,例如在防火墙规则、负载均衡或安全策略中应用。"不可写"(read-only)指的是这个字段的值不能被用户或系统管理员直接修改。它是由内核根据连接跟踪的状态自动更新和维护的。

 

连接跟踪器在内部表中存储连接状态,但只有当针对新连接的 ct 动作以 commit 参数调用时,它才会向此表添加新条目。对于给定的连接,如果管道已经执行了 ct 动作但尚未使用 commit,则该连接被称为未提交的。未提交的连接状态是临时的,不会在管道结束后持续存在,因此某些功能仅对已提交的连接可用。通常,将连接保持为未提交状态是一种机制,用于在不需要维护长期状态的情况下快速处理和丢弃数据包。例如,在检测到恶意或异常数据包时,可以将连接设置为未提交状态,从而避免为这些连接分配和维护不必要的状态信息,提高系统的效率和安全性。此外,对于一些短暂存在的连接,如某些类型的网络探测或扫描请求,也可以选择将其保持为未提交状态,以减少不必要的资源消耗

1. ct_state:与数据包匹配的连接状态

  • new (0x01):表示一个新的连接。如果这是一个未提交的连接,则设置为1。

  • est (0x02):表示现有连接的一部分。如果已提交的连接的数据包被连接跟踪器从两个方向看到,则设置为1。

  • rel (0x04):表示与现有连接相关联,例如ICMP"目的地不可达"消息或FTP数据连接。只有当与之相关的连接已提交时,该标志才会设置为1。

  • rpl (0x08):表示数据包处于回复方向,即与发起连接的数据包方向相反。只有在连接已提交时,该标志才会设置为1。

  • inv (0x10):表示状态无效,即连接跟踪器无法识别连接。这是对连接或连接跟踪器出现问题的总括,如:

    • L3/L4协议处理器未加载或不可用。

    • 数据包格式不正确。

    • 数据包长度不符合协议预期。

  • trk (0x20):表示数据包已被跟踪,即先前已经通过了连接跟踪器。如果这个标志未设置,其他标志也不会设置。如果设置,数据包则被标记为已跟踪,其他标志也可能被设置。

  • snat (0x40):表示数据包已被先前的ct动作进行了源地址/端口转换。Open vSwitch 2.6版本新增了这个标志。

  • dnat (0x80):表示数据包已被先前的ct动作进行了目标地址/端口转换。Open vSwitch 2.6版本新增了这个标志。

 

ct_state字段用于表示数据包所属连接的状态。这个字段可以通过符号名来匹配,每个符号名前缀可以是"+"表示必须设置的标志,或者是"-"表示必须未设置的标志,中间不使用其他分隔符。未提及的标志则视为通配符。例如,tcp,ct_state=+trk-new匹配的是已经被连接跟踪器处理过但并未建立新连接的TCP数据包。匹配也可以用数字形式表示为flags/mask,其中flags和mask都是32位的十进制或十六进制数值。

每个标志前面都有一个“+”,表示必须设置的标志,或者“-”,表示必须取消设置的标志。还可以指定多个标志,例如ct_state=+trk+new。我们将在下面看到其中一些标志的用法。

在Open vSwitch(一个开源的虚拟交换机)的管道中,一个单独的数据包(packet)可能处于两种状态之一:“未跟踪”(untracked)或“已跟踪”(tracked),这两种状态可以通过ct_state中的trk标志来区分。

  • 未跟踪(untracked):数据包在Open vSwitch管道的开始时处于未跟踪状态,并且会保持未跟踪状态,直到管道调用ct动作。在未跟踪的数据包中,连接跟踪字段的值都是零。

  • 已跟踪(tracked):当Open vSwitch管道中的某个流(flow)调用ct动作时,该动作会初始化连接跟踪字段,并且数据包在其后续的处理过程中将被视为已跟踪。

简单来说,当一个数据包进入Open vSwitch时,它默认是未跟踪的。但是,如果某个流规则(flow rule)指定了要对该数据包执行ct动作(通常用于启动或更新连接跟踪信息),那么该数据包就会变为已跟踪状态,并且其连接跟踪字段会被初始化或更新。这对于实现如防火墙、NAT(网络地址转换)等功能非常重要,因为这些功能通常需要知道数据包所属的连接信息。

 

连接跟踪(conntrack)标志之间的关系和它们的使用限制:

  1. 如果trk未设置,则其他标志也不会设置

    • 如果连接跟踪(trk)标志没有被设置(即数据包没有通过连接跟踪器处理),那么其他所有标志(如newestrelrplinv)都不会被设置。

  2. 如果trk已设置,则可能设置一个或多个其他标志

    • 一旦数据包通过了连接跟踪器(即trk被设置),其他标志(newestrelrpl)中的一个或多个可能也会被设置,以表示数据包在连接中的状态。

  3. 如果inv被设置,则只有trk标志也会被设置

    • 如果数据包的状态是无效的(inv被设置),那么只有trk标志也会被设置,表示数据包至少经过了连接跟踪器的处理,但状态无效。

  4. new和est是互斥的

    • 一个数据包不能同时被标记为新的连接(new)和已建立的连接(est)。这是因为在连接的生命周期中,一个连接开始时是新的(new),一旦完成握手过程,它就会变成已建立的(est)。

  5. new和rpl是互斥的

    • 一个数据包不能同时被标记为新的连接(new)和回复方向的数据包(rpl)。因为回复方向的数据包总是与已存在的连接相关,而新的连接还没有开始产生回复。

  6. rel可以与任何其他标志结合设置

    • rel标志(表示与现有连接相关的数据包)可以与任何其他标志(newestrpl)一起设置。这意味着相关连接可以是新的、已建立的或回复方向的。

这些约束条件确保了在应用连接跟踪规则时,标志之间的逻辑关系和状态转换是清晰和一致的。


2. ct_zone:连接跟踪区域

代表一个独立的连接跟踪上下文。ct_zone 是一个16位的字段,主要用于区分不同的连接跟踪环境。当一个数据包通过OVS时,连接跟踪 (ct) 动作可以设置 ct_zone 的值。这个值由最近执行的 ct 动作确定(通常是通过OpenFlow流规则作用于一个连接跟踪条目上),并且可以作为另一个流条目中的匹配字段来使用。

ct_zone 的主要用途在于,它允许网络管理员或自动控制系统在OVS中创建多个独立的连接跟踪环境。每个 ct_zone 实质上都是一个独立的连接跟踪表,数据包的连接状态只在这个特定的上下文中被跟踪。这意味着,如果一个数据包在不同的 ct_zone 中出现,它可以被视为两个完全独立的连接,即使它们可能具有相同的五元组(源IP、目的IP、源端口、目的端口和协议类型)。

这种机制在需要对不同类别的流量进行隔离跟踪的场景下特别有用,例如,你可以为不同业务部门的流量分配不同的 ct_zone,这样即使两个部门之间的流量具有相同的目的地和源地址,它们仍然会被视为独立的连接,从而可以单独地进行状态跟踪和管理。

ct_zone 的设置和使用,增加了OVS在复杂网络环境中的灵活性和功能性。通过精心设计的流规则,网络管理员可以利用 ct_zone 来实现高级的流量控制策略,如基于连接状态的负载均衡、安全策略实施以及故障隔离等。

值得注意的是,ct_zone 的值是由 ct 动作设置的,而这个动作可以出现在OVS的流表中。当一个数据包首次到达OVS时,如果没有匹配到任何带有 ct 动作的流规则,那么它将默认处于未跟踪状态,此时 ct_zone 的值为零。一旦一个数据包被某个带有 ct 动作的流规则匹配,并设置了 ct_zone 的值,那么这个数据包及其后续属于同一连接的所有数据包都会在指定的 ct_zone 上下文中被跟踪。

3. ct_mark:连接跟踪标记字段

被用于标记当前数据包所属的连接。当某个动作在ct动作(连接跟踪动作)的exec参数中被执行时,这个ct_mark元数据会被提交(或设置)到当前数据包所属的连接上。这样,随后的数据包属于同一个连接时,就可以使用这个标记来进行特定的处理或策略应用。

ct_mark 的主要用途在于,它允许网络管理员或自动控制系统在连接层面应用精细的策略。通过为不同的连接分配不同的标记,可以基于这些标记来实施流量控制、安全策略、QoS(Quality of Service)规则等。例如,一个特定的标记可能指示连接属于高优先级的流量,而另一个标记则可能指示连接涉及敏感数据,需要额外的安全检查。

在 OpenFlow 管道中,ct_mark 可以作为一个匹配字段,这意味着可以在后续的流规则中引用它来做出基于连接标记的决策。例如,一个流规则可能指定 "if ct_mark == X, then forward to port Y",这意味着所有具有标记 X 的连接的数据包将被转发到端口 Y。

值得注意的是,ct_mark 的值是在连接建立时设置的,并且在连接的生命周期中保持不变,除非有额外的动作显式地改变了这个值。这意味着,一旦一个连接被标记,所有属于这个连接的数据包都将携带相同的标记,直到连接终止。

此外,ct_mark 的可读写特性意味着它不仅可以用于读取和匹配,还可以通过管道中的动作来更新。这为动态调整连接的标记提供了可能性,例如,响应外部事件或根据网络状况的变化重新分类流量。

4. ct_lable:连接跟踪标签字段

ct_mark类似,ct_label字段允许网络管理员给特定的连接分配一个更大的标签,以进行后续的流量管理或策略应用。

 

允许网络管理员根据需要对网络连接进行分类和管理。例如,管理员可以给来自特定源或目的地的连接分配一个特定的标签,然后基于这个标签来应用特定的流量控制策略,如限速、路由重定向等。

由于ct_label是一个128位的字段,它提供了比ct_mark(32位)更大的范围,因此可以支持更多的连接分类和策略应用

 

5. ct_nw_src / ct_ipv6_src

 

ct_nw_srcct_ipv6_src 是Open vSwitch中用于连接跟踪的字段,它们分别用于匹配IPv4和IPv6连接的原始方向元组的源地址。这两个字段在Open vSwitch 2.8版本中被引入,用于存储和识别连接最初建立时的源地址信息。

ct_nw_src:这用于IPv4的连接跟踪源地址匹配。例如,如果你想匹配所有原始源地址为192.168.1.1的连接上的数据包,你可以使用ct_nw_src表达式。

ct_ipv6_src:这用于IPv6的连接跟踪源地址匹配。与IPv4类似,但用于IPv6地址。

这两个字段的存在使得Open vSwitch能够准确地跟踪连接的源头,即使在NAT(网络地址转换)或连接状态发生变化时也能保持对原始源地址的记录。这对于处理复杂网络环境中的流量控制、安全策略实施以及故障排查等任务至关重要。例如,防火墙规则可以基于这些字段来允许或拒绝特定来源的连接;负载均衡器可以依据这些信息来决定如何分发连接;而网络监控系统则可以利用它们来分析和可视化网络流量模式。

综上所述,ct_nw_srcct_ipv6_src 在Open vSwitch的连接跟踪功能中扮演着核心角色,确保了网络管理者能够对网络中的连接有深入的理解和精细的控制。

 

6. ct_nw_dst / ct_ipv6_dst

ct_nw_dstct_ipv6_dst 是 Open vSwitch (OVS) 中用于连接跟踪的字段,分别用于匹配 IPv4 和 IPv6 连接的原始方向元组的目标地址。这些字段允许网络管理员或自动化系统基于连接的最初目标地址来制定精细的策略和过滤规则。

ct_nw_dst: 这是用于 IPv4 地址的连接跟踪原始方向目标地址的匹配条件。当你想基于 IPv4 数据包的连接跟踪信息中的目标地址来过滤数据包时,你会使用这个条件。

ct_ipv6_dst: 这是用于 IPv6 地址的连接跟踪原始方向目标地址的匹配条件。与 ct_nw_dst 类似,但它是为 IPv6 数据包设计的。

 

7. ct_nw_proto

ct_nw_proto 是一个与 Linux 内核的 Connection Tracking (conntrack) 模块相关的网络过滤器条件,它用于匹配连接跟踪条目中原始方向(即从外部系统到内部系统的连接)的 IP 协议类型

在网络过滤规则(如 iptables 规则)中,ct_nw_proto 可以用来基于 IP 协议类型(如 TCP、UDP、ICMP 等)来过滤流量。这允许你针对特定协议类型应用不同的策略

 

8. ct_tp_src

匹配连接跟踪原始方向元组传输源端口

 

9. ct_tp_dst

匹配连接跟踪原始方向元组传输目的端口

 

Action 相关字段

ct 动作是 Open vSwitch (OVS) 中的一个功能,它允许数据包通过连接跟踪器 (conntrack) 进行处理。

ct 动作可以用来修改或查询这些连接的状态。

以下是 ct 动作支持的一些参数的详细解释:

  1. commit

    • 将连接提交给连接跟踪模块,一旦连接被提交,即使与该连接相关的数据包已经通过 Open vSwitch 流水线并被处理,连接状态信息仍然会被保留在连接跟踪模块中

  2. force

    • 除以上的commit标志外,还可以使用force标志来有效地终止现有连接并在当前方向开始新连接

  3. table=number

    用于指定数据包接下来应该被发送到的流水线(Pipeline)的表(Table),数据包的处理流程被分叉为两个路径:数据包的原始实例将继续按照当前的动作列表处理,而不进行连接跟踪(作为未跟踪的包)。同时,数据包的另一个实例将被发送到连接跟踪器,一旦连接跟踪完成,该实例将带有新的ct_state和其他连接跟踪相关的匹配字段(如源/目标IP、端口等)重新注入到OpenFlow流水线中的指定表(由table=number指定)。

  4. zone=value OR zone=src[start..end]

    一个 16 位的上下文 ID,可用于将连接隔离到不同的域中,允许不同区域中的网络地址重叠。如果没有提供区域,则默认使用区域零。

  5. exec([action][,action…])

    • 在连接跟踪的上下文中执行受限的动作集。在 exec 动作内部,仅允许修改 ct_mark 或 ct_label 字段的动作。

  6. alg=<ftp/tftp>

    • 指定要跟踪的特定连接类型的应用层网关 (ALG)。例如,可以跟踪 FTP 或 TFTP 连接,以便正确地处理与这些协议相关的命令和数据连接。

  7. nat

    • 指定要跟踪的连接的地址和端口转换。这通常与 NAT(网络地址转换)相关,允许您更改数据包的源或目标 IP 地址和端口。

 

实验:

1.基础互通

创建namespace
ip netns add left

ip netns add right

创建虚拟端口,并加入到namespace和ovs 桥

ip link add veth_l0 type veth peer name veth_l1

ip link set veth_l1 netns left

ip link add veth_r0 type veth peer name veth_r1

ip link set veth_r1 netns right

ip link set veth_l0 up

ip link set veth_r0 up

ovs-vsctl add-br br0

ovs-vsctl add-port br0 veth_l0 ovs-vsctl add-port br0 veth_r0

给veth_l1 veth_r1 配置地址并up接口

ip netns exec left ip link set lo up

ip netns exec left ip addr add  192.168.0.2/24 dev veth_l1

ip netns exec left ip link set veth_l1 up

ip netns exec right ip link set lo up

ip netns exec right ip addr add  10.0.0.2/24 dev veth_r1

ip netns exec right ip link set veth_r1 up

添加流表

ovs-ofctl add-flow br0  "table=0, priority=10, in_port=veth_l0, actions=veth_r0"

ovs-ofctl add-flow br0 "table=0, priority=10, in_port=veth_r0, actions=veth_l0"

ip netns exec left scapy

sendp(Ether()/IP(src="192.168.0.2", dst="10.0.0.2")/TCP(sport=1024, dport=2048, flags=0x02, seq=100), iface="veth_l1")

在veth_l1 veth_r1抓包


2.添加流表来启动"tracking"跟踪OVS中接收到的报文

a.来自客户端方向的TCP SYN报文

        ovs-ofctl add-flow br0 "table=0, priority=50, ct_state=-trk, tcp, in_port=veth_l0, actions=ct(table=0)"

        ovs-ofctl add-flow br0 "table=0, priority=50, ct_state=+trk+new, tcp, in_port=veth_l0, actions=ct(commit),veth_r0"

 

    发tcp syn包

    sendp(Ether()/IP(src="192.168.0.2", dst="10.0.0.2")/TCP(sport=1024, dport=2048, flags=0x02, seq=100), iface="veth_l1")

 

b.对于来自相反/服务器方向的TCP SYN+ACK报文

        ovs-ofctl add-flow br0  "table=0, priority=50, ct_state=-trk, tcp, in_port=veth_r0, actions=ct(table=0)"

        ovs-ofctl add-flow br0  "table=0, priority=50, ct_state=+trk+est, tcp, in_port=veth_r0, actions=veth_l0"

                      

        发送tcp syn+ack包

        sendp(Ether()/IP(src="10.0.0.2",dst="192.168.0.2")/TCP(sport=2048,dport=1024,flags=0X12,seq=201,ack=102),iface="veth_r1")

TCP SYN+ACK报文经过conntrack处理后,其ct_state设置了"est"连接建立标志。

在只接收到SYN和SYN ACK报文后,conntrack的状态成为"ESTABLISHED"。但此时,如果它没有收到第三个ACK报文(来自客户端),此连接很快会从conntrack中清除。

 

c.来自客户端方向的TCP ACK报文

    ovs-ofctl add-flow br0 "table=0, priority=50, ct_state=+trk+est, tcp, in_port=veth_l0, actions=veth_r0"

发送第三个TCP ACK报文

        sendp(Ether()/IP(src="192.168.0.2", dst="10.0.0.2")/TCP(sport=1024, dport=2048, flags=0x10, seq=101, ack=201), iface="veth_l1")

conntrack状态保持在"ESTABLISHED"状态,但现在它已经收到来自客户端的ACK,即使没有接收此连接上的任何数据,其也将保持此状态很长时间。 

 

拆除连接

客户端发送FIN+ACK

sendp(Ether()/IP(src="192.168.0.2", dst="10.0.0.2")/TCP(sport=1024, dport=2048, flags=0x11, seq=102, ack=201), iface="veth_l1")

服务端发送FIN+ACK

sendp(Ether()/IP(src="10.0.0.2", dst="192.168.0.2")/TCP(sport=2048, dport=1024, flags=0X11, seq=201, ack=103), iface="veth_r1")

客户端发送ACK

sendp(Ether()/IP(src="192.168.0.2", dst="10.0.0.2")/TCP(sport=1024, dport=2048, flags=0x10, seq=103, ack=202), iface="veth_l1")

0条评论
0 / 1000
y****n
1文章数
0粉丝数
y****n
1 文章 | 0 粉丝
y****n
1文章数
0粉丝数
y****n
1 文章 | 0 粉丝
原创

openvswitch 中的 ovs-conntrack模块介绍

2024-09-05 09:26:30
92
0

简介:

OVS可以与连接跟踪系统一起使用,其中可以使用OpenFlow流来匹配TCP、UDP、ICMP等连接的状态。(连接跟踪系统支持跟踪全状态和无状态协议)。
本教程演示了OVS如何使用连接跟踪系统来匹配从连接建立到连接断开的TCP段。它将使用带有Linux内核模块的OVS作为本教程的数据路径。(在Linux内核中利用OpenvSwitch内核模块进行报文处理的数据路径)

 

定义:

conntrack是一个用于状态数据包检测的连接跟踪模块

pipeline是数据包处理pineline,它是数据包在遍历与表中流的匹配字段匹配的表时所采用的路径,并执行匹配的流中存在的操作

network namespace:是在Linux内核的单个实例中创建虚拟路由域的一种方法。每个网络命名空间都有自己的网络表实例(ARP、路由)以及与之相连的某些接口

flow:本教程中使用的是指可以使用OpenFlow控制器或OVS命令行工具(如这里使用的ovs-ofctl)编程的OpenFlow流。流将具有匹配的字段和操作。

 

Match Fields 相关字段:

连接跟踪字段摘要

名称 字节数 掩码 可写? 先决条件 NXM/OXM支持
ct_state 4 OVS 2.5+
ct_zone 2 OVS 2.5+
ct_mark 4 OVS 2.5+
ct_label 16 OVS 2.5+
ct_nw_src 4 CT OVS 2.8+
ct_nw_dst 4 CT OVS 2.8+
ct_ipv6_src 16 CT OVS 2.8+
ct_ipv6_dst 16 CT OVS 2.8+
ct_nw_proto 1 CT OVS 2.8+
ct_tp_src 2 CT OVS 2.8+
ct_tp_dst 2 CT OVS 2.8+

连接跟踪概述

Open vSwitch 支持“连接跟踪”功能,它使得双向数据包流能够按状态被分组为连接。例如,OVS的连接跟踪功能能识别TCP数据包的模式,表明一个连接的成功建立或断开。此外,OVS的连接跟踪还可以识别相关联的连接,如从FTP控制连接派生出来的FTP数据连接。

字段解释

  • ct_state: 占4字节,有掩码,不可写,无先决条件。代表连接状态,如新建、已建立或断开。

  • ct_zone: 占2字节,无掩码,不可写,无先决条件。用于标识连接的安全区域。

  • ct_mark: 占4字节,有掩码,可写,无先决条件。用于标记连接,便于进一步过滤或处理。

  • ct_label: 占16字节,有掩码,可写,无先决条件。用于给连接打标签,增加连接的可区分性。

  • ct_nw_src 和 ct_nw_dst: 各占4字节,有掩码,不可写,需要CT功能启用。分别表示连接的源和目的IPv4地址。

  • ct_ipv6_src 和 ct_ipv6_dst: 各占16字节,有掩码,不可写,需要CT功能启用。分别表示连接的源和目的IPv6地址。

  • ct_nw_proto: 占1字节,无掩码,不可写,需要CT功能启用。表示网络层协议类型。

  • ct_tp_src 和 ct_tp_dst: 各占2字节,有掩码,不可写,需要CT功能启用。分别表示传输层的源和目的端口号。

这些字段提供了丰富的信息,使得OVS能够智能地处理和管理连接,例如在防火墙规则、负载均衡或安全策略中应用。"不可写"(read-only)指的是这个字段的值不能被用户或系统管理员直接修改。它是由内核根据连接跟踪的状态自动更新和维护的。

 

连接跟踪器在内部表中存储连接状态,但只有当针对新连接的 ct 动作以 commit 参数调用时,它才会向此表添加新条目。对于给定的连接,如果管道已经执行了 ct 动作但尚未使用 commit,则该连接被称为未提交的。未提交的连接状态是临时的,不会在管道结束后持续存在,因此某些功能仅对已提交的连接可用。通常,将连接保持为未提交状态是一种机制,用于在不需要维护长期状态的情况下快速处理和丢弃数据包。例如,在检测到恶意或异常数据包时,可以将连接设置为未提交状态,从而避免为这些连接分配和维护不必要的状态信息,提高系统的效率和安全性。此外,对于一些短暂存在的连接,如某些类型的网络探测或扫描请求,也可以选择将其保持为未提交状态,以减少不必要的资源消耗

1. ct_state:与数据包匹配的连接状态

  • new (0x01):表示一个新的连接。如果这是一个未提交的连接,则设置为1。

  • est (0x02):表示现有连接的一部分。如果已提交的连接的数据包被连接跟踪器从两个方向看到,则设置为1。

  • rel (0x04):表示与现有连接相关联,例如ICMP"目的地不可达"消息或FTP数据连接。只有当与之相关的连接已提交时,该标志才会设置为1。

  • rpl (0x08):表示数据包处于回复方向,即与发起连接的数据包方向相反。只有在连接已提交时,该标志才会设置为1。

  • inv (0x10):表示状态无效,即连接跟踪器无法识别连接。这是对连接或连接跟踪器出现问题的总括,如:

    • L3/L4协议处理器未加载或不可用。

    • 数据包格式不正确。

    • 数据包长度不符合协议预期。

  • trk (0x20):表示数据包已被跟踪,即先前已经通过了连接跟踪器。如果这个标志未设置,其他标志也不会设置。如果设置,数据包则被标记为已跟踪,其他标志也可能被设置。

  • snat (0x40):表示数据包已被先前的ct动作进行了源地址/端口转换。Open vSwitch 2.6版本新增了这个标志。

  • dnat (0x80):表示数据包已被先前的ct动作进行了目标地址/端口转换。Open vSwitch 2.6版本新增了这个标志。

 

ct_state字段用于表示数据包所属连接的状态。这个字段可以通过符号名来匹配,每个符号名前缀可以是"+"表示必须设置的标志,或者是"-"表示必须未设置的标志,中间不使用其他分隔符。未提及的标志则视为通配符。例如,tcp,ct_state=+trk-new匹配的是已经被连接跟踪器处理过但并未建立新连接的TCP数据包。匹配也可以用数字形式表示为flags/mask,其中flags和mask都是32位的十进制或十六进制数值。

每个标志前面都有一个“+”,表示必须设置的标志,或者“-”,表示必须取消设置的标志。还可以指定多个标志,例如ct_state=+trk+new。我们将在下面看到其中一些标志的用法。

在Open vSwitch(一个开源的虚拟交换机)的管道中,一个单独的数据包(packet)可能处于两种状态之一:“未跟踪”(untracked)或“已跟踪”(tracked),这两种状态可以通过ct_state中的trk标志来区分。

  • 未跟踪(untracked):数据包在Open vSwitch管道的开始时处于未跟踪状态,并且会保持未跟踪状态,直到管道调用ct动作。在未跟踪的数据包中,连接跟踪字段的值都是零。

  • 已跟踪(tracked):当Open vSwitch管道中的某个流(flow)调用ct动作时,该动作会初始化连接跟踪字段,并且数据包在其后续的处理过程中将被视为已跟踪。

简单来说,当一个数据包进入Open vSwitch时,它默认是未跟踪的。但是,如果某个流规则(flow rule)指定了要对该数据包执行ct动作(通常用于启动或更新连接跟踪信息),那么该数据包就会变为已跟踪状态,并且其连接跟踪字段会被初始化或更新。这对于实现如防火墙、NAT(网络地址转换)等功能非常重要,因为这些功能通常需要知道数据包所属的连接信息。

 

连接跟踪(conntrack)标志之间的关系和它们的使用限制:

  1. 如果trk未设置,则其他标志也不会设置

    • 如果连接跟踪(trk)标志没有被设置(即数据包没有通过连接跟踪器处理),那么其他所有标志(如newestrelrplinv)都不会被设置。

  2. 如果trk已设置,则可能设置一个或多个其他标志

    • 一旦数据包通过了连接跟踪器(即trk被设置),其他标志(newestrelrpl)中的一个或多个可能也会被设置,以表示数据包在连接中的状态。

  3. 如果inv被设置,则只有trk标志也会被设置

    • 如果数据包的状态是无效的(inv被设置),那么只有trk标志也会被设置,表示数据包至少经过了连接跟踪器的处理,但状态无效。

  4. new和est是互斥的

    • 一个数据包不能同时被标记为新的连接(new)和已建立的连接(est)。这是因为在连接的生命周期中,一个连接开始时是新的(new),一旦完成握手过程,它就会变成已建立的(est)。

  5. new和rpl是互斥的

    • 一个数据包不能同时被标记为新的连接(new)和回复方向的数据包(rpl)。因为回复方向的数据包总是与已存在的连接相关,而新的连接还没有开始产生回复。

  6. rel可以与任何其他标志结合设置

    • rel标志(表示与现有连接相关的数据包)可以与任何其他标志(newestrpl)一起设置。这意味着相关连接可以是新的、已建立的或回复方向的。

这些约束条件确保了在应用连接跟踪规则时,标志之间的逻辑关系和状态转换是清晰和一致的。


2. ct_zone:连接跟踪区域

代表一个独立的连接跟踪上下文。ct_zone 是一个16位的字段,主要用于区分不同的连接跟踪环境。当一个数据包通过OVS时,连接跟踪 (ct) 动作可以设置 ct_zone 的值。这个值由最近执行的 ct 动作确定(通常是通过OpenFlow流规则作用于一个连接跟踪条目上),并且可以作为另一个流条目中的匹配字段来使用。

ct_zone 的主要用途在于,它允许网络管理员或自动控制系统在OVS中创建多个独立的连接跟踪环境。每个 ct_zone 实质上都是一个独立的连接跟踪表,数据包的连接状态只在这个特定的上下文中被跟踪。这意味着,如果一个数据包在不同的 ct_zone 中出现,它可以被视为两个完全独立的连接,即使它们可能具有相同的五元组(源IP、目的IP、源端口、目的端口和协议类型)。

这种机制在需要对不同类别的流量进行隔离跟踪的场景下特别有用,例如,你可以为不同业务部门的流量分配不同的 ct_zone,这样即使两个部门之间的流量具有相同的目的地和源地址,它们仍然会被视为独立的连接,从而可以单独地进行状态跟踪和管理。

ct_zone 的设置和使用,增加了OVS在复杂网络环境中的灵活性和功能性。通过精心设计的流规则,网络管理员可以利用 ct_zone 来实现高级的流量控制策略,如基于连接状态的负载均衡、安全策略实施以及故障隔离等。

值得注意的是,ct_zone 的值是由 ct 动作设置的,而这个动作可以出现在OVS的流表中。当一个数据包首次到达OVS时,如果没有匹配到任何带有 ct 动作的流规则,那么它将默认处于未跟踪状态,此时 ct_zone 的值为零。一旦一个数据包被某个带有 ct 动作的流规则匹配,并设置了 ct_zone 的值,那么这个数据包及其后续属于同一连接的所有数据包都会在指定的 ct_zone 上下文中被跟踪。

3. ct_mark:连接跟踪标记字段

被用于标记当前数据包所属的连接。当某个动作在ct动作(连接跟踪动作)的exec参数中被执行时,这个ct_mark元数据会被提交(或设置)到当前数据包所属的连接上。这样,随后的数据包属于同一个连接时,就可以使用这个标记来进行特定的处理或策略应用。

ct_mark 的主要用途在于,它允许网络管理员或自动控制系统在连接层面应用精细的策略。通过为不同的连接分配不同的标记,可以基于这些标记来实施流量控制、安全策略、QoS(Quality of Service)规则等。例如,一个特定的标记可能指示连接属于高优先级的流量,而另一个标记则可能指示连接涉及敏感数据,需要额外的安全检查。

在 OpenFlow 管道中,ct_mark 可以作为一个匹配字段,这意味着可以在后续的流规则中引用它来做出基于连接标记的决策。例如,一个流规则可能指定 "if ct_mark == X, then forward to port Y",这意味着所有具有标记 X 的连接的数据包将被转发到端口 Y。

值得注意的是,ct_mark 的值是在连接建立时设置的,并且在连接的生命周期中保持不变,除非有额外的动作显式地改变了这个值。这意味着,一旦一个连接被标记,所有属于这个连接的数据包都将携带相同的标记,直到连接终止。

此外,ct_mark 的可读写特性意味着它不仅可以用于读取和匹配,还可以通过管道中的动作来更新。这为动态调整连接的标记提供了可能性,例如,响应外部事件或根据网络状况的变化重新分类流量。

4. ct_lable:连接跟踪标签字段

ct_mark类似,ct_label字段允许网络管理员给特定的连接分配一个更大的标签,以进行后续的流量管理或策略应用。

 

允许网络管理员根据需要对网络连接进行分类和管理。例如,管理员可以给来自特定源或目的地的连接分配一个特定的标签,然后基于这个标签来应用特定的流量控制策略,如限速、路由重定向等。

由于ct_label是一个128位的字段,它提供了比ct_mark(32位)更大的范围,因此可以支持更多的连接分类和策略应用

 

5. ct_nw_src / ct_ipv6_src

 

ct_nw_srcct_ipv6_src 是Open vSwitch中用于连接跟踪的字段,它们分别用于匹配IPv4和IPv6连接的原始方向元组的源地址。这两个字段在Open vSwitch 2.8版本中被引入,用于存储和识别连接最初建立时的源地址信息。

ct_nw_src:这用于IPv4的连接跟踪源地址匹配。例如,如果你想匹配所有原始源地址为192.168.1.1的连接上的数据包,你可以使用ct_nw_src表达式。

ct_ipv6_src:这用于IPv6的连接跟踪源地址匹配。与IPv4类似,但用于IPv6地址。

这两个字段的存在使得Open vSwitch能够准确地跟踪连接的源头,即使在NAT(网络地址转换)或连接状态发生变化时也能保持对原始源地址的记录。这对于处理复杂网络环境中的流量控制、安全策略实施以及故障排查等任务至关重要。例如,防火墙规则可以基于这些字段来允许或拒绝特定来源的连接;负载均衡器可以依据这些信息来决定如何分发连接;而网络监控系统则可以利用它们来分析和可视化网络流量模式。

综上所述,ct_nw_srcct_ipv6_src 在Open vSwitch的连接跟踪功能中扮演着核心角色,确保了网络管理者能够对网络中的连接有深入的理解和精细的控制。

 

6. ct_nw_dst / ct_ipv6_dst

ct_nw_dstct_ipv6_dst 是 Open vSwitch (OVS) 中用于连接跟踪的字段,分别用于匹配 IPv4 和 IPv6 连接的原始方向元组的目标地址。这些字段允许网络管理员或自动化系统基于连接的最初目标地址来制定精细的策略和过滤规则。

ct_nw_dst: 这是用于 IPv4 地址的连接跟踪原始方向目标地址的匹配条件。当你想基于 IPv4 数据包的连接跟踪信息中的目标地址来过滤数据包时,你会使用这个条件。

ct_ipv6_dst: 这是用于 IPv6 地址的连接跟踪原始方向目标地址的匹配条件。与 ct_nw_dst 类似,但它是为 IPv6 数据包设计的。

 

7. ct_nw_proto

ct_nw_proto 是一个与 Linux 内核的 Connection Tracking (conntrack) 模块相关的网络过滤器条件,它用于匹配连接跟踪条目中原始方向(即从外部系统到内部系统的连接)的 IP 协议类型

在网络过滤规则(如 iptables 规则)中,ct_nw_proto 可以用来基于 IP 协议类型(如 TCP、UDP、ICMP 等)来过滤流量。这允许你针对特定协议类型应用不同的策略

 

8. ct_tp_src

匹配连接跟踪原始方向元组传输源端口

 

9. ct_tp_dst

匹配连接跟踪原始方向元组传输目的端口

 

Action 相关字段

ct 动作是 Open vSwitch (OVS) 中的一个功能,它允许数据包通过连接跟踪器 (conntrack) 进行处理。

ct 动作可以用来修改或查询这些连接的状态。

以下是 ct 动作支持的一些参数的详细解释:

  1. commit

    • 将连接提交给连接跟踪模块,一旦连接被提交,即使与该连接相关的数据包已经通过 Open vSwitch 流水线并被处理,连接状态信息仍然会被保留在连接跟踪模块中

  2. force

    • 除以上的commit标志外,还可以使用force标志来有效地终止现有连接并在当前方向开始新连接

  3. table=number

    用于指定数据包接下来应该被发送到的流水线(Pipeline)的表(Table),数据包的处理流程被分叉为两个路径:数据包的原始实例将继续按照当前的动作列表处理,而不进行连接跟踪(作为未跟踪的包)。同时,数据包的另一个实例将被发送到连接跟踪器,一旦连接跟踪完成,该实例将带有新的ct_state和其他连接跟踪相关的匹配字段(如源/目标IP、端口等)重新注入到OpenFlow流水线中的指定表(由table=number指定)。

  4. zone=value OR zone=src[start..end]

    一个 16 位的上下文 ID,可用于将连接隔离到不同的域中,允许不同区域中的网络地址重叠。如果没有提供区域,则默认使用区域零。

  5. exec([action][,action…])

    • 在连接跟踪的上下文中执行受限的动作集。在 exec 动作内部,仅允许修改 ct_mark 或 ct_label 字段的动作。

  6. alg=<ftp/tftp>

    • 指定要跟踪的特定连接类型的应用层网关 (ALG)。例如,可以跟踪 FTP 或 TFTP 连接,以便正确地处理与这些协议相关的命令和数据连接。

  7. nat

    • 指定要跟踪的连接的地址和端口转换。这通常与 NAT(网络地址转换)相关,允许您更改数据包的源或目标 IP 地址和端口。

 

实验:

1.基础互通

创建namespace
ip netns add left

ip netns add right

创建虚拟端口,并加入到namespace和ovs 桥

ip link add veth_l0 type veth peer name veth_l1

ip link set veth_l1 netns left

ip link add veth_r0 type veth peer name veth_r1

ip link set veth_r1 netns right

ip link set veth_l0 up

ip link set veth_r0 up

ovs-vsctl add-br br0

ovs-vsctl add-port br0 veth_l0 ovs-vsctl add-port br0 veth_r0

给veth_l1 veth_r1 配置地址并up接口

ip netns exec left ip link set lo up

ip netns exec left ip addr add  192.168.0.2/24 dev veth_l1

ip netns exec left ip link set veth_l1 up

ip netns exec right ip link set lo up

ip netns exec right ip addr add  10.0.0.2/24 dev veth_r1

ip netns exec right ip link set veth_r1 up

添加流表

ovs-ofctl add-flow br0  "table=0, priority=10, in_port=veth_l0, actions=veth_r0"

ovs-ofctl add-flow br0 "table=0, priority=10, in_port=veth_r0, actions=veth_l0"

ip netns exec left scapy

sendp(Ether()/IP(src="192.168.0.2", dst="10.0.0.2")/TCP(sport=1024, dport=2048, flags=0x02, seq=100), iface="veth_l1")

在veth_l1 veth_r1抓包


2.添加流表来启动"tracking"跟踪OVS中接收到的报文

a.来自客户端方向的TCP SYN报文

        ovs-ofctl add-flow br0 "table=0, priority=50, ct_state=-trk, tcp, in_port=veth_l0, actions=ct(table=0)"

        ovs-ofctl add-flow br0 "table=0, priority=50, ct_state=+trk+new, tcp, in_port=veth_l0, actions=ct(commit),veth_r0"

 

    发tcp syn包

    sendp(Ether()/IP(src="192.168.0.2", dst="10.0.0.2")/TCP(sport=1024, dport=2048, flags=0x02, seq=100), iface="veth_l1")

 

b.对于来自相反/服务器方向的TCP SYN+ACK报文

        ovs-ofctl add-flow br0  "table=0, priority=50, ct_state=-trk, tcp, in_port=veth_r0, actions=ct(table=0)"

        ovs-ofctl add-flow br0  "table=0, priority=50, ct_state=+trk+est, tcp, in_port=veth_r0, actions=veth_l0"

                      

        发送tcp syn+ack包

        sendp(Ether()/IP(src="10.0.0.2",dst="192.168.0.2")/TCP(sport=2048,dport=1024,flags=0X12,seq=201,ack=102),iface="veth_r1")

TCP SYN+ACK报文经过conntrack处理后,其ct_state设置了"est"连接建立标志。

在只接收到SYN和SYN ACK报文后,conntrack的状态成为"ESTABLISHED"。但此时,如果它没有收到第三个ACK报文(来自客户端),此连接很快会从conntrack中清除。

 

c.来自客户端方向的TCP ACK报文

    ovs-ofctl add-flow br0 "table=0, priority=50, ct_state=+trk+est, tcp, in_port=veth_l0, actions=veth_r0"

发送第三个TCP ACK报文

        sendp(Ether()/IP(src="192.168.0.2", dst="10.0.0.2")/TCP(sport=1024, dport=2048, flags=0x10, seq=101, ack=201), iface="veth_l1")

conntrack状态保持在"ESTABLISHED"状态,但现在它已经收到来自客户端的ACK,即使没有接收此连接上的任何数据,其也将保持此状态很长时间。 

 

拆除连接

客户端发送FIN+ACK

sendp(Ether()/IP(src="192.168.0.2", dst="10.0.0.2")/TCP(sport=1024, dport=2048, flags=0x11, seq=102, ack=201), iface="veth_l1")

服务端发送FIN+ACK

sendp(Ether()/IP(src="10.0.0.2", dst="192.168.0.2")/TCP(sport=2048, dport=1024, flags=0X11, seq=201, ack=103), iface="veth_r1")

客户端发送ACK

sendp(Ether()/IP(src="192.168.0.2", dst="10.0.0.2")/TCP(sport=1024, dport=2048, flags=0x10, seq=103, ack=202), iface="veth_l1")

文章来自个人专栏
yulx的个人专栏
1 文章 | 1 订阅
0条评论
0 / 1000
请输入你的评论
5
3