找回密码
 会员注册
查看: 20|回复: 0

实时流量回放工具TCPCopy原理浅析

[复制链接]

3

主题

0

回帖

10

积分

新手上路

积分
10
发表于 2024-10-12 00:13:08 | 显示全部楼层 |阅读模式
简述随着互联网技术的发展,服务端的架构愈加复杂,仅依赖QA个人的经验很难覆盖到全面的业务场景,真实的线上流量对于服务端的测试十分必要。TCPCopy就是一款开源,并广泛应用于各大公司的流量回放工具。相信有很多人都在自己的项目中使用TCPCopy进行测试,但是可能对其底层原理不甚了解。本文通过对TCPCopy的原理作较为简单的介绍,希望对读者有所帮助。架构TCPCopy的架构历经几次升级,本文介绍最新的1.0版本架构。如图所示,TCPCopy由两部分组成:tcpcopy和intercept。tcpcopy在线上服务器上运行并捕获在线tcp类型的请求数据包,修改TCP/IP头部信息,发送给测试服务器,巧妙地达到“欺骗"测试服务器的目的。intercept在辅助服务器上运行并执行一些辅助工作,例如将响应信息传递给tcpcopy。简略的交互流程如下:①. tcpcopy在线上服务器抓包,解析出ip报文段②. tcpcopy修改ip头和tcp头,伪造源ip和端口,发包给测试机,伪造的ip地址参考启动时的-x和-c参数③. 测试机接收请求,返回结果包,目前ip为tcpcopy伪造的ip和端口④. 结果包被路由到intercept机器,被intercept捕获,intercept解析出ip头和tcp头,返回空响应数据给tcpcopy⑤. tcpcopy接收到返回数据技术原理tcpcopy的工作模式分为在线和离线工作方式,在线方式主要用来实时捕获在线请求数据包,离线方式主要从pcap格式的文件中读取在线请求数据包。虽然工作方式不同,但其核心原理是相同的,下文主要分几部分介绍tcpcopy的核心原理 。1. 抓包与发包tcpcopy的核心功能可以简单概括为“抓包”和“发包”,那我们就先从“抓包”开始谈起。如何抓取服务器的真实流量,相信很多小伙伴和我一样,一开始面对这个问题是一头雾水,其实linux操作系统已经为我们提供了相关的功能,只需要我们对linux的高级网络编程进行了解。tcpcopy关于抓包和发包的代码初始化都在tcpcopy/src/communication/tc_socket.c中,下面介绍tcpcopy抓包的两种方式:raw socketraw socket,即原始套接字,可以接收本机网卡上的数据帧或者数据包,对于监听网络的流量和分析是很有作用 。tcpcopy中关于初始化抓包raw socket的代码如下图,可以看出这种方式可以支持数据链路层和ip层的抓包初始化发包raw_socket的代码如下图,首先创建ip层的raw socket套接字,并告诉协议栈ip层不再追加ip头构建完整的ip数据报,发送给对方● 其中dst_addr填充目的ip● ip头填充源ip,目的ip等● tcp头填充源端口,目的端口等pcappcap是操作系统提供的一个用于捕获网络流量的应用程序接口(API),其名称来源于“抓包”(packet capture)。linux系统通过libpcap实现了pcap,大多数流量抓取工具如tcpdump、goreplay等也都是使用libpacp进行抓包。在windows系统中提供了winpcap库实现了pcap。初始化发包pcap的代码如下图raw socket VS pcap既然tcpcopy提供了两种方式,那么哪一种方式更好呢?对于抓包,我们关心的只是我们想要的包,如果抓包方式设置不当,系统内核就会把多余的包都抓取到,如果流量压力越大,一般丢包会越多。经过长时间测试,利用pcap接口抓请求数据包的方式,平均丢包率高于raw socket抓请求数据包的方式。tcpcopy也默认采用了raw socket 抓包,当然也可以采用pcap接口(--enable-pcap)。对于发包,tcpcopy默认采用了raw socket output接口,也可以通过pcap_inject(--enable-dlinject)来发包,具体使用哪种方式可以在自己的实际环境中测试其性能表现来作选择。2. tcp协议栈我们知道tcp协议是有状态的协议,虽然上面介绍了发包的原理,但是如果不建立起来一个真正的tcp连接,我们发送的包也无法真正被测试服务接收。在日常的网络编程中,我们可以使用操作系统封装好tcpsocket接口进行编程,无需对于tcp状态太过关心,但在tcpcopy要修改数据包源ip及目的ip,达到欺骗测试服务的目的,那么操作系统提供的API也就不满足要求了。所以,tcpcopy实现了一个模拟的tcp有效状态机,这也是tcpcopy源码中最为复杂,最具难度的地方,具体的代码在tcpcopy/src/tcpcopy/tc_session.c中tcpcopy中定义了一个session,用来维护不同的连接信息,对于抓的不同数据包,会做不同的处理:–Syn包,新的连接请求,分配源ip,修改目的ip, port,发送给测试机,同时新建一个session,保存此次会话中的所有状态。–Ack包● 纯ack包,不发送● 有payload(说明是具体请求),找到session,发送给测试机。如果本session正在等待上次请求的响应,那么暂缓发送。–Rst包,如果本次会话正在等待测试机结果返回,就不发送,否则发送–Fin包,如果本次会话正在等待测试机结果返回,就等待,否则发送3. 路由tcpcopy发出请求数据包后,其路途可能不会是“一帆风顺”的。● 该请求包的ip已经是伪造的ip,而非tcpcopy所在机器的ip,所以如果有些机器设置了rpfilter(反向过滤技术),将会判断源IP地址是否是所信任的IP地址,如果不是,将会在IP层丢弃掉该数据包。● 如果测试服务接收到了请求数据包,那么返回的数据包会返回给伪造的ip地址,也就是intercept机器所在的ip,这个时候如果没有填写intercept机器的真实ip地址,那么就需要路由的配置了,如果没有配置正确的路由,响应包没有被intercept捕获,仍然无法完成一次完整的数据交互。● intercept捕获到响应包后,会取出ip数据报,将具体的数据丢弃,只返回给tcpcopy响应头等必要信息,减少对tcpcopy所在机器的网络影响。4. intercept刚开始接触tcpcopy的同学可能有和我一样的困惑,有了tcpcopy,为什么还需要一个intercept呢?intercept看起来好像十分多余,实际上却承载了重要的工作。intercept可以理解为tcpcopy的服务端,其名字本身就解释了它的作用:“拦截器”。那么什么东西需要intercept来拦截呢?答案是测试服务的响应数据。设想一下,如果没有intercept,测试服务的响应数据只能返回给tcpcopy,而tcpcopy是部署在线上的,也就是说测试服务会直接把响应数据全部返回给线上服务器,这毫无疑问会大大增加线上服务器的网络负载,甚至对在线的服务本身造成影响。有了intercept后,通过对源ip进行伪造,可以对测试服务进行协议栈的“欺骗”,也就是让测试服务“误以为”intercept所在机器就是给它发请求的机器,而对于真实的线上机器根本“一无所知”,这保证了线上环境不被测试环境所影响。intercept是一个单独的进程,其抓包方式默认采用pcap方式进行抓包,启动的时候需要传入-F参数,如” tcp and src port 8080“,需要符合libpcap的过滤语法。也就是说intercept本身不与测试服务有连接,而且监听指定的端口,抓取测试服务的返回数据包,然后与tcpcopy进行交互。5. 性能tcpcopy采用了单进程单线程架构,基于epoll/select事件驱动,相关的代码都在tcpcopy/src/event中。默认在编译时使用了epoll,也可以使用select(--select),可以根据测试结果的性能差异选择不同的方式,理论上来说如果连接数较多的情况下,epoll方式的性能会更好。在实际的表现中,tcpcopy的性能和流量的大小直接相关,也与intercept建立的连接数有关,单线程本身并不会成为性能的瓶颈(nginx和redis都采用了单线程+epoll的方式,都能达到很大的并发)。因为tcpcopy与intercept直接建立连接,与测试机器不需要建立连接,也不需要耗费任何端口号,所以tcpcopy本身耗费的资源并不多,主要表现在对网络带宽的消耗。结语TCPCopy是一款十分优秀的开源项目,但因为能力有限,本文只介绍了TCPCopy的核心技术原理,很多细节并未涉及。不过还是希望通过本文的介绍,能够对TCPCopy和流量回放技术感兴趣的同学有所启发!分享给第一个想到的人
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 会员注册

本版积分规则

QQ|手机版|心飞设计-版权所有:微度网络信息技术服务中心 ( 鲁ICP备17032091号-12 )|网站地图

GMT+8, 2024-12-27 00:35 , Processed in 1.110108 second(s), 25 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表