iptables TEE使用技巧

shixudong@163.com

iptables TEE可用于镜像数据包,参数为--gateway ipaddr,根据官方文档,针对TEE目标的解释是将数据包克隆到本地网络上的另一台机器,一般情况下,ipaddr应指向本地网络,如ipaddr指向非本地网络,则需要配置下一跳(其实质是本机网关)转发该克隆包;针对--gateway ipaddr的解释则是将数据包克隆到本机可达的另一台机器。

虽然以上两种说法有点绕,但都指出gateway参数ipaddr不必限于本地网络,那么TEE究竟是如何处理ipaddr这个参数的呢?从源码可知,TEE将ipaddr作为目标IP进行路由寻址,如ipaddr位于本地网络,将返回ipaddr对应的MAC地址作为下一跳;如ipaddr不在本地网络且存在可达ipaddr的路由,将返回路由器的MAC作为下一跳。然后TEE把克隆包的目标MAC更改为前述返回的下一跳MAC后发出该包(TEE不对包的三层IP地址做任何修改,所以才有镜像或克隆的说法)。

根据TEE的这一机制,如ipaddr位于本地网络,克隆包将直接发至该ipaddr,鉴于克隆包的目标IP并非该ipaddr,如ipaddr所在机器开启了ip_forward功能,且克隆包的目标IP还会重新经过TEE功能所在机器的话,则有很大可能产生不必要的重复TEE包(重复数量取决于TTL)。如ipaddr不在本地网络,克隆包将发至可达ipaddr的路由器,但路由器并不知道ipaddr的任何信息,只能根据克隆包本身的目标IP进行后续路由,如后续路由可达克隆包的目标IP,该IP将收到2个包,原始包+克隆包。显然,在ipaddr不属于本地网络的情况下,gateway参数指定的ipaddr毫无意义,克隆包压根到不了ipaddr这台机器。
在局域网内测试TEE功能时意外发现,部分带LAN口交换机功能的宽带路由器,采用了硬件流交换技术:同一个数据流,首包根据目标MAC进行二层交换,后续包不再查找MAC表,而是直接发送到首包关联的交换机端口。TEE包和初始包的三层源IP和目标IP相同,属于同一数据流,导致TEE包和初始包都发到率先完成二层交换的首包(一般情况下首包为初始包,但如在OUTPUT链中执行TEE,首包也可能是TEE包)目标MAC对应的交换机端口。在使用硬件流交换的情形下,不光是TEE功能有这一现象,同一个包只要在局域网内被发送两次,譬如局域网内存在两台路由器,数据包第一次发送到次优路由器,第二次由次优路由器将其转发到出口路由器,由于类似的机制(转发包和初始包属于同一个数据流),也会产生同样的现象:第二次发送时硬件流交换不会将数据包发往出口路由器(即使出口路由器是交换机本身也是如此),而是重新发送到次优路由器(初始包目标MAC对应的交换机端口,后续包不再根据新的目标MAC转发,而是直接发送到首包关联的初始端口)。如次优路由器为linux路由器,因该包目标MAC不是linux路由器本身MAC,刚进入二层就被DROP,不会再次转发,但若linux路由器采用了bridge,桥物理端口处于promisc模式,bridge能收到该包(dmesg将显示br0: received packet on eth0 with own address as source address),但因该包二层转发出口对应同一个桥物理端口,仍然会被桥DROP(此时如收包的桥物理端口启用了hairpin模式,bridge将该包再次转发出去,将出现无限循环包)。

使用iptables TEE时,还需关注以下事项:

1、TEE不是终止性目标,具有相同匹配条件的TEE规则都被执行,可以实现一对多克隆,示例如下:

iptables -A INPUT -p udp --dport 2022 -j TEE --gateway IP1

iptables -A INPUT -p udp --dport 2022 -j TEE --gateway IP2

2、TEE规则不能置于同一链(chain)中具有相同匹配条件的终止性目标后面,否则TEE规则无法执行。举例分析如下:

如想通过TEE克隆DNAT后的包,下面两种方法都无法实现。

方法a:

iptables –t nat -A PREROUTING -p udp --dport 2022 -j TEE --gateway IP1

iptables –t nat -A PREROUTING -p udp --dport 2022 -j DNAT --to IP2

方法b:

iptables –t nat -A PREROUTING -p udp --dport 2022 -j DNAT --to IP2

iptables –t nat -A PREROUTING -p udp --dport 2022 -j TEE --gateway IP1

方法a先执行TEE,但此时尚未进行DNAT,故TEE只能克隆未经过DNAT的包;方法b先进行DNAT,但DNAT属于终止性目标,后面的TEE压根不执行。

可行的方法是根据DNAT后的IP是本机还是其他机器,在filter表的相应chain里使用相同的匹配条件执行TEE。

iptables -A chain -p udp --dport 2022 -j TEE --gateway IP1

DNAT后目标为本机则使用INPUT,否则使用FORWARD。

3、基于上述2的分析,TEE无法克隆SNAT后的包,这是因为PREROUTING链后再无其他filter可供TEE执行(可使用nftables自定义postrouting的优先级实现,此处不做展开)。

4、尽量不要通过nat表进行TEE,除了上述2和3的限制外,还有以下限制影响TEE发挥作用:

(1)如nat表仅有TEE规则,无其他实质性SNAT/DNAT规则,TEE规则计数器不增加,不产生conntrack记录,TEE规则实际上无法匹配而不予执行;

(2)如nat表还有其他相干(必须在TEE规则后)或不相干(无所谓顺序)的SNAT/DNAT规则,TEE规则计数器将增加,首个数据包被克隆。如TEE规则原始数据包(非克隆包)后续不被DROP,将产生conntrack记录,根据conntrack的快速匹配机制,因后续数据包已有对应conntrack记录,不再去匹配规则,故无法被克隆;如TEE规则原始数据包被后续规则显式DROP或内核隐式DROP(不允许接收或不允许转发),不会产生conntrack记录,后续数据包将持续被克隆。

5、克隆包直接通过ip_local_out发出,不使用conntrack,后续无法再通过OUTPUT链对TEE包进行DNAT(可通过引入network namespace以及conntrack zones或nftables实现,此处不做展开)。

由于TEE包不能改变克隆包的三层地址,而且TEE包本身不使用conntrack,不方便对克隆包进行必要的NAT处理,故原始包和克隆包使用相同的目标IP,限制了克隆包被多次合理使用的场景。但当原始包目标IP为广播地址时,仍可利用TEE规则实现广播到单播的转换以及跨网广播功能。

在《iptables DNAT实现broadcast与unicast之间相互映射》一文中提到,如需用iptables DNAT实现broadcast到unicast的映射,必须借助br_netfilter模块和ebtables工具,而这两者都依托于bridge模块,如linux没有使用桥接的话,就无法通过DNAT实现broadcast到unicast的映射。此时,可利用TEE规则以及gateway ipaddr参数(必须是本地ipaddr),变通实现broadcast到ipaddr的转换,转换后的数据包,二层目标地址是本地ipaddr对应的MAC(unicast),三层目标地址则保持broadcast不变,类似于无线的multicast_to_unicast功能,因为三层是广播包,依然能被转换后的ipaddr接收和处理,且ipaddr所在机器即便开通ip_forward功能,也不会产生重复包。

通常情况下,本地广播(255.255.255.255)不能跨网传输,但在跨网linux上,利用TEE根据gateway ipaddr参数获取下一跳路由的功能,将ipaddr设置为另一块网卡对应的定向广播地址,可完美实现本地广播(255.255.255.255)的跨网传输。但编写TEE规则时,要注意以下三点:

1、TEE规则必须明确收包网卡,因为TEE包由本机发出,且三层目标IP为广播地址,可以自发自收,收到自己发出的广播包后,虽然不能被nat的PREROUTING处理,但仍可以被mangle和filter处理,也意味着可以被再次TEE,并且TEE模块在处理数据包复制时调用的nf_dup_ipv4有个大bug:尽管每次dup后TTL-1,但TTL为0后,会继续变成255,然后周而复始,无穷无尽。

2、如果要实现双向跨网广播,即使在两个方向都分别明确了收包网卡,但依然会面临广播包在另一个方向自发自收的问题,同样产生无限的重复TEE包。根据国外网友建议,可在TEE规则之前将初始包的TTL强行设置为1(因为初始包是广播包,本身不会跨网也不需要跨网,ttl=1不会产生副作用),同时在TEE规则中增加TTL=1的限制,可有效防范重复TEE包。

3、在利用TEE功能实现跨网广播时,除了以上两个关注点外,TEE规则对初始广播包的限制越明确越好,譬如目标地址必须明确本地广播,避免先前强行调整ttl对非广播包的影响;明确限制端口,避免跨网传播对其他不需要跨网广播情形的影响(譬如DHCP广播包)。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值