tcprelay使用<一>

前言:

tcpreplay是一种pcap包的重放工具, 它可以将用ethreal, wireshark工具抓
下来的包原样或经过任意修改后重放回去. 它允许你对报文做任意的修改(主要是指对2层
, 3层, 4层报文头), 指定重放报文的速度等, 这样tcpreplay就可以用来复现抓包的情景
以定位bug, 以极快的速度重放从而实现压力测试.
tcpreplay本身包含了几个辅助工具, 用于准备发包的cache, 重写报文等:
    * tcpprep - 简单的说就是划分哪些包是client的, 哪些是server的, 一会发包的
    时候client的包从一个网卡发, server的包可能从另一个网卡发.
    * tcprewrite - 简单的说就是修改2层, 3层, 4层报文头部. 
    * tcpreplay - 真正发包, 可以选择主、从网卡, 发包速度等.
    * tcpbridge - bridge two network segments with the power of tcprewrite 

一、Linux系统安装tcprelay:

a. yum install epel-release

b. yum install tcpreplay

二、Tcpreplay套件包括以下工具:

    • tcpprep- 多通道pcap文件预处理器,用于将数据包确定为客户端还是服务器,并创建tcpreplay和tcprewrite使用的缓存文件
    • tcprewrite -pcap文件编辑器,用于重写TCP / IP和第2层数据包
    • tcpreplay- 以任意速度将pcap文件重播到网络上
    • tcpliveplay- 使用新的TCP连接在实时网络上重放存储在pcap文件中的网络流量
    • tcpreplay- edit-以任意速度将pcap文件重放和编辑到网络上
    • tcpbridge-使用tcprewrite的功能 桥接两个网段
    • tcpcapinfo- 原始pcap文件解码器和调试器
      除了tcpliveplay以外,其他工具都只是单纯的发包,不会建立TCP连接,也不会维护SEQ/ACK

三、Tcpreplay的发包机制

所谓回放数据包的意思就是,将这个数据包的流向再次重现,也就是说再把这个数据包的流向走一遍。所以tcpreplay是检测数据包的包头的内容里面的源、目的地端的内容,目的端的地址是多少就发往哪里,知道这个我们就清楚我们在使用tcpreplay重放的时候,各种数据包都流向了哪里,这个时候只需要拿wireshark拦截,就可以很清楚的看到各种数据包。

四、.Tcpreplay做不到服务端能实时响应的回放

回答 :使用Tcpreplay回放Pcap流量,Tcpreplay只能保证发出去,如果想要服务端响应的话,需要使用tcpliveplay(使用tcpreplay回放tcp的时候,不能同步TCP里面Syn/Ack的编号)。

五、在Tcpreplay服务端只能抓到单方向的流量

问题描述:在服务端通过nc -l 1234监听1234端口,在客户端连接服务端通过:

问题描述:在服务端通过nc -l 1234监听1234端口,在客户端连接服务端通过:

nc -nvv server_ip 1234

命令,客户端向服务端发送数据。
与此同时在客户端抓取流量,保存为chat.pcap。

tcpdump -i eth0  host server_ip  -w chat.pcap

然后在客户端进行回放:

tcpreplay -i eth0 chat.pcap

,在服务端抓取:

tcpdump -i host client_ip

结果显示,只有客户端发送服务端的流量,服务端发往客户端的流量没有,为何会出现这种情况?
回答:tcpreplay回放只是把数据包发出去,数据包去往何处,根据的是目标地址。对于客户端->服务端的流量,目标为服务端,所以这个方向的流量会发往服务端。而对于服务端->客户端的流量,此时目标为客户端,所以这个方向的流量,不会发往服务端,而是在客户端。

六、修改MAC地址的注意事项

对于不属于同一局域网下的两台主机,修改目的IP的MAC地址的时候,MAC地址不是目的机网卡物理地址,而是源机器所连接的交换机MAC地址。

七、关于tcpreplay发包的错误积累帖

排错-tcpreplay回放错误:send() [218] Message too long (errno = 90)

问题描述:

tcpreplay回放.pcap报文出现如下错误

Warning: Unable to send packet: Error with PF_PACKET send() [215]: Message too long (errno = 90)

wireshake打开数据包,可以看到数据包长度,其中有超过1w的,已经超过了MTU值(MTU默认为1500),所以问题的解决方法是修改系统的MTU值。

723 0.076477    10.130.39.1 10.130.39.9 TCP 52191 > cvmmon [PSH, ACK] Seq=75174 Ack=1 Win=65535 Len=11546

解决方法:

