流量复制-----tcpcopy的使用(1)

前言

TCPCopy是基于网络栈,TCP协议的流量复制,常用的场景是把线上流量复制到测试环境,模拟线上用户操作,让测试机和真实的用户交互,让测试环境在正式灰度前暴露问题,用来排查线下不容易重现的问题,或者对测试环境做压力测试,增加上线信心。
除了占用额外的CPU,内存和带宽外,TCPCopy对生产系统几乎没有影响。此外,在请求多样性,网络延迟和资源占用方面,再现的工作负载与生产工作负载相似。
Github参考地址:https://github.com/session-replay-tools/tcpcopy

原理

tcpcopy 经历了三次架构调整,这三次架构的基本原理都一样,本质是利用在线数据包信息,模拟tcp客户端协议栈,欺骗测试服务器的上层应用服务。由于tcp交互是相互的,一般情况下需要知道测试服务器的响应数据包信息,才能利用在线请求数据包,构造出适合测试服务器的请求数据包,因此只要基于数据包的方式,无论怎么实现(除非是tcp协议改的面目全非),都需要返回响应包的相关信息。 三种架构的差别就在于在什么地方截获响应包。
三种架构的区别:https://blog.csdn.net/wangbin579/article/details/8949315
TCPCopy由两部分组成: tcpcopy和intercept。tcpcopy负责抓包和发包工作,而intercept负责截获应答包

架构描述

流量复制-----tcpcopy的使用(1)_第1张图片
tcpcopy包含三部分:online server(线上服务器)、assistant server(辅助服务器)、target server(目标服务器即测试服务器)
访问流程(官方说明)
1、一个访问请求到达线上内核后端机;
2、socket 包在 IP 层被拷贝了一份传给tcpcopy 进程;
3、tcpcopy 修改包的目的及源地址,发给测试内核后端机;
4、拷贝的包到达测试内核后端机;
5、测试内核后端机的推荐内核处理访问,并返回结果;
6、返回结果在 IP 层被截获、丢弃,由 intercept 拷贝返回结果的 IP header 返回;
7、IP header 被发送给线上内核后端机的 tcpcopy 进程。

通俗解释:
假如三个机器IP如下:
线上服务器 --> 192.168.124.105
测试服务器 --> 192.168.124.68
辅助服务器 --> 192.168.124.180

  1. tcpcopy运行在线上服务器上,tcpcopy会把线上服务器收到的流量,重放给测试服务器,重放的时候tcpcopy修改了IP数据包的源IP地址(譬如修改源地址为192.168.2.254)。所以,线上服务器和测试服务器应该部署相同的服务。
  2. tcpcopy把源IP伪造成192.168.2.254的包发给了测试服务器,如此,测试服务器在处理完tcpcopy发过来的数据以后,会把这些数据包返回给客户端,即伪造的192.168.2.254。
  3. 由于没有192.168.2.254这个地址,我们在测试服务器添加一条专门的路由,把发往192.168.2.0/24的数据包,都全部转交给辅助服务器。
  4. 为了保证辅助服务器会接受这些本不属于自己的,部署在辅助服务器上的intercept就发挥作用了。辅助服务器还可以用来把客户端的请求返回给tcpcopy,但是默认只返回响应头部给tcpcopy。辅助服务器类似于黑洞。即:数据到达 assistant server 后被 intercept 进程截获。过滤相关信息将请求状态发送给 online server 的 tcpcopy,关闭 tcp 连接

详细介绍

工作模式:
1 线上实时拷贝数据包
2 通过使用tcpdump等抓包生成的文件进行离线(offline)请求重放
如果采用实时拷贝线上流程进行导入的方式,需要分别在线上服务器和测试服务器安装tcpcopy,对于离线模式,只需要在测试服务器上安装tcpcopy,编译时指定 --enable-offline。
其中请求实时复制,一般可以分为两类:
1)基于应用层的请求复制 ,
2)基于底层数据包的请求复制。
如果从应用层面进行复制,比如基于服务器的请求复制,实现起来相对简单,但也存在着若干缺点:
1)请求复制从应用层出发,穿透整个协议栈,这样就容易挤占应用的资源,比如宝贵的连接资源
2)测试跟实际应用耦合在一起,容易影响在线系统,
3)也因此很难支撑压力大的请求复制,
4)很难控制网络延迟。

