0
点赞
收藏
分享

微信扫一扫

toa 内核模块分析

TOA 的由来

我们知道 LVS 之前有三种负载均衡模式:DR、NAT 和 Tunnel,但都有各自的缺陷,比如 DR 和 NAT 要求 virtual server 与 real server 在同一子网下,而 Tunnel 运维起来比较复杂。因此,为了灵活部署,开发了第四种模式,即 FULLNAT。

FULLNAT 模式是 NAT 模式的一种扩展,不仅会替换目的 IP,也会替换源 IP。带来的好处是,使得 virtual server 和 real server 摆脱后端网络的束缚,不再要求它们位于同一子网下。

但是,这种模式也带来了一个问题,real server 无法获取真实的客户端 IP 地址,而在很多业务场景下,我们在对外提供服务时,需要检查服务请求方的 IP 地址,来针对IP地址做一些业务处理,最常见的一个例子就是:做白名单校验,只有在白名单列表中的 IP 地址,我们才允许它访问我们的服务;还有一种应用场景,那就是基于客户端的请求 IP 来进行调度,譬如 CDN 服务,那么就需要根据客户端的请求 IP,来调度最近最适合的资源提供服务。

为了解决上述问题,​​TOA​​ 应运而生,它实际是一个 TCP option filed,使用了 8 字节(kind = 0xfe,Length = 0x08,Value = 4B client's IP + 2B port),源码如下,

/* MUST be 4 bytes alignment */
struct toa_data {
__u8 opcode;
__u8 opsize;
__u16 port;
__u32 ip;
};

服务端机器打上 patch 后,在 lvs FULLNAT 模式下能够通过系统调用 ​​getsockopt​​ 拿到真实的 client IP 地址。

TOA 的使用

为了支持 TOA,FULLNAT 直接修改了内核代码,如果要重新编译内核,那使用起来就很麻烦了,我们可以以 .ko 文件的形式加载到内核,通过以下命令查看当前机器是否加载了 toa 模块,

lsmod | grep toa

toa 模块的编译可以参考文档 ​​TOA插件配置​​。

TOA 的实现原理

TOA 主要通过 hook 系统函数,进而从 tcp option 解析出 toa data。

注意:以下说明中用到的 linux 源码版本为 3.2.101。

​toa_init​​ 函数是 toa 模块的初始化函数,

/* module init */
static int __init
toa_init(void)
{
...
/* hook funcs for parse and get toa */
hook_toa_functions();
...
}

以上省略了一些处理细节,重点代码是 hook 的处理函数 ​​hook_toa_functions​​,以 ipv4 协议为例进行说明。

/* replace the functions with our functions */
static inline int
hook_toa_functions(void)
{
/* hook inet_getname for ipv4 */
struct proto_ops *inet_stream_ops_p =
(struct proto_ops *)&inet_stream_ops;

/* hook tcp_v4_syn_recv_sock for ipv4 */
struct inet_connection_sock_af_ops *ipv4_specific_p =
(struct inet_connection_sock_af_ops *)&ipv4_specific;
...
inet_stream_ops_p->getname = inet_getname_toa;
...
ipv4_specific_p->syn_recv_sock = tcp_v4_syn_recv_sock_toa;
return 0;
}

在linux 源码中 ipv4 协议各处理函数有如下定义,

/* net/ipv4/tcp_ipv4.c */
const struct inet_connection_sock_af_ops ipv4_specific = {
..
.send_check = tcp_v4_send_check,
.conn_request = tcp_v4_conn_request,
.syn_recv_sock = tcp_v4_syn_recv_sock,
.get_peer = tcp_v4_get_peer,
};
EXPORT_SYMBOL(ipv4_specific);
举报

相关推荐

0 条评论