修改发送数据包网卡的MTU值

例:

# ifconfig eth3 mtu 9216

重新发包

#tcpreplay -i eth3 -t -l 1 xx.pcap

发现正常发包了

说明:

每一种链路层协议都规定了帧的数据部分的长度上限--最大传送单元(MTU,Maximum Transfer Unit),如下

排错-tcpreplay回放错误:send() <wbr>[218] <wbr>Message <wbr>too <wbr>long <wbr>(errno <wbr>= <wbr>90)

八、Tcprelay的使用:

官网:https://github.com/appneta/tcpreplay

以前的版本貌似可以用一个命令把pcap包直接经过修改发出去, 但是3.0以后的
tcpreplay不支持这样了, 发包前先得用tcpgrep建立一个cache, 再用tcprewite修改包的
信息, 最后用tcpreplay发出去:
建立cache文件的作用解释,主要是加速报文的发送,cache文件中存放着pcap文件中每个
帧的编号和时间戳等信息,以达到tcpreplay回放时可以更加快速的发送报文的目的。

8.1 tcpprep(pcap pre-processor)

tcpprep工具会生成一个cache文件, 里面保存着哪些包将从主网口发出去, 哪些包将从从

网口发出去. 举个例子, 如果你用wireshark抓了一个pcap文件, 里面可能既有A地址发给
B地址的包, 也有B地址发给A址的包, 用tcpprep工具可以指定从A到B的包从主网卡发出, 
从B到A的包从次网卡发出.

8.1.1 根据报文源IP确定client/server报文

#tcpprep的用法举例, 根据源IP:
| $ tcpprep -c 172.22.64.2/24 -i mgcp.pcap -o mgcp.cach
上面的命令指定所有源IP为172.22.64.2/24的包, 都将从主网卡发出, 其它的从次网卡发
出. 输入文件是mgcp.pcap, 输出文件为mgcp.cach.

8.1.2 使用自动模式确定client/server报文

#tcpprep的用法举例, 自动模式:
| $ tcpprep -a client -i mgcp.pcap -o mgcp.cach
上面的命令采用自动/client模式指定分包模式. 自动模式这里按我的理解解释一下:
tcpprep在自动模式下认为有下面行为的IP为client端: 1.发TCP SYN包的一方, 2.发DNS 
包的一方, 3. 收入到 ICMP-Port Unreachable的一方. 认为有下面行为的一方为server 
端: 1.发TCP Syn/Ack的一方, 2.发DNS应答的一方, 3.发ICMP-Port Unreachable的一方.
而被认定为server的那一方发的那些包, 将从主网卡发出, 被认定为client的包则从次网
卡发出. 而自动/client模式将所有没有认出的包都归为client, 同理自动/server模式将
没有认出的包都归为server.这种模式貌似不如按IP地址分类的方式好用.
tcpprep还有很多其它指定发送方向的方式, 详情请阅Online Manual或man手册.

8.2 tcprewrite

简单地说, tcprewrite就是改写pcap包里的报文头部, 包括2层, 3层, 4层, 5-7层. 从3.0
版本以后, 所有改写pcap报文头的操作都从tcpreplay中移到了tcprewrite里了.
使用tcprewrite对packet进行修改可以有两个方法, 一种方法是一次修改一项, 生成一个
文件, 再拿这个文件作为输入文件..., 直到完成最后的修改, 如:
tcprewrite --option1=xxx -c input.cach -i input.pcap -o 1.pcap
tcprewrite --option2=xxx -c input.cach -i 1.pcap -o 2.pcap
...
tcprewrite --optionN=xxx -c input.cach -i N-1.pcap -o N.pcap

还有一种方法是一古脑的把所有的选项放到一个命令里完成, 如:

tcprewrite --option1=xxx --option2=xxx ... --optionN=xxx -i input.pcap -c input.cach -o out.pcap

两种方法都是可行的, 也各有利弊. 第一方法明了, 但是复杂, 第二种方法简单但不容易
理解. 我的建议是先用第一种方法做试验, 容易调试, 等修改成功了以后再把所有的选项
合到一起, 在实际使用的时候用第二种方法. 下面我先给出一个例子, 然后再逐个分析一
下用tcprewrite是如何修改二层, 三层, 四层, 5-7层头的, 以便理解tcprewrite的工作原
理.

8.2.1 tcprewrite的一个例子

