Tcpdump抓包重放
开发工作中经常有这样的场景,和同事联调的时候,对方发了一个测试包过来,这边用tcpdump –Xlnsp0抓到包了,但是程序结果不正确,然后自己debug,修改,然后需要再测试,这时候再让同事发一个?如果不正确,这一来一回的比较慢,如果有个工具自动把tcpdump抓下来的内容再发出去,就ok了。
于是问题就是这样的,比如用tcpdump –Xlnps0抓到一个udp包,然后用工具把这个包重新发出去。
Tcpdump –Xlnps0抓到的包一般是这样的
10:57:00.095166 IP 10.133.1.147.59278 > 10.128.0.44.10888: UDP, length 162
0x0000: 4500 00be 0000 4000 3b11 286c 0a85 0193 E.....@.;.(l....
0x0010: 0a80 002c e78e 2a88 00aa 4e28 0a00 a200 ...,..*...N(....
0x0020: 0505 0113 c266 0200 0000 0000 0000 0000 .....f..........
0x0030: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x0040: 0a85 018b 0000 0000 0000 0000 0000 0000 ................
0x0050: 0000 0000 0000 0000 06ad 509b 009c bc49 ..........P....I
0x0060: 6e00 0000 0000 0000 0000 0000 0000 0000 n...............
0x0070: 0000 0000 0000 13c2 6602 0000 0000 0000 ........f.......
0x0080: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x0090: 0000 0000 0000 0000 0000 0000 0019 0258 ...............X
0x00a0: 00e4 e9fb 0100 0a40 6476 4737 7230 7a78 .......@dvG7r0zx
0x00b0: 6300 0000 001c 6b0d aa00 0000 0003 c.....k.......
简单分析一下,从第一行可以知道目的ip,端口,udp包长度,从第二行开始就是数据,ip包头(20字节),udp包头(8字节),udp数据报内容,需要得到这些数据,然后填写到程序中去,再让程序发出数据包。
于是用shell简单构造一个脚本,把tcpdump得到的内容存放到dump文件中,然后运行脚本,得到一个test.c程序,编译运行(也可以把这一步放到脚本中)。
脚本如下
#!/bin/bash
file=dump
addr=`head -1 ${file} | cut -d'>' -f2 | cut -d":" -f1 | tr -d ' ' `
length=`head -1 ${file} | grep -o "\<[0-9]\+\>$"`
ip=`echo ${addr} | awk -F. '{print $1"."$2"."$3"."$4}'`
port=`echo ${addr} | cut -d"." -f5`
line=`wc -l ${file} | cut -d' ' -f1`
tail -$((${line}-1)) ${file} | cut -b 18-56 | tr ' ' '\n' | sed "/^$/d" | awk '{print "0x"substr($1,1,2)", "}(length($1) >2){print "0x"substr($1,3,4)", "}' >tmp
line=`wc -l tmp | cut -d' ' -f1`
content=`tail -$((${line}-28)) tmp`
if [ -e test.c ]
then
rm test.c
fi
cat head >>test.c
echo -e "\tint bytes_to_send = ${length};" >>test.c
echo -e "\tchar ip[]= \"${ip}\";" >>test.c
echo -e "\tint port = ${port};" >>test.c
echo -e "\tchar dump[] = {${content}};" >>test.c
cat tail >>test.c
echo output test.c
其中用到的head和tail是一个普通发包程序的部分片段,通过分析tcpdump得到的内容来给这个程序填入适当的参数,从而生成一个新的发包程序。
Head:
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
int main(int argc, char **argv)
{
Tail:
struct sockaddr_in servaddr;
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons((uint16_t)port);
if( inet_pton(AF_INET, ip, &servaddr.sin_addr) <= 0)
{
perror("servaddr error");
exit(-1);
}
int sockfd;
if( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
perror("socket error");
exit(-1);
}
int num = 0;
if( (num = sendto(sockfd, (void *)dump, bytes_to_send, 0, (struct sockaddr *)&servaddr, sizeof(servaddr))) < 0)
{
perror("send error");
exit(-1);
}
printf("send %d bytes\n", num);
char buf[1024];
int len = sizeof(servaddr);
if ( (num = recvfrom (sockfd, (void *)buf, 1024, 0, (struct sockaddr *)&servaddr, &len)) < 0)
{
perror("recv error");
exit(-1);
}
printf("recv %d bytes\n", num);
return 0;
}
2011年11月21日 21:52
你发包用的程序得交互式由同事操作啊。。。。
2011年11月22日 00:19
为什么不用 tcpreplay ? 我们公司的开发人员都是用这个重放 tcpdump 捕的包的。
2011年11月22日 02:06
@依云: 不同部门的合作联调
2011年11月24日 01:08
咦,居然已经update好几天了,才发现。。。我过来酱油一下啦,表示看到过,哈哈
2011年11月24日 01:30
@vx13: 哎呀,重复造轮子了
2011年11月24日 01:31
@ivy: 哈哈,随意酱油啦
2011年11月24日 01:54
@Crane: 哇,这里跟的很迅速呀
2011年11月24日 01:56
@ivy: 我的地盘嘛
2011年11月24日 02:02
@Crane: 别处不是你的地盘?