而基于底层数据包的请求复制,可以做到无需穿透整个协议栈,路程最短的,可以从数据链路层抓请求包,从数据链路层发包,路程一般的,可以在IP层抓请求包,从IP层发出去,不管怎么走,只要不走TCP,对在线的影响就会小得多。这也就是 TCPCopy 的基本思路,目前基本使用第二个。
使用场景:

  1. 压力测试
  2. 回归测试
  3. 线上问题重现

安装部署

略(以二线部署手册为准)
参考地址:https://github.com/session-replay-tools/tcpcopy
使用方法
一、 实时复制流量
tcpcopy -x 8000-192.168.124.68:8000 -s 192.168.124.180 -c 192.168.2.254 -n 2 -d
• -x, 是指本机8000端口的流量copy到192.168.124.68的8000端口
• -s, 指定intercept机器的地址,tcpcopy要和intercept建立连接
• -c 伪装地址,在把流量复制到测试服务器的时候,修改数据包的源地址为192.168.2.254,这样方便指定路由。也可以写成192.168.2.x,这样源地址就是指定网段中的地址了。
• -n 流量放大倍数,如果不是压测目的就不用指定这个参数。
-d 以守护模式运行。
其他常用参数说明
• -i 其中file 是pcap 离线文件的文件路径
• -o < device,> 指定从哪个网卡设备上发包
需注意如下事项:
1)此参数只有在编译./configure --enable-dlinject 模式下才有效
–enable-dlinject说明此模式是为了支持tcpcopy 能够从数据链路层发送请求数据包。从数据链路层发包的好处是不会去干扰在线服务器的IP 模块(比如不会去干扰ip_conntrack 模块),但不好的地方是需要自己去解决路由问题。
2)-o 参数需要设置成与转发IP 地址相匹配的网卡设备
tcpcopy -o eth0 -x 12345-221.130.189.25:12345
比如:转发IP 地址为外网IP 地址,那么-o 参数就设置成外网网卡设备的名称
• -I 参数离线模式下,降低请求之间的间隔,对稀疏的请求访问,其加速非常有效果
./tcpcopy -x 80-192.168.0.2:8080 -I 1000 -i online.pcap
对请求之间间隔1000毫秒以外的请求进行加速
注意只有在离线模式下有效
• -a 参数
离线模式下,对请求数据包的访问进行加速
举例:假设online.pcap 文件为在线请求数据包的抓包文件,时间为60 分钟
./tcpcopy -x 80-192.168.0.2:8080 -a 2 -i online.pcap
执行此命令后,离线回放加速了2 倍,只需要30分钟,离线回放就能完成
需要注意的是,此命令只有在离线模式下才有效,而且-a 参数设置越大,丢请求的概率
也越大。

• -r 参数
如果你想复制在线服务器应用的部分流量,可以采用-r 参数来实现,参数范围是1~99,其它值都是全流量复制。
举例:
./tcpcopy -x 80-192.168.0.2:8080 -r 20
这里tcpcopy 复制在线服务器8080 端口应用的20%流量给后端服务器,需要注意的是
20%是根据session(这里session 是由客户端IP,客户端端口决定)来统计的。
-r 参数常见于对测试应用进行profile 的场合或者测试服务器配置不如在线服务器的场合

二、离线复制流量
使用tcpdump抓包
tcpdump -i eth0 -w test.pcap tcp and port 8000 -c 100
流量回放
tcpcopy -x 8000-192.168.124.68:8000 -s 192.168.124.180 -c 192.168.2.254 -i test.pcap
阿里云环境下的TCP Copy环境部署参考
云环境下,安全策略可能会干扰测试的进行。按物理机步骤部署会出现大量TCP SYN_RECV状态,需要采用如下步骤可以规避麻烦:

  1. 测试机器和intercept部署到一台机器
  2. tcpcopy端-c参数采用tcpcopy所在的线上机器ip地址
  3. 在线上机器设置iptables黑洞来过滤掉测试服务器的响应包
  4. iptables -I INPUT -p tcp --sport 测试服务的端口 -j DROP -s 测试服务所在机器的ip地址
  5. 不要在测试服务器设置路由,否则会受到干扰
    测试结果
    在线上服务器开启tcpcopy: # /opt/tcpcopy/sbin/tcpcopy -x 8000-192.168.124.68:8000 -s 192.168.124.180 -c 192.168.2.254 -n 2 -d
    在另外一台机器上,向线上服务器发起请求,然后查看两个HTTP服务器的实时日志,
    线上服务器的结果:

发起了两次请求,由于url不存在,返回了404的HTTP Code。再看测试服务器:

在测试服务器上,请求变成了四次,明显看到流量被放大了1倍。效果正如预期。除此之外,还可以看到日志中的客户端IP也不一样。在原始的请求中,解析出来了主机名为Matrix3,而在测试机器上,客户端IP是192.168.2.254,就是我们捏造的IP,注意伪造IP的时候,一定要避免环境中存在的IP和常用的IP。
注意
• 辅助服务器要扮演成一个黑洞,所以不能开启ip_forward
• 在请求会修改数据的地方,譬如修改数据库,如果配置不当,可能导致数据被重复修改多次。
占用cpu内存空间实例(实例有点老,但):

注意事项

  1. 仅在Linux(内核2.6或更高版本)上进行了测试
  2. 不支持使用SSL/TLS协议的,比如加密协议https等
  3. 可能会丢包:线上机器,测试机器以及辅助机器部署在同一个网段,或者使用代理,可以降低丢包率
  4. 需要root权限和CAP_NET_RAW功能(CAP_NET_RAW:允许使用原始套接字)
  5. TCPCopy现在仅支持客户端启动的连接
  6. ip_forward不应在助手服务器上设置
    影响因素
    有几个因素可能影响TCPCopy,以下部分将详细介绍。
    1.捕获接口
    默认情况下,tcpcopy使用原始套接字输入接口来捕获在线服务器上网络层的数据包。当系统繁忙时,系统内核可能会丢失一些数据包。
    如果使用“ --pcap-capture” 配置tcpcopy,则tcpcopy可以在数据链路层捕获数据包,还可以过滤内核中的数据包。使用PF_RING,tcpcopy在使用pcap捕获时将丢失更少的数据包。
    捕获请求的最佳方法可能是通过交换机镜像入口数据包,然后通过负载平衡器将巨大的流量分配到多台计算机。
    2.发送接口
    默认情况下,tcpcopy使用原始套接字输出接口将网络层的数据包发送到目标服务器。如果要避免ip_conntrack问题或获得更好的性能,请使用“ --pcap-send” 配置tcpcopy,然后使用适当的参数tcpcopy可以在数据链路层将数据包发送到目标服务器。
    3.在通往目标服务器的途中
    通过tcpcopy发送数据包时,它在到达目标服务器之前可能会遇到很多挑战。由于数据包中的源IP地址仍然是最终用户的IP地址(默认情况下),而不是在线服务器的IP地址,因此某些安全设备可能会将其用于无效或伪造的数据包,并将其丢弃。在这种情况下,当您使用tcpdump捕获目标服务器上的数据包时,将不会捕获来自预期最终用户的数据包。要知道您是否处于这种情况下,可以选择同一网段中的目标服务器进行测试。如果数据包可以在同一网段中成功发送到目标服务器,但跨网段未成功发送,则您的数据包可能会中途丢失。
    为解决此问题,我们建议在同一网段的服务器上部署tcpcopy,目标应用程序和拦截程序。在同一网段中的代理服务器的帮助下,还有另一种解决方案。tcpcopy可以将数据包发送到代理,然后代理将相应的请求发送到另一个网段中的目标服务器。
    请注意,在同一网段中的一台虚拟机上部署目标服务器的应用程序可能会遇到上述问题。
    4.目标服务器的操作系统
    目标服务器可以设置rpfilter,它将检查数据包中的源IP地址是否是伪造的。如果是,则该数据包将在网络层被丢弃。
    尽管目标服务器上的tcpdump可以捕获数据包,但目标服务器仍未收到任何请求,则应检查是否有相应的rpfilter设置。如果已设置,则必须删除相关设置以使数据包通过网络层。
    还有其他导致tcpcopy无法正常工作的原因,例如iptables设置问题。
    5.目标服务器上的应用程序
    目标服务器上的应用程序可能无法及时处理所有请求。一方面,应用程序中的错误可能会使请求长时间不响应。另一方面,TCP层之上的某些协议可能只处理套接字缓冲区中的第一个请求,而使套接字缓冲区中的其余请求保持未处理状态。
    6.助手服务器的操作系统
    您不应将ip_forward设置为true,否则助手服务器不能充当黑洞。

你可能感兴趣的:(流量复制)