tcpreplay只保证能把包送出去, 至于包真正能到达的地址, 我认为还是根据原来的包的
IP和mac. 如果是在同一网段, 可能需要把mac地址改成测试设备的mac, 如果需要经过网
关, 就得将IP地址改为测试设备的IP以及端口号.
tcprewrite的基本格式是(请注意命令中是没有换行符的, 只为了阅读的方便添加了换行
符): 详请可以用tcprewrite ?命令查询详情.
#tcprewrite的格式:
|$ tcprewrite --enet-smac=host_src_mac,client_src_mac   \
|              --enet-dmac=host_dst_mac, client_dst_mac \
|              --endpoints=host_dst_ip:client_dst_ip    \
|              --portmap=old_port1:new_port1,old_port2, new_port2 \
|              -i input.pcap -c input.cach -o out.pcap
解释一下, 该命令的输入参数是input.pcap和input.cach文件, 结果将另存为out.pcap文
件. 该命令将所有input.pcap包里的主机包(由input.cach文件指定哪些包是主机包, 哪些
包是客户端包)的源mac地址, 目的mac地址, 目的IP地址分别改为 :host_src_mac,
host_dst_mac和host_dst_ip, 客户端包源mac地址, 目的mac地址, 目的IP地址分别改为
:client_src_mac, client_dst_mac和client_dst_ip, 将端口号由old_port1改为
new_port1, 将端口号由old_port2改为new_port2.
#tcprewrite的用法举例:
|$ tcprewrite --enet-smac=11:22:22:22:22:22,22:22:22:22:22:22   \
|             --enet-dmac=11:11: 11:11:11:11,22:11:11:11:11:11  \
|             --endpoints=192.168.0.1:192.168.0.11              \
|             --portmap=5070:5061,9060:5060                     \
|             -i success.pcap -o out.pcap -c success.cach
该命令将修改后的包, 主机包的二层, 三层, 四层头分别为: 11:22:22:22:22:22,
192.168.0.1, 5061, 客户端包的二层, 三层, 四层头分别为: 22:22:22:22:22:22,
192.168.0.11, 5060.

8.2.2 修改2层头1)  

修改MAC地址
如果不指定cache文件, 将把所有包的源mac地址和目的mac地址都改写成
00:44:66:FC:29:AF和00:55:22:AF:C6:37:
    $ tcprewrite --enet-dmac=00:55:22:AF:C6:37 --enet-smac=00:44:66:FC:29:AF --infile=input.pcap --outfile=output.pcap
指定cache文件后, 将server包的目的/源mac地址改写成
00:44:66:FC:29:AF/00:66:AA:D1:32:C2, 将client的目的/源mac地址改成:
00:55:22:AF:C6:37/00:22:55:AC:DE:AC, 注意是server地址在前.
    $ tcprewrite --enet-dmac=00:44:66:FC:29:AF,00:55:22:AF:C6:37 --enet-smac=00:66:AA:D1:32:C2,00:22:55:AC:DE:AC --cachefile=input.cache --infile=input.pcap --outfile=output.pcap
2)  修改802.1q VLAN
经常客户的抓包带有VLAN头域, 这些包如果不去掉VLAN头是没有办法在自己的交换机上
replay的, tcprewrite提了去掉或添加VLAN的方法:
去掉vlan很简单:
    $ tcprewrite --enet-vlan=del --infile=input.pcap --outfile=output.pcap
添加vlan也很简单, 下面的命令将VLAN tag设成40, CFI设成1, VLAN priority设成4. 
    $ tcprewrite --enet-vlan=add --enet-vlan-tag=40 --enet-vlan-cfi=1 --enet-vlan-pri=4 --infile=input.pcap --outfile=output.pcap
3)  修改二层协议名:
好像是将Ethernet协议头转成Cisco HDLC或其它二层协议? 这部分没有真正用过, 需要的
人自行参考[2].

8.2.3 修改3层头

从版本3.4.2开始, tcprewrite开始支持ipv6协议(我写这篇文章的时候版本号还是3.4.1呢
, tcpreplay升级蛮快哦^)^). tcprewrite修改IP地址后会自动帮你计算校验和, 这点还是
蛮周到的^)^, 命令行传入IPv6地址的时候要使用方括号, 例如: [2001::dead:beef]或
[2001::/16]
1)  修改目的IP
根据cache文件里的标识, 将server的IP改为10.10.1.1, client的IP改为10.10.1.2:
$ tcprewrite --endpoints=10.10.1.1:10.10.1.2 --cachefile=input.cache --infile=input.pcap --outfile=output.pcap --skipbroadcast 
2)  修改IP地址的网络部分
注: 2)和3)没有验证过
众所周知, IP地址同网络部分和主机部分组成, 下面的命令可以将子网地址为10.0.0.0/8
或192.168.0.0/16的IP改成子网为172.16.0.0/12:
    $ tcprewrite --pnat=10.0.0.0/8:172.16.0.0/12,192.168.0.0/16:172.16.0.0/12 --infile=input.pcap --outfile=output.pcap --skipbroadcast
