流量复制工具tcpcopy使用简介

背景

今天有一个优化内存的代码修改要上线,这种情况下需要进行测试,然而并没有线上的流量,也就导致没有很好的办法进行最终效果的模拟,而又由于改动较大存在与其他模块的不兼容所以在考虑如何测试的时候遇到了问题,突然心想能不能把线上机器的流量复制过来到测试端口不就OK啦!毕竟haproxy、nginx这种工具都已经支持流量转发了,流量复制这么普遍的需求也一定有!

于是google了一下流量复制,搜到两个关键词:tcpcopyngx_http_mirror_module.

ngx_http_mirror_module

这里先简单介绍一下NGINX的流量复制模块,顾名思义,这个模块是从http层对流量进行复制的,打开这个模块之后是需要在nginx配置文件中进行location的配置,之后访问这个location会把流量同时转发给两个后端的server,所以该模块在使用nginx作为代理的场景下会非常方便,我比较吃惊的事这个模块是在nginx 1.13.4版本的时候才进行了发布,这个功能不应该是个强需求吗🤣

tcpcopy

由于要测试的服务使用的是rpc协议,是需要在tcp层进行流量复制的,这种场景下使用的就是tcpcopy啦,关于tcpcopy的介绍网上比较多就不在赘述,这里主要记录下使用的几个要点以及一些记录

参考链接1

参考链接2

参考链接3

官方链接

原理

tcpcopy标准的使用方法:在已有一台线上服务器对外提供服务的基础上A,以及被测试的服务所在机器B,和一台辅助服务器C,同样也建议使用这种方法,中间我尝试去掉辅助机器C但是并没有成功,因此在不熟练使用的情况下建议使用官方标准文档建议的配制方法

tcpcopy的原理简单来说就是在线上服务所在机器的数据链路层进行抓包,之后将数据包头里相应的目的ip、目的端口、来源ip、来源端口替换为相应的测试机器,发往测试机器B,这个时候B收到数据包之后进行响应,这个过程需要借助辅助机器C将响应流量转发给A机器的tcpcopy进程,需要注意的是由于一个完整的数据包涉及到三次握手、数据传输、数据确认、关闭端口一系列复杂的流程,因此这里可以肯定的是辅助机器C在这里所起到的作用应该绝不仅仅是流量黑洞,它从A->B->C->A整个数据流动过程中都起到了作用,不管是ack还是说传输数据。

大晚上写的时候猛然发现白天明天稍稍有些不对,A机器链接辅助进程应该是链接C机器的而不是B机器的,由于使用的时候有过多次尝试,因此在B机器上也有运行辅助进程intercept,结果现象就是B收到了正常的复制流量。。。然而A机器tcpcopy进程连接的一直是B机器的intercept,而不是正确的C机器的,刚刚试验了一下竟然是真的!!C机器的intercept并没有用,这里就比较奇怪了,由于tcpcopy使用的ip层抓包原理,我们先按照官方文档来理解,这种意外情况忽略

下面列一下在各机器上需要执行的命令:

A机器

1
2
3
4
5
6
tcpcopy -x 6080-BIP:6080 -s CIP -l ./tcpcopy.log -c 62.135.200.x -d
# -x 表明将发往本机6080端口的数据发送到BIP的6080端口
# -s表示C机器的ip地址,这里要确保C机器的intercept进程已经启动,这里不指定端口的话会连接intercept进程默认端口
# -l表示将日志输出到文件
# -c表示将发送给B机器的ip包的client ip修改为多少
# -d表示已deamon行驶运行

B机器

1
2
3
route add -net 62.135.200.0 netmask 255.255.255.0 gw CIP
# 这里需要修改路由将发往62.135.200.0/24的数据包发给C机器,这也就是为什么B/C需要在一个网段的原因
# 除此之外只需要启动需要测试的服务进程即可

C机器

1
2
./intercept -i eth0 -F 'tcp and src port 6080' -d
# 这里的-F后面表示要监听的数据包,之后将必要信息通过与A机器tcpcopy建立的端口连接返回必要数据,有没有觉得这个语法很熟悉?因为这就是tcpdump的命令格式!

至此完整的流量拷贝就完成了,这里需要注意的一点是虽然说是流量拷贝但是由于比较底层,是从IP层抓包实现的,因此在某些情况下可能会发现这样执行完之后服务并没有收到请求,但是过上一段时间之后才会有请求过来,这是为什么呢?我猜测原因是这样的:例如client与A建立的是长连接这种情况下链接已经建立成功了,client只需要写数据就ok了,而这时候执行了流量拷贝,在B机器上看到的是端口为SYN_RECV状态,原因应该是因为B机器并没有收到请求建立连接的数据包只是收到了client一直在write的数据包,没有正常建立连接,换句话说就是蒙蒙的状态🤣,当然哈,这是我的理解:)

再就是为什么这里引入了C机器而不是B机器直接写会A机器,我的理解是由于A机器是线上机器,我们的一系列测试都不应该对其造成影响以及过多的资源消耗,作者在说明中又提,正是考虑到尽可能少的占用系统资源,所以才从IP层、链路层对流量进行复制处理后发往B,而B上面服务处理后的回包其实是无意义的数据,我们也不关系,所以把数据包写会的是C机器,C机器对数据包其实就是简单的丢弃,所起到的是一个流量黑洞的功能,这样回包也就不会占用A机器的系统资源啦

最后

tcpcopy还支持离线发送数据,既在A机器上使用tcpdump进行抓包之后使用tcpcopy将数据进行发送,这里需要注意的一点是tcpcopy的离线功能以及其他一些功能是需要在编译的时候指定的:)

就这些把

hello http://just4fun.im/2018/01/15/流量复制工具tcpcopy使用简介/ bye