Netfilter之IPVS匹配扩展

2023-12-19 10:08
文章标签 匹配 扩展 netfilter ipvs

本文主要是介绍Netfilter之IPVS匹配扩展,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

以下iptables命令查看ipvs匹配扩展的帮助信息。可匹配的字段分别为:虚拟服务的协议号、地址、端口、数据流的方向、转发模式以及控制连接的端口号。对于类似FTP的服务,其控制连接的端口为21,数据端口为20。

$ iptables -m ipvs --help    
iptables v1.6.0IPVS match options:
[!] --ipvs                      packet belongs to an IPVS connectionAny of the following options implies --ipvs (even negated)
[!] --vproto protocol           VIP protocol to match; by number or name, e.g. "tcp"
[!] --vaddr address[/mask]      VIP address to match
[!] --vport port                VIP port to match; by number or name, e.g. "http"--vdir {ORIGINAL|REPLY}     flow direction of packet
[!] --vmethod {GATE|IPIP|MASQ}  IPVS forwarding method used
[!] --vportctl port             VIP port of the controlling connection to match, e.g. 21 for FTP

IPVS匹配模块初始化

函数ipvs_mt_init先系统注册IPVS匹配扩展定义xt_ipvs_mt_reg。匹配名称为ipvs,这里定义了匹配函数ipvs_mt,以及检查函数ipvs_mt_check。

static struct xt_match xt_ipvs_mt_reg __read_mostly = {.name       = "ipvs",.revision   = 0,.family     = NFPROTO_UNSPEC,.match      = ipvs_mt,.checkentry = ipvs_mt_check,.matchsize  = XT_ALIGN(sizeof(struct xt_ipvs_mtinfo)),
};static int __init ipvs_mt_init(void)
{return xt_register_match(&xt_ipvs_mt_reg);
}

匹配结构中的matchsize字段,给定了数据结构xt_ipvs_mtinfo的长度,其定义中包含所有要匹配的字段变量。其最后一个成员变量bitmask掩码,取值为XT_IPVS_XX中的一个或多个,置位表明指定了相应的字段;否则,不处理相应的字段。如bitmask中置位XT_IPVS_METHOD,表明指定了转发模式字段fwd_method。

字段invert的取值与bitmask相同,但是invert中的相应位指明进行取反操作。例如,invert中设置了XT_IPVS_METHOD位,表明匹配除fwd_method变量中所指定了转发模式之外的模式。

enum {XT_IPVS_IPVS_PROPERTY = 1 << 0, /* all other options imply this one */XT_IPVS_PROTO =     1 << 1,XT_IPVS_VADDR =     1 << 2,XT_IPVS_VPORT =     1 << 3,XT_IPVS_DIR =       1 << 4,XT_IPVS_METHOD =    1 << 5,XT_IPVS_VPORTCTL =  1 << 6,
}struct xt_ipvs_mtinfo {union nf_inet_addr  vaddr, vmask;__be16          vport;__u8            l4proto;__u8            fwd_method;__be16          vportctl;__u8            invert;__u8            bitmask;
};

匹配检查

由注册的函数ipvs_mt_check可知,IPVS匹配模块仅支持IPv4和IPv6两种协议。此函数在匹配函数ipvs_mt之前执行。