下面的命令是基于client包或server包修改子网地址:
    $ tcprewrite --pnat=10.0.0.0/8:192.168.0.0/24 --pnat=10.0.0.0/8:192.168.1.0/24 --cachefile=input.cache --infile=input.pcap --outfile=output.pcap --skipbroadcast
3)  修改IP头的其它部分:
修改IPv4头的TOS为50
    $ tcprewrite --tos=50 --infile=input.pcap --outfile=output.pcap
将IPv6头Traffic Class值改为33
    $ tcprewrite --tclass=33 --infile=input.pcap --outfile=output.pcap
修改Flow Label field:
    $ tcprewrite --flowlabel=67234 --infile=input.pcap --outfile=output.pcap

8.2.4 修改4层头和修改IP头一样

修改4层头的时候tcpwrite会自动计算校验和, 这个就不需要担心了.
1)  修改端口号
将80端口号改为8080, 22改为8022:
    $ tcprewrite --portmap=80:8080,22:8022 --infile=input.pcap --outfile=output.pcap
2)  强制计算传输层校验和:
有些应用可能不计算传输层的校验和, 可以让tcpwrite强制计算一下:
   $ tcprewrite --fixcsum --infile=input.pcap --outfile=output.pcap

8.2.5 修改5-7层数据

tcpwrite对5-7层的修改非常有限, 顶多也就是抓包没有抓全, 中间的应用层数据丢了.
tcpwrite将没有抓到的数据补成全0, 或者修改tcp/udp的长度字节, 或者将该包丢弃. 有
需要的直接参考官方资料吧.[2]

8.3 tcpreplay在linux下, 用ifconfig命令可以获得接口的名字, 但在cygwin下必须用下面的命令获得接口的名字:

#在cygwin下获得接口的名字:
| $ tcpreplay --listnics
#结果可能如下所示:
| $ tcpreplay --listnics
| Available network interfaces:
| Alias   Name    Description
| %0      \Device\NPF_GenericDialupAdapter
|         Adapter for generic dialup and VPN capture
| %1      \Device\NPF_{6B508B29-B3E3-4D0B-892F-02914AC9A668}
|     Intel(R) 82566DM Gigabit Network Connection (Microsoft's Packet
|     Scheduler) 
| %2      \Device\NPF_{CBCE38CA-1FAD-4AEB-89DF-FD2D8EF861FA}
|     D-Link DFE-530TX PCI Fast Ethernet Adapter (rev.C)
|     (Microsoft's Packet Scheduler) 
| %3      \Device\NPF_{ABB813FE-3C51-49A3-8146-16CD2C4507C3}
|     D-Link DFE-530TX PCI Fast Ethernet Adapter (rev.C)
|     (Microsoft's Packet Scheduler) 
从中可以看出这台机器有两块网卡, 一块叫做%1, 另一块叫做%2. 下面就可以指定网卡
重发包了:
#用tcpreplay发包:
| $ tcpreplay -c mgcp.cach -i %1 -I %2 out.pcap
这条命令是把out.pcap包, 按照mgcp.cach里划分的主机包和客户端包的方式, 将主机包
从网卡%1发出去, 将客户端包从网卡%2发出去.

九、tpcrepaly参数介绍:

-i <nic> Primary interface to send traffic out of 双网卡回放报文必选参数,指定主接口。
-I <mac> Rewrite dest MAC on primary interface 可选参数,重写主网卡发送出报文的目的 MAC 地址。 
-j <nic> Secondary interface to send traffic out of 双网卡回放报文必选参数,指定从接口。
-J <mac> Rewrite dest MAC on secondary interface 可选参数,重写从网卡发送出报文的目的 MAC 地址。 
-k <mac> Rewrite source MAC on primary interface 可选参数,重写主网卡发送报文的源 MAC 地址。 
-K <mac> Rewrite source MAC on secondary interface可选参数,重写从网卡发送报文的源 MAC 地址。
-l <loop> Specify number of times to loop 可选参数,指定循环的次数,测试过程发现不是那么好用,有待确认。
-L <limit> Specify the maximum number of packets to send 可选参数,指定最大的发包数量。可以在确认连接的调试时使用。 
-m <multiple> Set replay speed to given multiple 可选参数,指定一个倍数值,就是必默认发送速率要快多少倍的速率发送报文。 加大发送的速率后,对于 DUT 可能意味着有更多的并发连接和连接数,特别是对 于 BT 报文的重放, 因为连接的超时是固定的, 如果速率增大的话, 留在 session 表中的连接数量增大,还可以通过修改连接的超时时间来达到该目的。
-M Disable sending martian IP packets 可选参数,表示不发送“火星”的 ip 报文,man 文件中的定义是 0/8、172/8、 255/8。 -
-n Not nosy mode (not promisc in sniff/bridge mode) 可选参数,在使用-S 参数,不对混杂模式进行侦听。没有测试过。
-N <CIDR1:CIDR2,...> Rewrite IP's via pseudo-NAT 可选参数,通过伪造的 NAT,重写 IP 地址。这个参数应该有很重要的应用,目 前没有测试使用。
-O One output mode 可选参数,没有测试使用 
-p <packetrate> Set replay speed to given rate (packets/sec) 可选参数,** 指定每秒发送报文的个数**, 指定该参数, 其它速率相关的参数被忽略, 最后的打印信息不会有速率和每秒发送报文的统计。
-P Print PID 可选参数,表示在输出信息中打印 PID 的信息,用于单用户或单帐户模式下暂停 和重启程序。
-r <rate> Set replay speed to given rate (Mbps) 可选参数,指定发送的速率。目前-m/-r/-p 这 3 个参数的相互关系还需要确认。
-R Set replay speed to **as fast as possible** 可选参数,让网卡极限速度发数据包。 
-s <seed> Randomize src/dst IP addresses w/ given seed 可选参数,
-S <snaplen> Sniff interface(s) and set the snaplen length 可选参数,
-t <mtu> Override MTU (defaults to 1500) 可选参数,指定 MTU,标准的 10/100M 网卡的默认值是 1500。 
-T Truncate packets > MTU so they can be sent 可选参数,截去报文中 MTU 大于标准值的部分再发送出去,默认是不发送,skip 掉。目前还有疑问,为什么会产生 MTU 大于 1500 字节的包,在 BT 报文中,这种 包比较常见。 -u pad|trunc Pad/Truncate packets which are larger than the snaplen 可选参数, 后面的参数值二选一, snaplen 是指保留数据包的长度, 这里的 trunc 参数值和 MTU 没有任何关系,不要混淆。 -v Verbose: print packet decodes for each packet sent 可选参数,没发送一个报文都以 tcpdump 的风格打印出对应的信息。 -V Version 查看版本号。 -w <file> Write (primary) packets or data to file 可选参数,将主网卡发送的报文写入一个文件中,参数后紧跟文件名。

实战:

1.

tcpprep -a client -i 13030001.pcap -o server.cach

tcprewrite --enet-smac=00:90:0b:60:92:32,00:90:0b:60:92:2e --enet-dmac=00:90:0b:5a:71:cf,00:90:0b:5a:71:cf --endpoints=192.168.53.10:192.168.53.16 -i 13030001.pcap -o out.pcap -c server.cach

tcpreplay -i enp3s0f0 -p 1000 2 out.pcap 

tcpreplay -c server.cach -i enp3s0f0 -I enp3s0f1 13030001.pcap

tcprewrite -e 10.0.2.3:10.0.2.13 --enet-dmac=00:90:0b:61:f7:bd,00:90:0b:61:f7:be  --enet-smac=02:1a:c5:01:00:00,02:1a:c5:02:00:00 -c test.cache -i 13030001.pcap -o 6.pcap

注意:

tcpreplay只能使用再旁路环境下,再透明与反代模式下,由于机制的过滤,检测功能是不能生效的。

另外,再使用tcpreplay时,需要添加好目标ip与端口号地址,否则也不能生效。


[参考资料]
[1] tcpreplay官方网站:  http://tcpreplay.synfin.net/trac/
[2] tcpreplay官方网站:  http://tcpreplay.synfin.net/wiki/manual
[3] winpcap官方网站:  http://www.winpcap.org
[4]巧用Tcpreplay让攻击流量瞒天过海,
http://news.newhua.com/news1/safe_product/2007/1116/0711169442155I34A78I25B09B5752K.html

tpcreplay重写攻击流量:http://blog.chinaunix.net/uid-16865301-id-97411.html

tcpreplay使用:https://www.suibianlu.com/9348.html

posted on 2020-11-22 13:44  古风尘  阅读(2832)  评论(0编辑  收藏  举报

导航