业务请求经过高防 IP 的 4 层转发后,业务服务器端接收到报文后,其看到的源 IP 地址是高防 IP 的出口 IP 地址。为了让服务器端能够获取到用户端实际的 IP 地址,可以使用如下 TOA 的方案。在业务服务的 Linux 服务器上,安装对应的 TOA 内核包,并重启服务器后。业务侧就可以获取到用户端实际的 IP 地址。
TOA 原理
高防转发后,数据包同时会做 SNAT 和 DNAT,数据包的源地址和目标地址均修改。
TCP 协议下,为了将客户端 IP 传给服务器,会将客户端的 IP,port 在转发时放入了自定义的 tcp option 字段。
#define
TCPOPT_ADDR 200
#define
TCPOLEN_ADDR 8 /* |opcode|size|ip+port| = 1 + 1 + 6 */
/*
*insert
client ip in tcp option, now only support IPV4,
*must be 4
bytes alignment.
*/
struct ip_vs_tcpo_addr {
__u8
opcode;
__u8
opsize;
__u16
port;
__u32
addr;
};
Linux 内核在监听套接字收到三次握手的 ACK 包之后,会从 SYN_REVC 状态进入到 TCP_ESTABLISHED 状态。这时内核会调用 tcp_v4_syn_recv_sock 函数。 Hook 函数 tcp_v4_syn_recv_sock_toa首先调用原有的tcp_v4_syn_recv_sock函数,然后调用 get_toa_data 函数从 TCP OPTION 中提取出 TOA OPTION,并存储在 sk_user_data 字段中。
然后用 inet_getname_toa hook inet_getname,在获取源 IP 地址和端口时,首先调用原来的inet_getname,然后判断 sk_user_data 是否为空,如果有数据从其中提取真实的 IP 和 port,替换 inet_getname 的返回。
客户端程序在用户态调用 getpeername,返回的 IP 和 port 即为客户端的原始 IP。
内核包安装步骤
Centos 6.x
安装步骤
下载安装包
Centos 6.x 下载
安装包文件
Centos 6安装命令:rpm -hiv kernel-2.6.32-220.23.1.el6.toa.x86_64.rpm --force
Centos 7安装命令:rpm -hiv kernel-3.10.0-693.el7.centos.toa.x86_64.rpm --force 如果提示冲突报错安装下面依赖组件
Centos 7安装依赖组件:yum -y install dracut linux-firmware xfsprogs kmod kexec-tools
安装完成之后重启主机
reboot
执行命令检查 toa 模块是否加载成功
lsmod | grep toa
没有加载的话手工开启
modprobe toa
可用下面的命令开启自动加载 toa 模块
echo modprobe toa >> /etc/rc.d/rc.local
Centos 7.x/其他版本
根据上 Linux 的版本,下载对应的 TOA 包解压:
如果上述下载文件中没有您的操作系统版本对应的安装包,可以下载 Linux 通用版的源码包,编译后获取,该版本支持 Centos6.9 和 Centos7、Ubuntu14.04 等绝大多数的 Linux 发行版:
如果编译报错,有可能是安装的内核版本和 uname -r 展示版本不一致,进入到 /lib/modules/ 目录,查看本机上真实安装的内核版本,修改 Makefile 文件里面的 uname -r 为真实的内核版本,重新编译。