static int ipvs_mt_check(const struct xt_mtchk_param *par)
{if (par->family != NFPROTO_IPV4
#ifdef CONFIG_IP_VS_IPV6&& par->family != NFPROTO_IPV6
#endif) {pr_info("protocol family %u not supported\n", par->family);return -EINVAL;}return 0;

执行匹配

因为XT_IPVS_IPVS_PROPERTY属性是一个基础属性,并且之后的其它字段都隐含了此字段,如果bitmask掩码完全等于XT_IPVS_IPVS_PROPERTY,表明仅仅设置了此字段,即iptables配置命令行的命令字:(–ipvs)。根据invert的值决定是否匹配,如果此报文仅有IPVS系统处理,skb的成员ipvs_property为1,如果invert为0,不取反,则匹配发生。

其次,如果报文未经过ipvs系统处理,ipvs_property为0,就没有继续处理的必要了。

static bool ipvs_mt(const struct sk_buff *skb, struct xt_action_param *par)
{const struct xt_ipvs_mtinfo *data = par->matchinfo;struct netns_ipvs *ipvs = net_ipvs(xt_net(par));    const u_int8_t family = xt_family(par);   /* ipvs_mt_check ensures that family is only NFPROTO_IPV[46]. */struct ip_vs_iphdr iph;if (data->bitmask == XT_IPVS_IPVS_PROPERTY) {match = skb->ipvs_property ^ !!(data->invert & XT_IPVS_IPVS_PROPERTY);goto out;}/* other flags than XT_IPVS_IPVS_PROPERTY are set */if (!skb->ipvs_property) {match = false;goto out;}

函数ip_vs_fill_iph_skb获取数据包中的IP头部信息,保存于ip_vs_iphdr结构类型的变量iph中。匹配字段XT_IPVS_PROTO对应于iptables配置命令的命令选项(–vproto)。注意这里的字段对比与以上XT_IPVS_IPVS_PROPERTY字段的操作不同,如果协议字段相等,并且invert字段为1,表明匹配失败。反之,匹配成功,match的初始值就位true。

其后,根据协议值,获取IPVS的协议处理结构和IPVS连接结构。

    ip_vs_fill_iph_skb(family, skb, true, &iph);if (data->bitmask & XT_IPVS_PROTO)if ((iph.protocol == data->l4proto) ^ !(data->invert & XT_IPVS_PROTO)) {match = false;goto out;}pp = ip_vs_proto_get(iph.protocol);if (unlikely(!pp)) {match = false;goto out;}/* Check if the packet belongs to an existing entry */cp = pp->conn_out_get(ipvs, family, skb, &iph);if (unlikely(cp == NULL)) {match = false;goto out;}

以下代码根据IPVS连接结构cp中的信息进行匹配比较,其逻辑与以上的XT_IPVS_PROTO字段一致。包括:XT_IPVS_VPORT、XT_IPVS_VPORTCTL、XT_IPVS_DIR、XT_IPVS_METHOD和XT_IPVS_VADDR等字段。

对于XT_IPVS_VPORTCTL字段,需要找到其IPVS控制连接结构,对比其中的虚拟服务端口,因为此为控制端口。

对于方向XT_IPVS_DIR字段的比较,使用conntrack系统的信息值ctinfo进行匹配。

    if (data->bitmask & XT_IPVS_VPORT)if ((cp->vport == data->vport) ^ !(data->invert & XT_IPVS_VPORT)) {match = false; goto out_put_cp;}if (data->bitmask & XT_IPVS_VPORTCTL)if ((cp->control != NULL && cp->control->vport == data->vportctl) ^ !(data->invert & XT_IPVS_VPORTCTL)) {match = false; goto out_put_cp;}if (data->bitmask & XT_IPVS_DIR) {enum ip_conntrack_info ctinfo;struct nf_conn *ct = nf_ct_get(skb, &ctinfo);if (ct == NULL) {match = false; goto out_put_cp;}if ((ctinfo >= IP_CT_IS_REPLY) ^ !!(data->invert & XT_IPVS_DIR)) {match = false; goto out_put_cp;}}if (data->bitmask & XT_IPVS_METHOD)if (((cp->flags & IP_VS_CONN_F_FWD_MASK) == data->fwd_method) ^ !(data->invert & XT_IPVS_METHOD)) {match = false; goto out_put_cp;}if (data->bitmask & XT_IPVS_VADDR) {if (ipvs_mt_addrcmp(&cp->vaddr, &data->vaddr, &data->vmask, family) ^ !(data->invert & XT_IPVS_VADDR)) {match = false; goto out_put_cp;}

IPVS匹配应用

在内核邮件列表中,作者提供了一种利用ipvs匹配实现全NAT(SNAT+DNAT)的转发模式。IPVS的NAT/Masq转发模式实现的是DNAT转发,以下iptables命令开启SNAT功能。

# ipvsadm -A -t 192.168.100.30:80 -s rr 
# ipvsadm -a -t 192.168.100.30:80 -r 192.168.10.20:80 -m 
# ... # Source NAT for VIP 192.168.100.30:80 
# iptables -t nat -A POSTROUTING -m ipvs --vaddr 192.168.100.30/32 --vport 80 -j SNAT --to-source 192.168.10.10 or SNAT-ing only a specific real server: # iptables -t nat -A POSTROUTING --dst 192.168.10.20 -m ipvs --vaddr 192.168.100.30/32 -j SNAT --to-source 192.168.10.10 

以上命令将到达虚拟服务:192.168.100.30:80的流量,进行SNAT转换,源地址变换为:192.168.10.10。或者仅仅对调度到真实服务器192.168.10.20的流量,进行SNAT转换。

这里有一个问题,如果指定的虚拟服务的端口为FTP端口21,对其进行SNAT操作,那么对于FTP的数据通道,其端口并不是21,就需要以下的命令为其数据连接指定SNAT,这里使用命令选项(–vportctl)。

# SNAT FTP control connection 
# iptables -t nat -A POSTROUTING -m ipvs --vaddr 192.168.100.30/32 --vport 21 -j SNAT --to-source 192.168.10.10 # SNAT FTP passive data connection 
# iptables -t nat -A POSTROUTING -m ipvs --vaddr 192.168.100.30/32 --vportctl 21 -j SNAT --to-source 192.168.10.10 

以上的配置SNAT方式,在开启IPVS同步功能时,在主和被机上将产生不同的行为,

内核版本 5.0

这篇关于Netfilter之IPVS匹配扩展的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/511790

相关文章

浅谈配置MMCV环境,解决报错,版本不匹配问题

《浅谈配置MMCV环境,解决报错,版本不匹配问题》:本文主要介绍浅谈配置MMCV环境,解决报错,版本不匹配问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录配置MMCV环境,解决报错,版本不匹配错误示例正确示例总结配置MMCV环境,解决报错,版本不匹配在col

详解nginx 中location和 proxy_pass的匹配规则

《详解nginx中location和proxy_pass的匹配规则》location是Nginx中用来匹配客户端请求URI的指令,决定如何处理特定路径的请求,它定义了请求的路由规则,后续的配置(如... 目录location 的作用语法示例:location /www.chinasem.cntestproxy

Java常用注解扩展对比举例详解

《Java常用注解扩展对比举例详解》:本文主要介绍Java常用注解扩展对比的相关资料,提供了丰富的代码示例,并总结了最佳实践建议,帮助开发者更好地理解和应用这些注解,需要的朋友可以参考下... 目录一、@Controller 与 @RestController 对比二、使用 @Data 与 不使用 @Dat

Spring组件初始化扩展点BeanPostProcessor的作用详解

《Spring组件初始化扩展点BeanPostProcessor的作用详解》本文通过实战案例和常见应用场景详细介绍了BeanPostProcessor的使用,并强调了其在Spring扩展中的重要性,感... 目录一、概述二、BeanPostProcessor的作用三、核心方法解析1、postProcessB

Nginx中location实现多条件匹配的方法详解

《Nginx中location实现多条件匹配的方法详解》在Nginx中,location指令用于匹配请求的URI,虽然location本身是基于单一匹配规则的,但可以通过多种方式实现多个条件的匹配逻辑... 目录1. 概述2. 实现多条件匹配的方式2.1 使用多个 location 块2.2 使用正则表达式

golang字符串匹配算法解读

《golang字符串匹配算法解读》文章介绍了字符串匹配算法的原理,特别是Knuth-Morris-Pratt(KMP)算法,该算法通过构建模式串的前缀表来减少匹配时的不必要的字符比较,从而提高效率,在... 目录简介KMP实现代码总结简介字符串匹配算法主要用于在一个较长的文本串中查找一个较短的字符串(称为

C++使用栈实现括号匹配的代码详解

《C++使用栈实现括号匹配的代码详解》在编程中,括号匹配是一个常见问题,尤其是在处理数学表达式、编译器解析等任务时,栈是一种非常适合处理此类问题的数据结构,能够精确地管理括号的匹配问题,本文将通过C+... 目录引言问题描述代码讲解代码解析栈的状态表示测试总结引言在编程中,括号匹配是一个常见问题,尤其是在

关于Gateway路由匹配规则解读

《关于Gateway路由匹配规则解读》本文详细介绍了SpringCloudGateway的路由匹配规则,包括基本概念、常用属性、实际应用以及注意事项,路由匹配规则决定了请求如何被转发到目标服务,是Ga... 目录Gateway路由匹配规则一、基本概念二、常用属性三、实际应用四、注意事项总结Gateway路由

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi