linux抓包http

2012-02-28 15:03:54 mifan88 阅读数 12109

       最近因为研究http协议的需要,在linux下面进行实验并抓取数据包进行相关验证。我们都知道,wireshark是一款windows下面非常流行的抓包工具。那么linux下面我们该怎么实现这个抓包过程呢。我通过几个步骤对其进行说明:

1.实验目的。

       在linux平台下,用C语言自己伪造http数据包,并发送给百度服务器请求其服务器主页。使用抓包工具抓取源客户端发出的数据包,验证其是否和真实的http数据包格式相吻合。

2.实验过程

      1)linux上面下载安装tcpdump工具并抓取数据包

                 抓包命令为:tcpdump  -s 0 tcp port 80 -w   loghttp.cap  (存储抓包信息的文件名)             

      2)实现linux与windows的文件共享

                 主要使用samba实现。

      3)windows下面安装wireshark抓包工具

                 直接在官方网站就可以下载到

      4)在windows下面用wireshark工具打开linux上面tcpdump抓取的数据包

                 打开自己的往上邻居,在里面找到samba服务器 就可以找到共享的文件夹。

 3.现在我们就可以在wireshark图形界面工具中,对我们自己的http包进行查看分析了,如果不合格的话,可以再进行加工改造,直到和一般的http相差无几。 

2017-05-07 22:54:37 daiyudong2020 阅读数 19398


tcpdump安装略过。


1.监听eth0网卡HTTP 80端口的request和response
tcpdump -i eth0 -A -s 0 'tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)'


2.监听eth0网卡HTTP 80端口的request(不包括response),指定来源域名"example.com",也可以指定IP"192.168.1.107"
tcpdump -i eth0 -A -s 0 'src example.com and tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)'


3.监听本机发送至本机的HTTP 80端口的request和response
tcpdump -i lo -A -s 0 'tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)'


4.监听eth0网卡HTTP 80端口的request和response,结果另存为cap文件
tcpdump -i eth0 -A -s 0 'tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)' -w ./dump.cap


注1:如果报错"tcpdump: Bluetooth link-layer type filtering not implemented",是因为默认网卡不是ech0,需要用-i参数指定

注2:通过ifconfig命令查看网卡



End;


原文出自:http://blog.csdn.net/daiyudong2020/article/details/71375256



2018-09-20 18:51:35 Daisy_ljq 阅读数 2966

说到抓包分析,最简单的办法莫过于在客户端直接安装一个Wireshark或者Fiddler了,但是有时候由于客户端开发人员(可能是第三方)知识欠缺或者其它一些原因,无法顺利的在客户端进行抓包分析,这种情况下怎么办呢?

本文中,我们将给大家介绍在服务端进行抓包分析的方法,使用tcpdump抓包,配合Wireshark对HTTP请求进行分析,非常简单有效。

本文将会持续修正和更新,最新内容请参考我的 GITHUB 上的 程序猿成长计划 项目,欢迎 Star,更多精彩内容请 follow me

使用tcpdump在服务器抓包

在服务端进行抓包分析,使用tcpdump

tcpdump -tttt -s0 -X -vv tcp port 8080 -w captcha.cap

这里的参数是这样的

  • -tttt 输出最大程度可读的时间戳
  • -s0 指定每一个包捕获的长度,单位是byte,使用-s0可以捕获整个包的内容
  • -X 以hex和ASCII两种形式显示包的内容
  • -vv 显示更加多的包信息
  • tcp 指我们只捕获tcp流量
  • port 8080 指我们只捕获端口8080的流量
  • -w captcha.cap 指定捕获的流量结果输出到captcha.cap文件,便于分析使用
关于tcpdump更加高级的用法,可以参考 tcpdump简明教程

上述命令会保持运行,并将结果输出到 captcha.cap 文件中,在这个过程中,所有访问 8080 端口的 TCP 流量都会被捕获。当请求结束之后,我们可以使用 Ctrl+C 中断该命令的执行,这时候在当前目录下就可以看到生成了一个名为 captcha.cap 的文件。

使用Wireshark分析

接下来我们从服务器上下载这个captcha.cap文件到自己电脑上,使用 Wireshark 打开

最简单的下载方法当然是使用scp了

scp account@ip:/path/to/captcha.cap .

因为我们需要分析http包,直接打开看显然无法区分我们需要的内容,因此,可以在filter栏中添加过滤规则 http,这样就可以只展示http流量了

当请求比较多的时候,我们还是无法快速区分出哪个是指定客户端的访问请求,好在强大的filter可以组合使用

http and ip.src == 192.168.0.65    

上面这个filter将会过滤出所有来自客户端 192.168.0.65 的http流量。

找到我们需要分析的http请求了,那么怎么查看请求响应的内容呢?也很简单,只需要选中这个请求,右键 Follow - HTTP Stream

在新开的窗口中,我们就可以看到这个请求的所有内容了

总结

tcpdump和wireshark都是非常强大的网络分析工具,其使用用途不仅仅局限于http请求抓包,借助这两个工具,我们可以对所有的网络流量,网络协议进行分析。本文只是针对最常见的http请求抓包方法做了一个简单的讲解,实际上配合wireshark强大的filter规则,我们可以更加精准的对流量进行过滤,分析。

本文将会持续修正和更新,最新内容请参考我的 GITHUB 上的 程序猿成长计划 项目,欢迎 Star,更多精彩内容请 follow me

2018-05-30 11:33:59 DislodgeCocoon 阅读数 3269

本文转载自:https://blog.csdn.net/test201105/article/details/50618699

纯干货,重点不在于理论,更注重实战技能,尤其注重对抓包数据的分析。本文中的命令追求的是使用最简单,最普及的Linux系统自带工具包实现各种抓包分析,具有尽可能广泛的移植性和可用性。文中给出的命令均在Centos 6.3,tcpdump 4.1版本下测试可用;其他平台及环境,可能需要你自己微调部分命令及脚本才可以运行。文中多数命令及脚本都严重依赖于tcpdump命令输出文本数据格式,微调代码时应格外注意这一点。注意,本文中的命令适用于一般的基于tcp连接的,请求响应模型的网络服务,但不适用于使用pipeline模式的网络服务。如果想理解本文命令思路的话,需要你熟悉tcp/ip协议,网络osi模型,常见网络通讯协议,socket编程,linux脚本编程,awk脚本编程,数据挖掘思维方式等知识,不足者请自行脑补。理解本文的思路后,还可以在这些命令基础上有许多种灵活搭配和变种,请自行研究。不想费脑细胞的,运气好的话,很多命令都可以直接使用。尽管这里讲的是Linux抓包,但如果使用流行的wireshark在Windows上抓包后保存成tcpdump格式文件,然后上传到Linux系统上照样可以使用本文中的命令进行分析。

1.盲抓

        盲抓就是瞎抓,尤其在你接触到一台陌生机器,感觉有点抓瞎的时候,应当使用本节中的方法,其目的是找出这台机器上的重点网络服务是哪些ip和端口。如果你明确的知道要抓的包是哪个ip,哪个端口,可以直接跳至下一小节。

在目标机器上抓取任意tcp数据(需要root权限):

[plain] view plain copy
  1. tcpdump -i any -nn tcp > 123.pkg.head.txt  
分析目标机器上热点ip:port(按数据包数量统计):

[plain] view plain copy
  1. cat 123.pkg.head.txt | awk 'NF>5 && $2=="IP" {print $3,"[out]"; print substr($5,1,length($5)-1), "[in]"}' | sort | uniq -c | awk '{buf[NR]=$0;sum+=$1} END{for(i=1;i<=NR;i++) print buf[i], sum}' | awk '{printf("%s %s %s %.2f %%\n",$1, $2, $3, 100*$1/$4)}' | sort -nr -k 4 | less  
  2. 示例:  
  3. 2359 10.71.28.21.80 [in] 23.59 %  
  4. 2057 10.71.28.21.80 [out] 20.57 %  
  5. 331 10.71.28.20.8080 [in] 3.31 %  
  6. 253 10.71.28.20.8080 [out] 2.53 %  
  7. 190 218.92.220.60.39147 [out] 1.90 %  
  8. 154 218.92.220.60.39147 [in] 1.54 %  
  9. 106 218.92.220.56.60503 [out] 1.06 %  
分析目标机器上热点ip:port(按字节数,即带宽统计):

[plain] view plain copy
  1. cat 123.pkg.head.txt | awk 'BEGIN{header_len=0x36;inp=0;inb=0;inbb=0;outp=0;outb=0;outbb=0;start="";end=""} function getBodyLen(){if("length"==$(NF-1)) return $NF;t_c=split($7,a,/[()]/);if(3==t_c)return a[2];else return 0;} NF>5 && $2=="IP" {len=header_len + getBodyLen();print $3,"[out]", len; print substr($5,1,length($5)-1), "[in]", len; }' | sort | awk 'BEGIN{ipport="";dir="";bc=0} {if($1!=ipport || $2!=dir){if(bc>0)print ipport,dir,bc;ipport=$1;dir=$2;bc=$3;}else{bc+=$3;}} END{if(bc>0)print ipport,dir,bc;}' | awk '{buf[NR]=$0;sum+=$3} END{for(i=1;i<=NR;i++) print buf[i], sum}' | awk '{printf("%s %s %s %.2f %%\n",$1, $2, $3, 100*$3/$4)}' | sort -nr -k 4 | less  
  2. 示例:  
  3. 10.71.28.21.80 [out] 2559403 42.46 %  
  4. 218.92.220.60.39147 [in] 417277 6.92 %  
  5. 10.71.28.21.80 [in] 306507 5.08 %  
  6. 101.26.37.38.39906 [in] 271432 4.50 %  
  7. 122.225.28.115.48239 [in] 170901 2.84 %  
  8. 218.92.220.56.60503 [in] 151630 2.52 %  
  9. 218.92.220.62.59711 [in] 151322 2.51 %  
  10. 218.92.220.56.25777 [in] 138038 2.29 %  
  11. 60.210.23.239.7490 [in] 131700 2.18 %  
  12. 10.71.28.20.8080 [out] 121366 2.01 %  
分析数据流量概要信息(调整ipportRegex的值来控制统计口径):

[plain] view plain copy
  1. cat 123.pkg.head.txt | awk 'BEGIN{ipportRegex="10.71.28.21.80";header_len=0x36;inp=0;inb=0;inbb=0;outp=0;outb=0;outbb=0;start="";end=""} function getBodyLen(){if("length"==$(NF-1)) return $NF;t_c=split($7,a,/[()]/);if(3==t_c)return a[2];else return 0;} $3~ipportRegex{outp++;bl=getBodyLen();outb+=header_len+bl;outbb+=bl;if(""==start)start=$1;end=$1;} $5~ipportRegex{inp++;bl=getBodyLen();inb+=header_len+bl;inbb+=bl;if(""==start)start=$1;end=$1;} function timeSub(s,e){split(substr(s,1,8),sA1,":");s1=sA1[1]*3600+sA1[2]*60+sA1[3];us1=substr(s,10);split(substr(e,1,8),sA2,":");s2=sA2[1]*3600+sA2[2]*60+sA2[3];us2=substr(e,10);return s2*1000000+us2-s1*1000000-us1;} END{second=timeSub(start,end)/1000000;if(second<1) second=1; printf("total time: %.1f seconds\n", second);printf("[In]  pkg count: %s, pkg rate: %.2f pkg/s, bytes count: %s, bytes rate: %.2f KB/s, body bytes: %s, body bytes rate: %.2f KB/s, payload percent: %.1f%%\n", inp,inp/second,inb,inb/second/1024,inbb,inbb/second/1024,100*inbb/inb);printf("[Out] pkg count: %s, pkg rate: %.2f pkg/s, bytes count: %s, bytes rate: %.2f KB/s, body bytes: %s, body bytes rate: %.2f KB/s, payload percent: %.1f%%\n", outp,outp/second,outb,outb/second/1024,outbb,outbb/second/1024,100*outbb/outb);}'  
  2. cat 123.pkg.head.txt | awk 'BEGIN{ipportRegex="10.71.28.21.";header_len=0x36;inp=0;inb=0;inbb=0;outp=0;outb=0;outbb=0;start="";end=""} function getBodyLen(){if("length"==$(NF-1)) return $NF;t_c=split($7,a,/[()]/);if(3==t_c)return a[2];else return 0;} $3~ipportRegex{outp++;bl=getBodyLen();outb+=header_len+bl;outbb+=bl;if(""==start)start=$1;end=$1;} $5~ipportRegex{inp++;bl=getBodyLen();inb+=header_len+bl;inbb+=bl;if(""==start)start=$1;end=$1;} function timeSub(s,e){split(substr(s,1,8),sA1,":");s1=sA1[1]*3600+sA1[2]*60+sA1[3];us1=substr(s,10);split(substr(e,1,8),sA2,":");s2=sA2[1]*3600+sA2[2]*60+sA2[3];us2=substr(e,10);return s2*1000000+us2-s1*1000000-us1;} END{second=timeSub(start,end)/1000000;if(second<1) second=1; printf("total time: %.1f seconds\n", second);printf("[In]  pkg count: %s, pkg rate: %.2f pkg/s, bytes count: %s, bytes rate: %.2f KB/s, body bytes: %s, body bytes rate: %.2f KB/s, payload percent: %.1f%%\n", inp,inp/second,inb,inb/second/1024,inbb,inbb/second/1024,100*inbb/inb);printf("[Out] pkg count: %s, pkg rate: %.2f pkg/s, bytes count: %s, bytes rate: %.2f KB/s, body bytes: %s, body bytes rate: %.2f KB/s, payload percent: %.1f%%\n", outp,outp/second,outb,outb/second/1024,outbb,outbb/second/1024,100*outbb/outb);}'  
  3. cat 123.pkg.head.txt | awk 'BEGIN{ipportRegex="10.";header_len=0x36;inp=0;inb=0;inbb=0;outp=0;outb=0;outbb=0;start="";end=""} function getBodyLen(){if("length"==$(NF-1)) return $NF;t_c=split($7,a,/[()]/);if(3==t_c)return a[2];else return 0;} $3~ipportRegex{outp++;bl=getBodyLen();outb+=header_len+bl;outbb+=bl;if(""==start)start=$1;end=$1;} $5~ipportRegex{inp++;bl=getBodyLen();inb+=header_len+bl;inbb+=bl;if(""==start)start=$1;end=$1;} function timeSub(s,e){split(substr(s,1,8),sA1,":");s1=sA1[1]*3600+sA1[2]*60+sA1[3];us1=substr(s,10);split(substr(e,1,8),sA2,":");s2=sA2[1]*3600+sA2[2]*60+sA2[3];us2=substr(e,10);return s2*1000000+us2-s1*1000000-us1;} END{second=timeSub(start,end)/1000000;if(second<1) second=1; printf("total time: %.1f seconds\n", second);printf("[In]  pkg count: %s, pkg rate: %.2f pkg/s, bytes count: %s, bytes rate: %.2f KB/s, body bytes: %s, body bytes rate: %.2f KB/s, payload percent: %.1f%%\n", inp,inp/second,inb,inb/second/1024,inbb,inbb/second/1024,100*inbb/inb);printf("[Out] pkg count: %s, pkg rate: %.2f pkg/s, bytes count: %s, bytes rate: %.2f KB/s, body bytes: %s, body bytes rate: %.2f KB/s, payload percent: %.1f%%\n", outp,outp/second,outb,outb/second/1024,outbb,outbb/second/1024,100*outbb/outb);}'  
  4. 示例:  
  5. total time: 45.7 seconds  
  6. [In]  pkg count: 2359, pkg rate: 51.59 pkg/s, bytes count: 306507, bytes rate: 6.55 KB/s, body bytes: 179121, body bytes rate: 3.83 KB/s, payload percent: 58.4%  
  7. [Out] pkg count: 2057, pkg rate: 44.99 pkg/s, bytes count: 2559403, bytes rate: 54.66 KB/s, body bytes: 2448325, body bytes rate: 52.29 KB/s, payload percent: 95.7%  

2.抓取源数据

        明确了要抓取的目标服务的ip和端口后,就要开始正式抓包了,这些抓包数据是后续分析工作的基础。当然,你可能在抓包之前还要做一些其他工作,以保证抓包时的工作场景就是你想要分析的目标场景。抓包时你需要root权限。

抓取不含包体的包:

[plain] view plain copy
  1. tcpdump -nn port 80 > 123.pkg.txt  
抓取含有包体的包并进行初步解包:

[plain] view plain copy
  1. tcpdump port 80 -w 123.pkg -s 120  
  2. tcpdump port 80 -w 123.pkg -s 0  
  3. tcpdump -r 123.pkg -XXnn > 123.pkg.txt  
  4. 示例:  
  5. 11:12:01.894222 IP 10.64.12.14.59493 > 10.70.60.56.1521: Flags [P.], seq 3862499245:3862499262, ack 627056474, win 501, options [nop,nop,TS val 2916000715 ecr 736856730], length 17  
  6.         0x0000:  0000 0c07 ace9 0022 195d 2445 0800 4500  .......".]$E..E.  
  7.         0x0010:  0045 cb3b 4000 4006 12ac 0a40 0c0e 0a46  .E.;@.@....@...F  
  8.         0x0020:  3c38 e865 05f1 e639 0fad 2560 1f5a 8018  <8.e...9..%`.Z..  
  9.         0x0030:  01f5 5d03 0000 0101 080a adce a3cb 2beb  ..]...........+.  
  10.         0x0040:  8a9a 0011 0000 0600 0000 0000 0305 0001  ................  
  11.         0x0050:  0301 0a                                  ...  
  12. 11:12:01.894226 IP 10.64.12.14.59514 > 10.70.60.56.1521: Flags [P.], seq 3903163064:3903163580, ack 4171729186, win 501, options [nop,nop,TS val 2916000715 ecr 736856729], length 516  
  13.         0x0000:  0000 0c07 ace9 0022 195d 2445 0800 4500  .......".]$E..E.  
  14.         0x0010:  0238 f2e9 4000 4006 e90a 0a40 0c0e 0a46  .8..@.@....@...F  
  15.         0x0020:  3c38 e87a 05f1 e8a5 8ab8 f8a7 8922 8018  <8.z........."..  
  16.         0x0030:  01f5 5ef6 0000 0101 080a adce a3cb 2beb  ..^...........+.  
  17.         0x0040:  8a99 0204 0000 0600 0000 0000 1169 0001  .............i..  


3.过滤

       有时候,需要分析的问题是包含在抓取目标服务的全部数据包中的一小部分,这个时候就要对包数据进行过滤。当然也可以在上一节进行抓取时直接进行过滤,但这里主要满足事后的过滤需求。

过滤掉含有包体的数据文件,只保留数据包头:

[plain] view plain copy
  1. cat 123.pkg.txt | awk 'substr($1,1,3)!="0x0"' > 123.pkg.head.txt  
  2. 示例:  
  3. 11:12:01.894222 IP 10.64.12.14.59493 > 10.70.60.56.1521: Flags [P.], seq 3862499245:3862499262, ack 627056474, win 501, options [nop,nop,TS val 2916000715 ecr 736856730], length 17  
  4. 11:12:01.894226 IP 10.64.12.14.59514 > 10.70.60.56.1521: Flags [P.], seq 3903163064:3903163580, ack 4171729186, win 501, options [nop,nop,TS val 2916000715 ecr 736856729], length 516  
  5. 11:12:01.894228 IP 10.64.12.14.59518 > 10.70.60.56.1521: Flags [P.], seq 3897659932:3897660175, ack 3171500152, win 501, options [nop,nop,TS val 2916000715 ecr 736856729], length 243  
  6. 11:12:01.894231 IP 10.64.12.14.59512 > 10.70.60.56.1521: Flags [P.], seq 3898476274:3898476788, ack 1748466768, win 501, options [nop,nop,TS val 2916000715 ecr 736856730], length 514  
按时间段过滤含有包体的数据文件(调整start和end的值以改变时间范围):

[plain] view plain copy
  1. cat 123.pkg.txt | awk 'BEGIN {start="11:13:49.0";end="11:13:49.9";flag=0} {if(substr($1,1,3)=="0x0"){if(1==flag){print $0}}else{cur=substr($1,1,length(start));if(cur>=start && cur<=end){print $0;flag=1}else{flag=0}}}' > new123.pkg.txt  
按ip端口过滤含有包体的数据文件(调整ip和port的值):

[plain] view plain copy
  1. cat new123.pkg.txt | awk 'BEGIN {ip="192.168.122.180";port="54365";flag=0} {if(substr($1,1,3)=="0x0"){if(1==flag){print $0}}else if($0~ip"."port){print $0;flag=1;}else{flag=0;}}' > newnew123.pkg.txt  
按文本关键字过滤含有包体的数据文件(调整keyword的值):

[plain] view plain copy
  1. cat newnew123.pkg.txt | awk 'BEGIN{keyword="id_10bc3c9";buf="";found=0} {if(substr($1,1,2)=="0x"){if($0~keyword) found=1;buf=buf"\n"$0}else{if(1==found){print buf;found=0;}if($0~keyword) found=1;buf=$0}} END{if(1==found) print buf}' > tmp.pkg.txt  
按二进制串关键字从二进制数据包中过滤含有包体的数据文件(性能稍低,对于大文件耐心等待;例子中是过滤包含"test_dava_11968@163.com"字符串的数据包):

[plain] view plain copy
  1. cat newnew123.pkg.txt | awk 'BEGIN{keyword="746573745f646176615f3131393638403136332e636f6d";bin="";buf=""} {if(substr($1,1,2)=="0x"){for(i=2;i<NF;i++) bin=bin""$i;buf=buf"\n"$0}else{if(length(bin)>0&&bin~keyword) print buf;buf=$0;bin=""}} END{if(length(bin)>0&&bin~keyword) print buf}' > tmp2.pkg.txt  


4.分类

       通过分类,将抓包文件中混杂在一起的多个客户端的数据包拆分成各自单独的文件,以利于人工查看以及后续分析。新生成的文件放在当前目录下的子目录中,例如10.64.12.14.443_detail。

按client端ip端口将混杂在一起的含有包体的包拆分的单独文件:

[plain] view plain copy
  1. cat 123.pkg.txt | awk 'BEGIN{server="10.70.60.56.1521";buf="";client="";dir=server"_detail";system("mkdir "dir" 2>/dev/null")} {if(substr($1,1,2)=="0x"){buf=buf"\n"$0}else{if(length(client)>0) print buf>>dir"/"client".txt";if($3==server){client=substr($5,1,length($5)-1);}else if($5~server){client=$3}else{client=""} buf=$0}}'  
按client端ip端口将混杂在一起的含有包体的包拆分的单独文件(超过1000个client后因受同时打开文件数限制awk性能非常低,可增加dd命令的bs缓冲区大小,并使用limit参数进行限制):
[plain] view plain copy
  1. dd if=123.pkg.txt bs=100M 2>/dev/null | awk 'BEGIN{server="10.70.60.56.1521";limit=1000;buf="";client="";count=0;dir=server"_detail";system("mkdir "dir" 2>/dev/null")} {if(substr($1,1,2)=="0x"){if(length(client)>0) buf=buf"\n"$0}else{if(length(client)>0) print buf>>dir"/"client".txt";if($3==server){client=substr($5,1,length($5)-1)}else if($5~server){client=$3}else{client=""}if(length(client)>0){if("ok"==all_clients[client]){buf=$0}else if(count<limit){count++;all_clients[client]="ok";buf=$0}else{client=""}}}}'  


5.交互分析

       前面的分析处理仅限于数据包本身的ip和port,而本节的交互分析则将数据包归类到一个个具体的tcp连接之中,提取有关的交互“成本”数据,并尝试分析数据包在请求响应模型中的交互语义。本节中的命令需要系列awk脚本支持,为不影响理解本节主要内容,相关脚本源码附录在文章末尾供参考,其中包含主脚本parseTcp.awk,以及若干插件脚本:fixLenParser.awk,lineParser.awk,oracleSqlParser.awk,httpParser.awk。

分析单个不含包体的数据文件的交互过程:

[plain] view plain copy
  1. cat 123.pkg.txt | /data/speng/tcpdump/parseTcp.awk 61.135.169.125.80 > interaction.txt  
分析单个不含包体的数据文件中只与某特定客户端有关的交互过程:

[plain] view plain copy
  1. cat 123.pkg.txt | /data/speng/tcpdump/parseTcp.awk 61.135.169.125.80 1 172.20.154.45.3752 > interaction.txt  
  2. 示例:  
  3. 14:00:53.123517 client 172.20.154.45.3752_2455096098 connect take(us): 3291 slient_before(us): 72266270 result: ok  
  4. 14:00:53.132710 client 172.20.154.45.3752_2455096098 round-trip 1 slient_before(us): 5902 total take(us): 5927 req_time(us): 76 req_bytes: 1635 server_process(us): 5402 response_time(us): 449 response_bytes: 6587  
  5. 14:00:53.263446 client 172.20.154.45.3752_2455096098 round-trip 2 slient_before(us): 124809 total take(us): 17767 req_time(us): 88 req_bytes: 1620 server_process(us): 17679 response_time(us): 0 response_bytes: 946  
  6. 14:00:53.472286 client 172.20.154.45.3752_2455096098 round-trip 3 slient_before(us): 191073 total take(us): 9319 req_time(us): 53 req_bytes: 1620 server_process(us): 8517 response_time(us): 749 response_bytes: 10361  
  7. 14:00:54.587117 client 172.20.154.45.3752_2455096098 round-trip 4 slient_before(us): 1105512 total take(us): 13233 req_time(us): 92 req_bytes: 1618 server_process(us): 13113 response_time(us): 28 response_bytes: 2777  
  8. 14:01:14.598513 client 172.20.154.45.3752_2455096098 close take(us): 589 slient_before(us): 19998163 close_bytes: 0 direction: server->client result: full_close  
分析多个分类后含有包体的数据文件的交互过程(cd进入上一节分类后所生成的目录下执行命令):
[plain] view plain copy
  1. ls | xargs -n 10 awk 'BEGIN{f=""} {if(FILENAME!=f){print "newfile",FILENAME;f=FILENAME}if(substr($1,1,2)!="0x") print $0}' | ../parseTcp.awk 10.70.60.56.1521 > ../interaction.txt  
分析多个分类后含有包体的数据文件的交互过程(cd进入分类后文件所在目录下执行命令。支持识别包体中的特征数据,并打印出来便于后续业务分析。可编写类似oracleSqlParser.awk或httpParser.awk插件脚本进行新协议或业务扩展。源码附录在文章末尾):

[plain] view plain copy
  1. ls | xargs -n 10 awk -f ../oracleSqlParser.awk --source 'function getLen(){if("length"==$(NF-1)) return $NF;t_c=split($7,a,/[()]/);if(3==t_c) return a[2];else return 0;} BEGIN{f="";h="";b=0;} {if(FILENAME!=f){if(1==b)parserEnd();if(""!=h)print h;print "newfile",FILENAME;f=FILENAME;h="";b=0;}if(substr($1,1,2)=="0x"){if(1==b)parserWork();}else{if(1==b)parserEnd();b=0;if(""!=h)print h;h=$0;bl=getLen();if(bl>0){parserInit(bl);b=1;}}} END{if(1==b)parserEnd();if(""!=h)print h;}' | ../parseTcp.awk 10.70.60.56.1521 > ../interaction.txt  
  2. ls | xargs -n 10 awk -f ../httpParser.awk --source 'function getLen(){if("length"==$(NF-1)) return $NF;t_c=split($7,a,/[()]/);if(3==t_c) return a[2];else return 0;} BEGIN{f="";h="";b=0;} {if(FILENAME!=f){if(1==b)parserEnd();if(""!=h)print h;print "newfile",FILENAME;f=FILENAME;h="";b=0;}if(substr($1,1,2)=="0x"){if(1==b)parserWork();}else{if(1==b)parserEnd();b=0;if(""!=h)print h;h=$0;bl=getLen();if(bl>0){parserInit(bl);b=1;}}} END{if(1==b)parserEnd();if(""!=h)print h;}' | ../parseTcp.awk 10.70.66.120.80 > ../interaction.txt  
  3. 示例:  
  4. sql:  
  5. 11:12:29.422380 client 10.64.12.14.59573_3961647293 connect take(us): 567 slient_before(us): 0 result: ok  
  6. 11:12:29.423124 client 10.64.12.14.59573_3961647293 round-trip 1 slient_before(us): 177 total take(us): 54042 req_time(us): 0 req_bytes: 211 server_process(us): 54042 response_time(us): 0 response_bytes: 8  
  7. 11:12:29.478165 client 10.64.12.14.59573_3961647293 round-trip 2 slient_before(us): 999 total take(us): 2021 req_time(us): 1409 req_bytes: 363 server_process(us): 612 response_time(us): 0 response_bytes: 127  
  8. 11:12:29.480257 client 10.64.12.14.59573_3961647293 round-trip 3 slient_before(us): 71 total take(us): 1420 req_time(us): 0 req_bytes: 33 server_process(us): 1420 response_time(us): 0 response_bytes: 188  
  9. 11:12:29.481825 client 10.64.12.14.59573_3961647293 round-trip 4 slient_before(us): 148 total take(us): 1036 req_time(us): 0 req_bytes: 779 server_process(us): 1036 response_time(us): 0 response_bytes: 834  
  10. 11:12:29.483414 client 10.64.12.14.59573_3961647293 round-trip 5 slient_before(us): 553 total take(us): 3983 req_time(us): 810 req_bytes: 184 server_process(us): 3173 response_time(us): 0 response_bytes: 73  
  11. 11:12:29.487836 client 10.64.12.14.59573_3961647293 round-trip 6 slient_before(us): 439 total take(us): 4891 req_time(us): 0 req_bytes: 574 server_process(us): 4891 response_time(us): 0 response_bytes: 1180  
  12. 11:12:29.492988 client 10.64.12.14.59573_3961647293 round-trip 7 slient_before(us): 261 total take(us): 3220 req_time(us): 0 req_bytes: 505 server_process(us): 3220 response_time(us): 0 response_bytes: 358  
  13. 11:12:29.496568 client 10.64.12.14.59573_3961647293 round-trip 8 slient_before(us): 360 total take(us): 2276 req_time(us): 0 req_bytes: 245 server_process(us): 2276 response_time(us): 0 response_bytes: 393 req_appflag: select.usrid,mailadd,mailflg,mobile,verifyflg,user_seq_id,is_oauth_type,lastlogin,pwd_strict.from.tab_users.where.mailadd.=:1--con_id_52d2c4  
  14. 11:12:29.499283 client 10.64.12.14.59573_3961647293 round-trip 9 slient_before(us): 439 total take(us): 704 req_time(us): 0 req_bytes: 17 server_process(us): 704 response_time(us): 0 response_bytes: 208  
  15. 11:12:29.500267 client 10.64.12.14.59573_3961647293 round-trip 10 slient_before(us): 280 total take(us): 766 req_time(us): 0 req_bytes: 245 server_process(us): 766 response_time(us): 0 response_bytes: 393 req_appflag: select.usrid,mailadd,mailflg,mobile,verifyflg,user_seq_id,is_oauth_type,lastlogin,pwd_strict.from.tab_users.where.mailadd.=:1--con_id_52d2c4  
  16. 11:12:29.501945 client 10.64.12.14.59573_3961647293 round-trip 11 slient_before(us): 912 total take(us): 681 req_time(us): 0 req_bytes: 17 server_process(us): 681 response_time(us): 0 response_bytes: 208  
  17. 11:12:29.503286 client 10.64.12.14.59573_3961647293 round-trip 12 slient_before(us): 660 total take(us): 4956 req_time(us): 0 req_bytes: 513 server_process(us): 4956 response_time(us): 0 response_bytes: 64 req_appflag: update.tab_users.tu.set.tu.lastlogin_third=tu.lastlogin,tu.lastlogin=to_date(:1,'yyyy-mm-dd.hh24:mi:ss'),tu.uct_time=to_date(:2,'yyyy-mm-dd.hh24:mi:ss'),tu.uct=:3,tu.auto_login_flag=:4,login_ip=:5.where.mailadd.=:6--con_id_52d2c4  
  18. 11:12:29.510362 client 10.64.12.14.59573_3961647293 round-trip 13 slient_before(us): 2120 total take(us): 3591 req_time(us): 0 req_bytes: 515 server_process(us): 3591 response_time(us): 0 response_bytes: 63 req_appflag: update.tab_users.tu.set.tu.lastlogin_third=tu.lastlogin,tu.lastlogin=to_date(:1,'yyyy-mm-dd.hh24:mi:ss'),tu.uct_time=to_date(:2,'yyyy-mm-dd.hh24:mi:ss'),tu.uct=:3,tu.auto_login_flag=:4,login_ip=:5.where.mailadd.=:6--con_id_52d2c4  
  19. 11:12:29.515085 client 10.64.12.14.59573_3961647293 round-trip 14 slient_before(us): 1132 total take(us): 3660 req_time(us): 0 req_bytes: 513 server_process(us): 3660 response_time(us): 0 response_bytes: 63 req_appflag: update.tab_users.tu.set.tu.lastlogin_third=tu.lastlogin,tu.lastlogin=to_date(:1,'yyyy-mm-dd.hh24:mi:ss'),tu.uct_time=to_date(:2,'yyyy-mm-dd.hh24:mi:ss'),tu.uct=:3,tu.auto_login_flag=:4,login_ip=:5.where.mailadd.=:6--con_id_52d2c4  
  20. 11:12:29.518969 client 10.64.12.14.59573_3961647293 round-trip 15 slient_before(us): 224 total take(us): 724 req_time(us): 0 req_bytes: 245 server_process(us): 724 response_time(us): 0 response_bytes: 392 req_appflag: select.usrid,mailadd,mailflg,mobile,verifyflg,user_seq_id,is_oauth_type,lastlogin,pwd_strict.from.tab_users.where.mailadd.=:1--con_id_52d2c4  
  21. 11:12:29.519737 client 10.64.12.14.59573_3961647293 round-trip 16 slient_before(us): 44 total take(us): 664 req_time(us): 0 req_bytes: 17 server_process(us): 664 response_time(us): 0 response_bytes: 208  
  22. 11:12:29.522030 client 10.64.12.14.59573_3961647293 round-trip 17 slient_before(us): 1629 total take(us): 4037 req_time(us): 0 req_bytes: 513 server_process(us): 4037 response_time(us): 0 response_bytes: 63 req_appflag: update.tab_users.tu.set.tu.lastlogin_third=tu.lastlogin,tu.lastlogin=to_date(:1,'yyyy-mm-dd.hh24:mi:ss'),tu.uct_time=to_date(:2,'yyyy-mm-dd.hh24:mi:ss'),tu.uct=:3,tu.auto_login_flag=:4,login_ip=:5.where.mailadd.=:6--con_id_52d2c4  
  23. 11:12:29.526610 client 10.64.12.14.59573_3961647293 round-trip 18 slient_before(us): 543 total take(us): 709 req_time(us): 0 req_bytes: 245 server_process(us): 709 response_time(us): 0 response_bytes: 392 req_appflag: select.usrid,mailadd,mailflg,mobile,verifyflg,user_seq_id,is_oauth_type,lastlogin,pwd_strict.from.tab_users.where.mailadd.=:1--con_id_52d2c4  
  24. 11:12:29.527617 client 10.64.12.14.59573_3961647293 round-trip 19 slient_before(us): 298 total take(us): 1490 req_time(us): 0 req_bytes: 17 server_process(us): 1490 response_time(us): 0 response_bytes: 208   
  25.   
  26. http:  
  27. 14:00:53.123517 client 172.20.154.45.3752_2455096098 connect take(us): 3291 slient_before(us): 72266270 result: ok  
  28. 14:00:53.132710 client 172.20.154.45.3752_2455096098 round-trip 1 slient_before(us): 5902 total take(us): 5927 req_time(us): 76 req_bytes: 1635 server_process(us): 5402 response_time(us): 449 response_bytes: 6587 req_appflag: GET./static/api/js/share.js?v=89860593.js?cdnversion=403517 response_appflag: 200.OK  
  29. 14:00:53.263446 client 172.20.154.45.3752_2455096098 round-trip 2 slient_before(us): 124809 total take(us): 17767 req_time(us): 88 req_bytes: 1620 server_process(us): 17679 response_time(us): 0 response_bytes: 946 req_appflag: GET./static/js/shell_v2.js?cdnversion=403519 response_appflag: 200.OK  
  30. 14:00:53.472286 client 172.20.154.45.3752_2455096098 round-trip 3 slient_before(us): 191073 total take(us): 9319 req_time(us): 53 req_bytes: 1620 server_process(us): 8517 response_time(us): 749 response_bytes: 10361 req_appflag: GET./static/js/bds_s_v2.js?cdnversion=403519 response_appflag: 200.OK  
  31. 14:00:54.587117 client 172.20.154.45.3752_2455096098 round-trip 4 slient_before(us): 1105512 total take(us): 13233 req_time(us): 92 req_bytes: 1618 server_process(us): 13113 response_time(us): 28 response_bytes: 2777 req_appflag: GET./static/js/logger.js?cdnversion=403519 response_appflag: 200.OK  
  32. 14:01:14.598513 client 172.20.154.45.3752_2455096098 close take(us): 589 slient_before(us): 19998163 close_bytes: 0 direction: server->client result: full_close  
  33.   
  34. https:  
  35. 16:53:29.658744 client 10.64.12.16.32769_169947140 connect take(us): 89 slient_before(us): 0 result: ok  
  36. 16:53:29.658857 client 10.64.12.16.32769_169947140 round-trip 1 slient_before(us): 24 total take(us): 6865 req_time(us): 0 req_bytes: 117 server_process(us): 1535 response_time(us): 5330 response_bytes: 5140  
  37. 16:53:29.670379 client 10.64.12.16.32769_169947140 round-trip 2 slient_before(us): 4657 total take(us): 6071 req_time(us): 0 req_bytes: 198 server_process(us): 6071 response_time(us): 0 response_bytes: 59  
  38. 16:53:29.676530 client 10.64.12.16.32769_169947140 round-trip 3 slient_before(us): 80 total take(us): 983303 req_time(us): 0 req_bytes: 133 server_process(us): 983303 response_time(us): 0 response_bytes: 842  
  39. 16:53:30.659883 client 10.64.12.16.32769_169947140 close take(us): 4412 slient_before(us): 50 close_bytes: 37 direction: server->client result: full_close  
  40. 16:54:39.540752 client 10.64.12.16.32769_239829149 connect take(us): 91 slient_before(us): 68876457 result: ok  
  41. 16:54:39.540866 client 10.64.12.16.32769_239829149 round-trip 1 slient_before(us): 23 total take(us): 7459 req_time(us): 0 req_bytes: 117 server_process(us): 2127 response_time(us): 5332 response_bytes: 5140  
  42. 16:54:39.552971 client 10.64.12.16.32769_239829149 round-trip 2 slient_before(us): 4646 total take(us): 5452 req_time(us): 0 req_bytes: 198 server_process(us): 5452 response_time(us): 0 response_bytes: 59  
  43. 16:54:39.558487 client 10.64.12.16.32769_239829149 round-trip 3 slient_before(us): 64 total take(us): 965470 req_time(us): 0 req_bytes: 133 server_process(us): 965470 response_time(us): 0 response_bytes: 842  
  44. 16:54:40.524004 client 10.64.12.16.32769_239829149 close take(us): 115 slient_before(us): 47 close_bytes: 37 direction: server->client result: full_close  


6.统计分析

        统计分析用于掌握一批数据包反映的整体交互规律和指标数据。配合使用上一节交互分析中获得的业务关键字过滤,还可以分析具有某些特定特征的交互指标数据。

分析多行模式输出的交互过程的请求响应对的平均响应时间(含请求响应的网络传输时间,但不含socket建立阶段):

[plain] view plain copy
  1. cat interaction.txt | grep round-trip | awk '{sum+=($10/1000000)} END {print "Lines = "NR", Sum = "sum"(seconds), Average = "sum/NR"(seconds)"}'   
  2. 示例:  
  3. Lines = 678796, Sum = 4234.81(seconds), Average = 0.00623871(seconds)  
分析多行模式输出的交互过程的请求响应对的服务器平均处理时间:

[plain] view plain copy
  1. cat interaction.txt | grep round-trip | awk '{sum+=($16/1000000)} END {print "Lines = "NR", Sum = "sum"(seconds), Average = "sum/NR"(seconds)"}'  
  2. 示例:  
  3. Lines = 678796, Sum = 1612.32(seconds), Average = 0.00237526(seconds)  
分析多行模式输出的交互过程的请求响应对的平均请求大小:

[plain] view plain copy
  1. cat interaction.txt | grep round-trip | awk '{sum+=$14} END {print "Lines = "NR", Sum = "sum"(bytes), Average = "sum/NR"(bytes)"}'  
分析多行模式输出的交互过程的请求响应对的平均响应大小:

[plain] view plain copy
  1. cat interaction.txt | grep round-trip | awk '{sum+=$20} END {print "Lines = "NR", Sum = "sum"(bytes), Average = "sum/NR"(bytes)"}'  
分析某多行模式输出的https短连接交互过程的ssl握手阶段的平均处理时间:

[plain] view plain copy
  1. cat interaction.txt | grep round-trip | awk '$5==1 {start=$1;r1_time=$10} $5==2 {slient=$7;r2_time=$10;print start, r1_time+slient+r2_time}' | awk '{sum+=($2/1000000)} END {print "Lines = "NR", Sum = "sum"(seconds), Average = "sum/NR"(seconds)"}'  
  2. 示例:  
  3. Lines = 284861, Sum = 12216.7(seconds), Average = 0.0428866(seconds)  
分析某多行模式输出的https短连接交互过程的ssl握手阶段的tps及每秒平均处理时间(可导入excel作图):

[plain] view plain copy
  1. cat interaction.txt | grep round-trip | awk '$5==1 {start=$1;r1_time=$10} $5==2 {slient=$7;r2_time=$10;print start, r1_time+slient+r2_time}' | sort | awk '{print $2,$1}' | awk -F '.' '{print $1}' | awk 'BEGIN{sum=0;count=0;time=""} {if($2!=time){if(count>0) print time,count,sum/count/1000000;sum=$1;count=1;time=$2}else{sum+=$1;count++}} END{if(count>0) print time,count,sum/count/1000000}'  
上例做图如下:


分析某多行模式输出的https短连接交互过程的socket建立完成至服务器accept此连接经历的平均等待时间(可导入excel作图):

[plain] view plain copy
  1. cat interaction.txt | grep "round-trip 1 " | awk '{print $1,$7}' | sort | awk '{print $2,$1}' | awk -F '.' '{print $1}' | awk 'BEGIN{sum=0;count=0;time=""} {if($2!=time){if(count>0) printf("%s %s %.6f\n", time,count,sum/count/1000000);sum=$1;count=1;time=$2}else{sum+=$1;count++}} END{if(count>0) printf("%s %s %.6f\n", time,count,sum/count/1000000)}'  
分析某多行模式输出含有包体特征数据的oracle长连接交互过程中select语句及update语句的平均响应时间:

[plain] view plain copy
  1. cat interaction.txt | grep select | awk '{sum+=($10/1000000)} END {print "Lines = "NR", Sum = "sum"(seconds), Average = "sum/NR"(seconds)"}'  
  2. cat interaction.txt | grep update | awk '{sum+=($10/1000000)} END {print "Lines = "NR", Sum = "sum"(seconds), Average = "sum/NR"(seconds)"}'  



附录:

parseTcp.awk源码(文件需有可执行权限):

[plain] view plain copy
  1. #!/bin/awk -f  
  2.   
  3. BEGIN \  
  4. {  
  5.   if(ARGC<2)  
  6.   {  
  7.     printf("Usage:\n");  
  8.     printf("      ./parseTcp.awk <server ip port> [<print in multi line, 0 or 1, default to 1> [client ip port]]\n");  
  9.     printf("Example:\n");  
  10.     printf("      cat ./pkg.txt | ./parseTcp.awk 10.64.12.14.443 1 10.64.12.16.60990\n");  
  11.     exit;  
  12.   }  
  13.   server=ARGV[1];  
  14.   multi_line=1;  
  15.   if(ARGC>2)  
  16.     multi_line=ARGV[2];  
  17.   default_client="";  
  18.   if(ARGC>3)  
  19.      default_client=ARGV[3];  
  20.   max_close_wait=240000000;  
  21.   max_connect_wait=max_close_wait;  
  22.   isn=0;  
  23.   need_newline=0;  
  24.   ARGC=1;  # don't delete this line!  
  25. }  
  26.   
  27. function checkflag(flag)  
  28. {  
  29.   pkgFlag=$6;  
  30.   if("Flags"==pkgFlag)  
  31.     pkgFlag=$7;  
  32.   if(pkgFlag~flag)  
  33.     return 1;  
  34.   else  
  35.     return 0  
  36. }  
  37.   
  38. function getBodyLen()  
  39. {  
  40.   if("length"==$(NF-1)) return $NF;  
  41.   count=split($7,a,/[()]/);  
  42.   if(3==count)  
  43.     return a[2];  
  44.   else  
  45.     return 0;  
  46. }  
  47.   
  48. function getTcpISN()  
  49. {  
  50.   if("seq"==$8)  
  51.     return substr($9,1,length($9)-1);  
  52.   count=split($7,a,":");  
  53.   if(2==count)  
  54.     return a[1];  
  55.   else  
  56.     return 0;  
  57. }  
  58.   
  59. function timeSub(start,end)  
  60. {  
  61.   split(substr(start,1,8),sA1,":");  
  62.   s1=sA1[1]*3600+sA1[2]*60+sA1[3];  
  63.   us1=substr(start,10);  
  64.   split(substr(end,1,8),sA2,":");  
  65.   s2=sA2[1]*3600+sA2[2]*60+sA2[3];  
  66.   us2=substr(end,10);  
  67.   return s2*1000000+us2-s1*1000000-us1;  
  68. }  
  69.   
  70. function printConnectInfo()  
  71. {  
  72.   if(1==connect_reset)  
  73.     connect_result="reset_by_server";  
  74.   else if(1==connect_timeout)  
  75.     connect_result="timeout";  
  76.   else  
  77.     connect_result="ok";  
  78.   printf("%s client %s_%s connect take(us): %s slient_before(us): %s result: %s",connect_start, client, isn, timeSub(connect_start,$1), slient_time, connect_result);  
  79.   need_newline=1;  
  80.   if("ok"!=connect_result)  
  81.   {  
  82.     printf("\n");  
  83.     need_newline=0;  
  84.   }  
  85. }  
  86.   
  87. function printRoundInfo()  
  88. {  
  89.   if(1==multi_line){printf("\n")}else{printf(" || ")}  
  90.   printf("%s client %s_%s round-trip %d slient_before(us): %s total take(us): %s req_time(us): %s req_bytes: %s server_process(us): %s response_time(us): %s response_bytes: %s",req_start, client, isn, round, slient_time, timeSub(req_start,response_end), timeSub(req_start,req_end), req_len, server_process, timeSub(response_start,response_end), response_len);  
  91.   if(""!=req_appflag)  
  92.     printf(" req_appflag: %s",req_appflag);  
  93.   if(""!=response_appflag)  
  94.     printf(" response_appflag: %s",response_appflag);  
  95.   need_newline=1;  
  96. }  
  97.   
  98. function printCloseInfo()  
  99. {  
  100.   if(1==server_close)  
  101.     direction="server->client";  
  102.   else  
  103.     direction="client->server";  
  104.   if(1==close_timeout)  
  105.     close_result="close_timeout";  
  106.   else if(2==client_close || 2==server_close)  
  107.     close_result="full_close";  
  108.   else  
  109.     close_result="half_close";  
  110.   if(1==multi_line){printf("\n")}else{printf(" || ")}  
  111.   printf("%s client %s_%s close take(us): %s slient_before(us): %s close_bytes: %s direction: %s result: %s\n", close_start, client, isn, timeSub(close_start,close_end), close_slient_time, close_bytes, direction, close_result);  
  112.   need_newline=0;  
  113. }  
  114.   
  115. function printResetInfo()  
  116. {  
  117.   if(1==multi_line){printf("\n")}else{printf(" || ")};  
  118.   if($3==server)  
  119.     resetPeer="server";  
  120.   else  
  121.     resetPeer="client";  
  122.   printf("%s client %s_%s reset connect by %s\n", $1, client, isn, resetPeer);  
  123.   need_newline=0;  
  124. }  
  125.   
  126. function onNewConnect()  
  127. {  
  128.   client=$3;  
  129.   isn=getTcpISN();  
  130.   slient_time=timeSub(slient_start,$1);  
  131.   connect_start=$1;  
  132.   connect_timeout=0;  
  133.   connect_reset=0;  
  134.   prepareClose();  
  135. }  
  136.   
  137. function onFirstRoundTrip()  
  138. {  
  139.   req_start="";  
  140.   round=0;  
  141. }  
  142.   
  143. function onNewRequest()  
  144. {  
  145.   req_start=$1;  
  146.   req_end=$1;  
  147.   req_len=bodyLen;  
  148.   round++;  
  149.   slient_time=timeSub(slient_start,$1);  
  150.   process_start=$1;  
  151.   req_appflag=last_appflag;  
  152. }  
  153.   
  154. function mergeRequest()  
  155. {  
  156.   req_end=$1;  
  157.   req_len+=bodyLen;  
  158.   process_start=$1;  
  159.   if(""!=last_appflag)  
  160.     req_appflag=last_appflag;  
  161. }  
  162.   
  163. function onNewResponse()  
  164. {  
  165.   response_start=$1;  
  166.   response_end=$1;  
  167.   response_len=bodyLen;  
  168.   server_process=timeSub(req_end,$1);  
  169.   slient_start=$1;  
  170.   response_appflag=last_appflag;  
  171. }  
  172.   
  173. function mergeResponse()  
  174. {  
  175.   response_end=$1;  
  176.   response_len+=bodyLen;  
  177.   slient_start=$1;  
  178.   if(""!=last_appflag)  
  179.     response_appflag=last_appflag;  
  180. }  
  181.   
  182. function prepareClose()  
  183. {  
  184.   close_start="";  
  185.   close_end="";  
  186.   close_bytes=0;  
  187.   close_timeout=0;  
  188.   client_close=0;  
  189.   server_close=0;  
  190.   close_slient_time=0;  
  191. }  
  192.   
  193. function checkCloseState()  
  194. {  
  195.   if(""==close_start)  
  196.   {  
  197.     if(1==checkflag("F") && ($3==client || $5==client":"))  
  198.     {  
  199.       close_start=$1;  
  200.       close_end=$1;  
  201.       if($3==server)  
  202.         server_close=1;  
  203.       else  
  204.         client_close=1;  
  205.       close_slient_time=timeSub(slient_start,$1);  
  206.       close_bytes+=bodyLen;  
  207.       return 1;  
  208.     }  
  209.     else  
  210.       return 0;  
  211.   }  
  212.   
  213.   if(timeSub(close_start,$1)>=max_close_wait)  
  214.   {  
  215.     close_end=$1;  
  216.     close_timeout=1;  
  217.     return 3;  
  218.   }  
  219.   
  220.   if($3==client || $5==client":")  
  221.   {  
  222.     close_bytes+=bodyLen;  
  223.     close_end=$1;  
  224.     if(1==checkflag("F"))  
  225.     {  
  226.       if($3==server && 1==client_close)  
  227.       {  
  228.         server_close=2;  
  229.         return 2;  
  230.       }  
  231.       else if($3==client && 1==server_close)  
  232.       {  
  233.         client_close=2;  
  234.         return 2;  
  235.       }  
  236.     }  
  237.   }  
  238.   
  239.   return 1;  
  240. }  
  241.   
  242. {  
  243.   last_appflag="";  
  244.   if("app_flag"==$1)  
  245.   {  
  246.     last_appflag=substr($0,length($1) + length(FS) + 1);  
  247.     getline;  
  248.   }  
  249.   
  250.   if("newfile"==$1)  
  251.   {  
  252.     if("response"==state)  
  253.       printRoundInfo();  
  254.     if(""!=close_start)  
  255.       printCloseInfo();  
  256.     if(1==need_newline)  
  257.       printf("\n");  
  258.     need_newline=0;  
  259.     isn=0;  
  260.     slient_start="";  
  261.     state="";  
  262.     next  
  263.   }  
  264.   
  265.   if(""==slient_start)  
  266.     slient_start=$1;  
  267.   
  268.   if($3!=server && $5!=server":")  
  269.     next;  
  270.   if(""!=default_client && $3!=default_client && $5!=default_client":")  
  271.     next;  
  272.   
  273.   bodyLen=getBodyLen();  
  274.     
  275.   if(""==state)  
  276.   {  
  277.     if($5!=server":")  
  278.       next;  
  279.     if(1==checkflag("S"))  
  280.       state="listen";  
  281.     else if(bodyLen>0)  
  282.     {  
  283.       client=$3;  
  284.       onFirstRoundTrip();  
  285.       prepareClose();  
  286.       state="request";  
  287.     }  
  288.     else  
  289.       next;  
  290.   }  
  291.   
  292.   if("listen"==state)  
  293.   {  
  294.     if($5==server":" && 1==checkflag("S"))  
  295.     {  
  296.       onNewConnect();  
  297.       slient_start=$1;  
  298.       state="syn_recv";  
  299.     }  
  300.   }  
  301.   else if("syn_recv"==state)  
  302.   {  
  303.     if(timeSub(connect_start,$1)>=max_connect_wait)  
  304.     {  
  305.       connect_timeout=1;  
  306.       printConnectInfo();  
  307.       slient_start=$1;  
  308.       state="listen";  
  309.     }  
  310.     else if($5==client":")  
  311.     {  
  312.       if(1==checkflag("S"))  
  313.         state="syn_ack";  
  314.       else if(1==checkflag("R"))  
  315.       {  
  316.         connect_reset=1;  
  317.         printConnectInfo();  
  318.         slient_start=$1;  
  319.         state="listen";  
  320.       }  
  321.     }  
  322.     else if($5==server":" && 1==checkflag("S"))  
  323.     {  
  324.       onNewConnect();  
  325.       slient_start=$1;  
  326.       state="syn_recv";  
  327.     }  
  328.   }  
  329.   else if("syn_ack"==state)  
  330.   {  
  331.     if(timeSub(connect_start,$1)>=max_connect_wait)  
  332.     {  
  333.       connect_timeout=1;  
  334.       printConnectInfo();  
  335.       slient_start=$1;  
  336.       state="";  
  337.     }  
  338.     else if(0==checkflag("R") && 0==checkflag("S") && $3==client)  
  339.     {  
  340.       printConnectInfo();  
  341.       onFirstRoundTrip();  
  342.       slient_start=$1;  
  343.       state="request";  
  344.     }  
  345.     else if(1==checkflag("R") && ($3==client || $5==client":"))  
  346.     {  
  347.       connect_reset=1;  
  348.       printConnectInfo();  
  349.       slient_start=$1;  
  350.       state="listen";  
  351.     }  
  352.   }  
  353.   else if("request"==state)  
  354.   {  
  355.     if(bodyLen>0)  
  356.     {  
  357.       if($3==client)  
  358.       {  
  359.         if(""==req_start)  
  360.           onNewRequest();  
  361.         else  
  362.           mergeRequest();  
  363.         if(checkCloseState()>1)  
  364.         {  
  365.           printCloseInfo();  
  366.           close_start="";            
  367.           state="listen";  
  368.         }  
  369.         slient_start=$1;  
  370.       }  
  371.       else if($5==client":")  
  372.       {  
  373.         onNewResponse();  
  374.         if(checkCloseState()>1)  
  375.         {  
  376.           printRoundInfo();  
  377.           printCloseInfo();  
  378.           close_start="";  
  379.           state="listen";  
  380.         }  
  381.         else  
  382.           state="response";  
  383.         slient_start=$1;  
  384.       }  
  385.     }  
  386.     else if(checkCloseState()>1)  
  387.     {  
  388.       printCloseInfo();  
  389.       close_start="";  
  390.       slient_start=$1;  
  391.       state="listen";  
  392.     }  
  393.     else if(1==checkflag("R") && ($3==client || $5==client":"))  
  394.     {  
  395.       printResetInfo();  
  396.       slient_start=$1;  
  397.       state="listen";  
  398.     }  
  399.   }  
  400.   else if("response"==state)  
  401.   {  
  402.     if(bodyLen>0)  
  403.     {  
  404.       if($5==client":")  
  405.       {  
  406.         mergeResponse();  
  407.         if(checkCloseState()>1)  
  408.         {  
  409.           printRoundInfo();  
  410.           printCloseInfo();  
  411.           close_start="";  
  412.           state="listen";  
  413.         }  
  414.         slient_start=$1;  
  415.       }  
  416.       else if($3==client)  
  417.       {  
  418.         printRoundInfo();  
  419.         if(checkCloseState()>1)  
  420.         {  
  421.           printCloseInfo();  
  422.           close_start="";  
  423.           state="listen";  
  424.         }  
  425.         else  
  426.         {  
  427.           onNewRequest();  
  428.           state="request";  
  429.         }  
  430.         slient_start=$1;  
  431.       }  
  432.     }  
  433.     else if(checkCloseState()>1)  
  434.     {  
  435.       printRoundInfo();  
  436.       printCloseInfo();  
  437.       close_start="";  
  438.       slient_start=$1;  
  439.       state="listen";  
  440.     }  
  441.     else if(1==checkflag("R") && ($3==client || $5==client":"))  
  442.     {  
  443.       printRoundInfo();  
  444.       printResetInfo();  
  445.       slient_start=$1;  
  446.       state="listen";  
  447.     }  
  448.   }  
  449. }  
  450.   
  451. END { \  
  452.   if("response"==state)  
  453.     printRoundInfo();  
  454.   if(""!=close_start)  
  455.     printCloseInfo();  
  456.   if(1==need_newline)  
  457.     printf("\n");  
  458. }  

fixLenParser.awk源码(这是一个插件,不可独立运行):

[plain] view plain copy
  1. function getHeaderBinLen()  
  2. {  
  3.   #check min length of (Ethernet + IP + TCP) packet header  
  4.   if(length(bin) < 108)  
  5.     return 0;  
  6.   if("08004" == substr(bin,25,5))  
  7.     ethernetHeaderLen=28;  
  8.   else if("08004" == substr(bin,29,5))  
  9.     ethernetHeaderLen=32;  
  10.   else  
  11.   {  
  12.     #unknown ethernet frame packet  
  13.     return -1;  
  14.   }  
  15.   ipHeaderLen = 8 * substr(bin,ethernetHeaderLen+2,1);  
  16.   tcpHeaderLen = 8 * substr(bin,ethernetHeaderLen+ipHeaderLen+25,1);  
  17.   return ethernetHeaderLen + ipHeaderLen + tcpHeaderLen;  
  18. }  
  19.   
  20. function parserInit(pkgBodyLen)  
  21. {  
  22.   maxLen=100;  
  23.   bin="";  
  24.   text="";  
  25.   pkgHeaderBinLen=0;  
  26.   ignore=0;  
  27. }  
  28.   
  29. function parserWork()  
  30. {  
  31.   if(1 == ignore)  
  32.     return;  
  33.   
  34.   for(field=2; field < NF; field++)  
  35.     bin=bin""$field;  
  36.   text=text""$NF;  
  37.     
  38.   if(pkgHeaderBinLen <= 0)  
  39.   {  
  40.     pkgHeaderBinLen=getHeaderBinLen();  
  41.     #print "pkgHeaderBinLen:", pkgHeaderBinLen  
  42.     if(-1 == pkgHeaderBinLen)  
  43.       ignore=1;  
  44.     if(pkgHeaderBinLen <= 0)  
  45.       return;  
  46.   }  
  47.   
  48.   if(length(text) >= pkgHeaderBinLen/2 + maxLen)  
  49.   {  
  50.     print "app_flag", substr(text,pkgHeaderBinLen/2+1, maxLen);  
  51.     ignore=1;  
  52.     return;  
  53.   }  
  54. }  
  55.   
  56. function parserEnd()  
  57. {  
  58.   if(1 == ignore)  
  59.     return;  
  60.   
  61.   print "app_flag", substr(text,pkgHeaderBinLen/2+1);  
  62. }  

lineParser.awk源码(这是一个插件,不可独立运行):

[plain] view plain copy
  1. function getHeaderBinLen()  
  2. {  
  3.   #check min length of (Ethernet + IP + TCP) packet header  
  4.   if(length(bin) < 108)  
  5.     return 0;  
  6.   if("08004" == substr(bin,25,5))  
  7.     ethernetHeaderLen=28;  
  8.   else if("08004" == substr(bin,29,5))  
  9.     ethernetHeaderLen=32;  
  10.   else  
  11.   {  
  12.     #unknown ethernet frame packet  
  13.     return -1;  
  14.   }  
  15.   ipHeaderLen = 8 * substr(bin,ethernetHeaderLen+2,1);  
  16.   tcpHeaderLen = 8 * substr(bin,ethernetHeaderLen+ipHeaderLen+25,1);  
  17.   return ethernetHeaderLen + ipHeaderLen + tcpHeaderLen;  
  18. }  
  19.   
  20. function parserInit(pkgBodyLen)  
  21. {  
  22.   maxline=1;  
  23.   bin="";  
  24.   text="";  
  25.   pkgHeaderBinLen=0;  
  26.   lineEndBin="0a";  
  27.   newLineStartInBodyBin0=0;  
  28.   lineCount=0;  
  29.   output="";  
  30.   if(pkgBodyLen < 2)  
  31.     ignore=1;  
  32.   else  
  33.     ignore=0;  
  34. }  
  35.   
  36. function parserWork()  
  37. {  
  38.   if(1 == ignore)  
  39.     return;  
  40.   
  41.   for(field=2; field < NF; field++)  
  42.     bin=bin""$field;  
  43.   text=text""$NF;  
  44.     
  45.   if(pkgHeaderBinLen <= 0)  
  46.   {  
  47.     pkgHeaderBinLen=getHeaderBinLen();  
  48.     #print "pkgHeaderBinLen:", pkgHeaderBinLen  
  49.     if(-1 == pkgHeaderBinLen)  
  50.       ignore=1;  
  51.     if(pkgHeaderBinLen <= 0)  
  52.       return;  
  53.   }  
  54.   
  55.   while(1)  
  56.   {  
  57.     pkgBodyBin=substr(bin,pkgHeaderBinLen+newLineStartInBodyBin0+1);  
  58.     #print "debug:pkgBodyBin", pkgBodyBin;  
  59.     lineEndPos=index(pkgBodyBin,lineEndBin);  
  60.     if(0 == lineEndPos)  
  61.       return;  
  62.     output=output""substr(text,(pkgHeaderBinLen+newLineStartInBodyBin0)/2+1,lineEndPos/2+1);  
  63.     #print "debug:output", output;  
  64.     lineCount++;  
  65.     if(lineCount >= maxline)  
  66.     {  
  67.       print "app_flag", output;  
  68.       ignore=1;  
  69.       return;  
  70.     }  
  71.     newLineStartInBodyBin0+=lineEndPos+1;  
  72.   }  
  73. }  
  74.   
  75. function parserEnd()  
  76. {  
  77.   if(1 == ignore)  
  78.     return;  
  79.   
  80.   output=output""substr(text,(pkgHeaderBinLen+newLineStartInBodyBin0)/2+1);  
  81.   print "app_flag", output;  
  82. }  

oracleSqlParser.awk源码(这是一个插件,不可独立运行):

[plain] view plain copy
  1. function getHeaderBinLen()  
  2. {  
  3.   #check min length of (Ethernet + IP + TCP) packet header  
  4.   if(length(bin) < 108)  
  5.     return 0;  
  6.   if("08004" == substr(bin,25,5))  
  7.     ethernetHeaderLen=28;  
  8.   else if("08004" == substr(bin,29,5))  
  9.     ethernetHeaderLen=32;  
  10.   else  
  11.   {  
  12.     #unknown ethernet frame packet  
  13.     return -1;  
  14.   }  
  15.   ipHeaderLen = 8 * substr(bin,ethernetHeaderLen+2,1);  
  16.   tcpHeaderLen = 8 * substr(bin,ethernetHeaderLen+ipHeaderLen+25,1);  
  17.   return ethernetHeaderLen + ipHeaderLen + tcpHeaderLen;  
  18. }  
  19.   
  20. function parserInit(pkgBodyLen)  
  21. {  
  22.   bin="";  
  23.   text="";  
  24.   pkgHeaderBinLen=0;  
  25.   sqlStartInBodyBin0=100;  
  26.   slqEndBin="01010";  
  27.   sql="";  
  28.   foundSqlStart=0;  
  29.   if(pkgBodyLen < sqlStartInBodyBin0/2 + 6)  
  30.     ignore=1;  
  31.   else  
  32.     ignore=0;  
  33. }  
  34.   
  35. function parserWork()  
  36. {  
  37.   if(1 == ignore)  
  38.     return;  
  39.   
  40.   for(field=2; field < NF; field++)  
  41.     bin=bin""$field;  
  42.   text=text""$NF;  
  43.   
  44.   if(pkgHeaderBinLen <= 0)  
  45.   {  
  46.     pkgHeaderBinLen=getHeaderBinLen();  
  47.     #print "pkgHeaderBinLen:", pkgHeaderBinLen  
  48.     if(-1 == pkgHeaderBinLen)  
  49.       ignore=1;  
  50.     if(pkgHeaderBinLen <= 0)  
  51.       return;  
  52.   }  
  53.   
  54.   if(0 == foundSqlStart)  
  55.   {  
  56.     if(length(text) >= (pkgHeaderBinLen+sqlStartInBodyBin0)/2 + 6)  
  57.     {  
  58.       sqlCmd=substr(text,(pkgHeaderBinLen+sqlStartInBodyBin0)/2 + 1,6);  
  59.       if("select" == sqlCmd || "update" == sqlCmd || "delete" == sqlCmd || "create" == sqlCmd)  
  60.         foundSqlStart=1;  
  61.       else  
  62.         ignore=1;  
  63.     }  
  64.   }  
  65.   else  
  66.   {  
  67.     tmpBin=substr(bin,pkgHeaderBinLen+sqlStartInBodyBin0);  
  68.     sqlEndPos=index(tmpBin,slqEndBin);  
  69.     if(sqlEndPos>0)  
  70.     {  
  71.       sql=substr(text,(pkgHeaderBinLen+sqlStartInBodyBin0)/2 + 1,(sqlEndPos - 1)/2);  
  72.       print "app_flag",sql;  
  73.       ignore=1;  
  74.     }  
  75.   }  
  76. }  
  77.   
  78. function parserEnd()  
  79. {  
  80.   if(1 == ignore)  
  81.     return;  
  82.   
  83.   if(1 == foundSqlStart)  
  84.   {  
  85.     sql=substr(text,(pkgHeaderBinLen+sqlStartInBodyBin0)/2 + 1);  
  86.     print "app_flag",sql;  
  87.   }  
  88. }  

httpParser.awk源码(这是一个插件,不可独立运行): 

[plain] view plain copy
  1. function getHeaderBinLen()  
  2. {  
  3.   #check min length of (Ethernet + IP + TCP) packet header  
  4.   if(length(bin) < 108)  
  5.     return 0;  
  6.   if("08004" == substr(bin,25,5))  
  7.     ethernetHeaderLen=28;  
  8.   else if("08004" == substr(bin,29,5))  
  9.     ethernetHeaderLen=32;  
  10.   else  
  11.   {  
  12.     #unknown ethernet frame packet  
  13.     return -1;  
  14.   }  
  15.   ipHeaderLen = 8 * substr(bin,ethernetHeaderLen+2,1);  
  16.   tcpHeaderLen = 8 * substr(bin,ethernetHeaderLen+ipHeaderLen+25,1);  
  17.   return ethernetHeaderLen + ipHeaderLen + tcpHeaderLen;  
  18. }  
  19.   
  20. function parserInit(pkgBodyLen)  
  21. {  
  22.   bin="";  
  23.   text="";  
  24.   pkgHeaderBinLen=0;  
  25.   lineEndBin="0d0a";  
  26.   spaceBin="20";  
  27.   maybeHttpReq="";  
  28.   maybeHttpResponse=0;  
  29.   if(pkgBodyLen < 16)  
  30.     ignore=1;  
  31.   else  
  32.     ignore=0;  
  33. }  
  34.   
  35. function parserWork()  
  36. {  
  37.   if(1 == ignore)  
  38.     return;  
  39.   
  40.   for(field=2; field < NF; field++)  
  41.     bin=bin""$field;  
  42.   text=text""$NF;  
  43.     
  44.   if(pkgHeaderBinLen <= 0)  
  45.   {  
  46.     pkgHeaderBinLen=getHeaderBinLen();  
  47.     #print "pkgHeaderBinLen:", pkgHeaderBinLen  
  48.     if(-1 == pkgHeaderBinLen)  
  49.       ignore=1;  
  50.     if(pkgHeaderBinLen <= 0)  
  51.       return;  
  52.   }  
  53.   
  54.   if("" == maybeHttpReq && 0 == maybeHttpResponse)  
  55.   {  
  56.     if(length(text) >= pkgHeaderBinLen/2 + 9)  
  57.     {  
  58.       tmp_count=split(substr(text,pkgHeaderBinLen/2+1,9),words,".");  
  59.       if(tmp_count <= 1)  
  60.       {  
  61.         ignore = 1;  
  62.         return;  
  63.       }  
  64.   
  65.       if("GET" == words[1] || "POST" == words[1] || "PUT" == words[1] || "DELETE" == words[1] || "OPTIONS" == words[1] || "HEAD" == words[1])  
  66.         maybeHttpReq = words[1];  
  67.       else if(words[1] ~ /^HTTP\//)  
  68.         maybeHttpResponse = 1;  
  69.       else  
  70.       {  
  71.         ignore = 1;  
  72.         return;  
  73.       }  
  74.     }  
  75.     else  
  76.       return;  
  77.   }  
  78.   
  79.   pkgBodyBin=substr(bin,pkgHeaderBinLen+1);  
  80.   lineEndPos=index(pkgBodyBin,lineEndBin);  
  81.   if(0 == lineEndPos)  
  82.     return;  
  83.     
  84.   firstLineBin=substr(pkgBodyBin,1,lineEndPos - 1);  
  85.   firstLineText=substr(text,pkgHeaderBinLen/2+1,lineEndPos/2);  
  86.   #print "debug:pkgBodyBin", pkgBodyBin;  
  87.   #print "debug:firstLineBin", firstLineBin;  
  88.   #print "debug:firstLineText", firstLineText;  
  89.   if("" != maybeHttpReq)  
  90.   {  
  91.     if(3 == split(firstLineBin, a1, spaceBin) && 2 == split(firstLineText, a2, ".HTTP/"))  
  92.       print "app_flag", a2[1];  
  93.     ignore = 1;  
  94.   }  
  95.   else if(1 == maybeHttpResponse)  
  96.   {  
  97.     if(split(firstLineBin, a1, spaceBin) >= 3 && split(firstLineText, a2, ".") >= 4 && a2[3] + 0 >= 100)  
  98.       print "app_flag", substr(firstLineText, length(a1[1])/2 + 2);  
  99.     ignore = 1;  
  100.   }  
  101. }  
  102.   
  103. function parserEnd()  
  104. {  
  105.   if(1 == ignore)  
  106.     return;  
  107.   
  108.   if("" != maybeHttpReq)  
  109.     print "app_flag", substr(text,pkgHeaderBinLen/2+1);  
  110. }  

2018-10-21 17:30:47 qq_17585545 阅读数 1861

相信抓包是程序员,运维工程师,架构师,都必不可少的一项技能。但是能够深入掌握好这门技艺的人,确实需要有开发,网络,运维,架构等"跨界”背景才能比较好的发挥抓包神技的威力。本文是纯干货,重点不在于理论,更注重实战技能,尤其注重对抓包数据的分析。本文中的命令追求的是使用最简单,最普及的Linux系统自带工具包实现各种抓包分析,具有尽可能广泛的移植性和可用性。文中给出的命令均在Centos 6.3,tcpdump 4.1版本下测试可用;其他平台及环境,可能需要你自己微调部分命令及脚本才可以运行。文中多数命令及脚本都严重依赖于tcpdump命令输出文本数据格式,微调代码时应格外注意这一点。注意,本文中的命令适用于一般的基于tcp连接的,请求响应模型的网络服务,但不适用于使用pipeline模式的网络服务。如果想理解本文命令思路的话,需要你熟悉tcp/ip协议,网络osi模型,常见网络通讯协议,socket编程,linux脚本编程,awk脚本编程,数据挖掘思维方式等知识,不足者请自行脑补。理解本文的思路后,还可以在这些命令基础上有许多种灵活搭配和变种,请自行研究。不想费脑细胞的,运气好的话,很多命令都可以直接使用。尽管这里讲的是Linux抓包,但如果使用流行的wireshark在Windows上抓包后保存成tcpdump格式文件,然后上传到Linux系统上照样可以使用本文中的命令进行分析。

 

1.盲抓

        盲抓就是瞎抓,尤其在你接触到一台陌生机器,感觉有点抓瞎的时候,应当使用本节中的方法,其目的是找出这台机器上的重点网络服务是哪些ip和端口。如果你明确的知道要抓的包是哪个ip,哪个端口,可以直接跳至下一小节。

在目标机器上抓取任意tcp数据(需要root权限):

[plain] view plain copy

  1. tcpdump -i any -nn tcp > 123.pkg.head.txt  

分析目标机器上热点ip:port(按数据包数量统计):[plain] view plain copy

  1. cat 123.pkg.head.txt | awk 'NF>5 && $2=="IP" {print $3,"[out]"; print substr($5,1,length($5)-1), "[in]"}' | sort | uniq -c | awk '{buf[NR]=$0;sum+=$1} END{for(i=1;i<=NR;i++) print buf[i], sum}' | awk '{printf("%s %s %s %.2f %%\n",$1, $2, $3, 100*$1/$4)}' | sort -nr -k 4 | less  
  2. 示例:  
  3. 2359 10.71.28.21.80 [in] 23.59 %  
  4. 2057 10.71.28.21.80 [out] 20.57 %  
  5. 331 10.71.28.20.8080 [in] 3.31 %  
  6. 253 10.71.28.20.8080 [out] 2.53 %  
  7. 190 218.92.220.60.39147 [out] 1.90 %  
  8. 154 218.92.220.60.39147 [in] 1.54 %  
  9. 106 218.92.220.56.60503 [out] 1.06 %  

分析目标机器上热点ip:port(按字节数,即带宽统计):[plain] view plain copy

  1. cat 123.pkg.head.txt | awk 'BEGIN{header_len=0x36;inp=0;inb=0;inbb=0;outp=0;outb=0;outbb=0;start="";end=""} function getBodyLen(){if("length"==$(NF-1)) return $NF;t_c=split($7,a,/[()]/);if(3==t_c)return a[2];else return 0;} NF>5 && $2=="IP" {len=header_len + getBodyLen();print $3,"[out]", len; print substr($5,1,length($5)-1), "[in]", len; }' | sort | awk 'BEGIN{ipport="";dir="";bc=0} {if($1!=ipport || $2!=dir){if(bc>0)print ipport,dir,bc;ipport=$1;dir=$2;bc=$3;}else{bc+=$3;}} END{if(bc>0)print ipport,dir,bc;}' | awk '{buf[NR]=$0;sum+=$3} END{for(i=1;i<=NR;i++) print buf[i], sum}' | awk '{printf("%s %s %s %.2f %%\n",$1, $2, $3, 100*$3/$4)}' | sort -nr -k 4 | less  
  2. 示例:  
  3. 10.71.28.21.80 [out] 2559403 42.46 %  
  4. 218.92.220.60.39147 [in] 417277 6.92 %  
  5. 10.71.28.21.80 [in] 306507 5.08 %  
  6. 101.26.37.38.39906 [in] 271432 4.50 %  
  7. 122.225.28.115.48239 [in] 170901 2.84 %  
  8. 218.92.220.56.60503 [in] 151630 2.52 %  
  9. 218.92.220.62.59711 [in] 151322 2.51 %  
  10. 218.92.220.56.25777 [in] 138038 2.29 %  
  11. 60.210.23.239.7490 [in] 131700 2.18 %  
  12. 10.71.28.20.8080 [out] 121366 2.01 %  

分析数据流量概要信息(调整ipportRegex的值来控制统计口径):[plain] view plain copy

  1. cat 123.pkg.head.txt | awk 'BEGIN{ipportRegex="10.71.28.21.80";header_len=0x36;inp=0;inb=0;inbb=0;outp=0;outb=0;outbb=0;start="";end=""} function getBodyLen(){if("length"==$(NF-1)) return $NF;t_c=split($7,a,/[()]/);if(3==t_c)return a[2];else return 0;} $3~ipportRegex{outp++;bl=getBodyLen();outb+=header_len+bl;outbb+=bl;if(""==start)start=$1;end=$1;} $5~ipportRegex{inp++;bl=getBodyLen();inb+=header_len+bl;inbb+=bl;if(""==start)start=$1;end=$1;} function timeSub(s,e){split(substr(s,1,8),sA1,":");s1=sA1[1]*3600+sA1[2]*60+sA1[3];us1=substr(s,10);split(substr(e,1,8),sA2,":");s2=sA2[1]*3600+sA2[2]*60+sA2[3];us2=substr(e,10);return s2*1000000+us2-s1*1000000-us1;} END{second=timeSub(start,end)/1000000;if(second<1) second=1; printf("total time: %.1f seconds\n", second);printf("[In]  pkg count: %s, pkg rate: %.2f pkg/s, bytes count: %s, bytes rate: %.2f KB/s, body bytes: %s, body bytes rate: %.2f KB/s, payload percent: %.1f%%\n", inp,inp/second,inb,inb/second/1024,inbb,inbb/second/1024,100*inbb/inb);printf("[Out] pkg count: %s, pkg rate: %.2f pkg/s, bytes count: %s, bytes rate: %.2f KB/s, body bytes: %s, body bytes rate: %.2f KB/s, payload percent: %.1f%%\n", outp,outp/second,outb,outb/second/1024,outbb,outbb/second/1024,100*outbb/outb);}'  
  2. cat 123.pkg.head.txt | awk 'BEGIN{ipportRegex="10.71.28.21.";header_len=0x36;inp=0;inb=0;inbb=0;outp=0;outb=0;outbb=0;start="";end=""} function getBodyLen(){if("length"==$(NF-1)) return $NF;t_c=split($7,a,/[()]/);if(3==t_c)return a[2];else return 0;} $3~ipportRegex{outp++;bl=getBodyLen();outb+=header_len+bl;outbb+=bl;if(""==start)start=$1;end=$1;} $5~ipportRegex{inp++;bl=getBodyLen();inb+=header_len+bl;inbb+=bl;if(""==start)start=$1;end=$1;} function timeSub(s,e){split(substr(s,1,8),sA1,":");s1=sA1[1]*3600+sA1[2]*60+sA1[3];us1=substr(s,10);split(substr(e,1,8),sA2,":");s2=sA2[1]*3600+sA2[2]*60+sA2[3];us2=substr(e,10);return s2*1000000+us2-s1*1000000-us1;} END{second=timeSub(start,end)/1000000;if(second<1) second=1; printf("total time: %.1f seconds\n", second);printf("[In]  pkg count: %s, pkg rate: %.2f pkg/s, bytes count: %s, bytes rate: %.2f KB/s, body bytes: %s, body bytes rate: %.2f KB/s, payload percent: %.1f%%\n", inp,inp/second,inb,inb/second/1024,inbb,inbb/second/1024,100*inbb/inb);printf("[Out] pkg count: %s, pkg rate: %.2f pkg/s, bytes count: %s, bytes rate: %.2f KB/s, body bytes: %s, body bytes rate: %.2f KB/s, payload percent: %.1f%%\n", outp,outp/second,outb,outb/second/1024,outbb,outbb/second/1024,100*outbb/outb);}'  
  3. cat 123.pkg.head.txt | awk 'BEGIN{ipportRegex="10.";header_len=0x36;inp=0;inb=0;inbb=0;outp=0;outb=0;outbb=0;start="";end=""} function getBodyLen(){if("length"==$(NF-1)) return $NF;t_c=split($7,a,/[()]/);if(3==t_c)return a[2];else return 0;} $3~ipportRegex{outp++;bl=getBodyLen();outb+=header_len+bl;outbb+=bl;if(""==start)start=$1;end=$1;} $5~ipportRegex{inp++;bl=getBodyLen();inb+=header_len+bl;inbb+=bl;if(""==start)start=$1;end=$1;} function timeSub(s,e){split(substr(s,1,8),sA1,":");s1=sA1[1]*3600+sA1[2]*60+sA1[3];us1=substr(s,10);split(substr(e,1,8),sA2,":");s2=sA2[1]*3600+sA2[2]*60+sA2[3];us2=substr(e,10);return s2*1000000+us2-s1*1000000-us1;} END{second=timeSub(start,end)/1000000;if(second<1) second=1; printf("total time: %.1f seconds\n", second);printf("[In]  pkg count: %s, pkg rate: %.2f pkg/s, bytes count: %s, bytes rate: %.2f KB/s, body bytes: %s, body bytes rate: %.2f KB/s, payload percent: %.1f%%\n", inp,inp/second,inb,inb/second/1024,inbb,inbb/second/1024,100*inbb/inb);printf("[Out] pkg count: %s, pkg rate: %.2f pkg/s, bytes count: %s, bytes rate: %.2f KB/s, body bytes: %s, body bytes rate: %.2f KB/s, payload percent: %.1f%%\n", outp,outp/second,outb,outb/second/1024,outbb,outbb/second/1024,100*outbb/outb);}'  
  4. 示例:  
  5. total time: 45.7 seconds  
  6. [In]  pkg count: 2359, pkg rate: 51.59 pkg/s, bytes count: 306507, bytes rate: 6.55 KB/s, body bytes: 179121, body bytes rate: 3.83 KB/s, payload percent: 58.4%  
  7. [Out] pkg count: 2057, pkg rate: 44.99 pkg/s, bytes count: 2559403, bytes rate: 54.66 KB/s, body bytes: 2448325, body bytes rate: 52.29 KB/s, payload percent: 95.7%  

 

2.抓取源数据

        明确了要抓取的目标服务的ip和端口后,就要开始正式抓包了,这些抓包数据是后续分析工作的基础。当然,你可能在抓包之前还要做一些其他工作,以保证抓包时的工作场景就是你想要分析的目标场景。抓包时你需要root权限。

抓取不含包体的包:

[plain] view plain copy

  1. tcpdump -nn port 80 > 123.pkg.txt  

抓取含有包体的包并进行初步解包:[plain] view plain copy

  1. tcpdump port 80 -w 123.pkg -s 120  
  2. tcpdump port 80 -w 123.pkg -s 0  
  3. tcpdump -r 123.pkg -XXnn > 123.pkg.txt  
  4. 示例:  
  5. 11:12:01.894222 IP 10.64.12.14.59493 > 10.70.60.56.1521: Flags [P.], seq 3862499245:3862499262, ack 627056474, win 501, options [nop,nop,TS val 2916000715 ecr 736856730], length 17  
  6.         0x0000:  0000 0c07 ace9 0022 195d 2445 0800 4500  .......".]$E..E.  
  7.         0x0010:  0045 cb3b 4000 4006 12ac 0a40 0c0e 0a46  .E.;@.@....@...F  
  8.         0x0020:  3c38 e865 05f1 e639 0fad 2560 1f5a 8018  <8.e...9..%`.Z..  
  9.         0x0030:  01f5 5d03 0000 0101 080a adce a3cb 2beb  ..]...........+.  
  10.         0x0040:  8a9a 0011 0000 0600 0000 0000 0305 0001  ................  
  11.         0x0050:  0301 0a                                  ...  
  12. 11:12:01.894226 IP 10.64.12.14.59514 > 10.70.60.56.1521: Flags [P.], seq 3903163064:3903163580, ack 4171729186, win 501, options [nop,nop,TS val 2916000715 ecr 736856729], length 516  
  13.         0x0000:  0000 0c07 ace9 0022 195d 2445 0800 4500  .......".]$E..E.  
  14.         0x0010:  0238 f2e9 4000 4006 e90a 0a40 0c0e 0a46  .8..@.@....@...F  
  15.         0x0020:  3c38 e87a 05f1 e8a5 8ab8 f8a7 8922 8018  <8.z........."..  
  16.         0x0030:  01f5 5ef6 0000 0101 080a adce a3cb 2beb  ..^...........+.  
  17.         0x0040:  8a99 0204 0000 0600 0000 0000 1169 0001  .............i..  

 

3.过滤

       有时候,需要分析的问题是包含在抓取目标服务的全部数据包中的一小部分,这个时候就要对包数据进行过滤。当然也可以在上一节进行抓取时直接进行过滤,但这里主要满足事后的过滤需求。

过滤掉含有包体的数据文件,只保留数据包头:

[plain] view plain copy

  1. cat 123.pkg.txt | awk 'substr($1,1,3)!="0x0"' > 123.pkg.head.txt  
  2. 示例:  
  3. 11:12:01.894222 IP 10.64.12.14.59493 > 10.70.60.56.1521: Flags [P.], seq 3862499245:3862499262, ack 627056474, win 501, options [nop,nop,TS val 2916000715 ecr 736856730], length 17  
  4. 11:12:01.894226 IP 10.64.12.14.59514 > 10.70.60.56.1521: Flags [P.], seq 3903163064:3903163580, ack 4171729186, win 501, options [nop,nop,TS val 2916000715 ecr 736856729], length 516  
  5. 11:12:01.894228 IP 10.64.12.14.59518 > 10.70.60.56.1521: Flags [P.], seq 3897659932:3897660175, ack 3171500152, win 501, options [nop,nop,TS val 2916000715 ecr 736856729], length 243  
  6. 11:12:01.894231 IP 10.64.12.14.59512 > 10.70.60.56.1521: Flags [P.], seq 3898476274:3898476788, ack 1748466768, win 501, options [nop,nop,TS val 2916000715 ecr 736856730], length 514  

按时间段过滤含有包体的数据文件(调整start和end的值以改变时间范围):[plain] view plain copy

  1. cat 123.pkg.txt | awk 'BEGIN {start="11:13:49.0";end="11:13:49.9";flag=0} {if(substr($1,1,3)=="0x0"){if(1==flag){print $0}}else{cur=substr($1,1,length(start));if(cur>=start && cur<=end){print $0;flag=1}else{flag=0}}}' > new123.pkg.txt  

按ip端口过滤含有包体的数据文件(调整ip和port的值):[plain] view plain copy

  1. cat new123.pkg.txt | awk 'BEGIN {ip="192.168.122.180";port="54365";flag=0} {if(substr($1,1,3)=="0x0"){if(1==flag){print $0}}else if($0~ip"."port){print $0;flag=1;}else{flag=0;}}' > newnew123.pkg.txt  

按文本关键字过滤含有包体的数据文件(调整keyword的值):[plain] view plain copy

  1. cat newnew123.pkg.txt | awk 'BEGIN{keyword="id_10bc3c9";buf="";found=0} {if(substr($1,1,2)=="0x"){if($0~keyword) found=1;buf=buf"\n"$0}else{if(1==found){print buf;found=0;}if($0~keyword) found=1;buf=$0}} END{if(1==found) print buf}' > tmp.pkg.txt  

按二进制串关键字从二进制数据包中过滤含有包体的数据文件(性能稍低,对于大文件耐心等待;例子中是过滤包含"test_dava_11968@163.com"字符串的数据包):[plain] view plain copy

  1. cat newnew123.pkg.txt | awk 'BEGIN{keyword="746573745f646176615f3131393638403136332e636f6d";bin="";buf=""} {if(substr($1,1,2)=="0x"){for(i=2;i<NF;i++) bin=bin""$i;buf=buf"\n"$0}else{if(length(bin)>0&&bin~keyword) print buf;buf=$0;bin=""}} END{if(length(bin)>0&&bin~keyword) print buf}' > tmp2.pkg.txt  

 

4.分类

       通过分类,将抓包文件中混杂在一起的多个客户端的数据包拆分成各自单独的文件,以利于人工查看以及后续分析。新生成的文件放在当前目录下的子目录中,例如10.64.12.14.443_detail。

按client端ip端口将混杂在一起的含有包体的包拆分的单独文件:

[plain] view plain copy

  1. cat 123.pkg.txt | awk 'BEGIN{server="10.70.60.56.1521";buf="";client="";dir=server"_detail";system("mkdir "dir" 2>/dev/null")} {if(substr($1,1,2)=="0x"){buf=buf"\n"$0}else{if(length(client)>0) print buf>>dir"/"client".txt";if($3==server){client=substr($5,1,length($5)-1);}else if($5~server){client=$3}else{client=""} buf=$0}}'  

按client端ip端口将混杂在一起的含有包体的包拆分的单独文件(超过1000个client后因受同时打开文件数限制awk性能非常低,可增加dd命令的bs缓冲区大小,并使用limit参数进行限制):
[plain] view plain copy

  1. dd if=123.pkg.txt bs=100M 2>/dev/null | awk 'BEGIN{server="10.70.60.56.1521";limit=1000;buf="";client="";count=0;dir=server"_detail";system("mkdir "dir" 2>/dev/null")} {if(substr($1,1,2)=="0x"){if(length(client)>0) buf=buf"\n"$0}else{if(length(client)>0) print buf>>dir"/"client".txt";if($3==server){client=substr($5,1,length($5)-1)}else if($5~server){client=$3}else{client=""}if(length(client)>0){if("ok"==all_clients[client]){buf=$0}else if(count<limit){count++;all_clients[client]="ok";buf=$0}else{client=""}}}}'  

 

5.交互分析

       前面的分析处理仅限于数据包本身的ip和port,而本节的交互分析则将数据包归类到一个个具体的tcp连接之中,提取有关的交互“成本”数据,并尝试分析数据包在请求响应模型中的交互语义。本节中的命令需要系列awk脚本支持,为不影响理解本节主要内容,相关脚本源码附录在文章末尾供参考,其中包含主脚本parseTcp.awk,以及若干插件脚本:fixLenParser.awk,lineParser.awk,oracleSqlParser.awk,httpParser.awk。

分析单个不含包体的数据文件的交互过程:

[plain] view plain copy

  1. cat 123.pkg.txt | /data/speng/tcpdump/parseTcp.awk 61.135.169.125.80 > interaction.txt  

分析单个不含包体的数据文件中只与某特定客户端有关的交互过程:[plain] view plain copy

  1. cat 123.pkg.txt | /data/speng/tcpdump/parseTcp.awk 61.135.169.125.80 1 172.20.154.45.3752 > interaction.txt  
  2. 示例:  
  3. 14:00:53.123517 client 172.20.154.45.3752_2455096098 connect take(us): 3291 slient_before(us): 72266270 result: ok  
  4. 14:00:53.132710 client 172.20.154.45.3752_2455096098 round-trip 1 slient_before(us): 5902 total take(us): 5927 req_time(us): 76 req_bytes: 1635 server_process(us): 5402 response_time(us): 449 response_bytes: 6587  
  5. 14:00:53.263446 client 172.20.154.45.3752_2455096098 round-trip 2 slient_before(us): 124809 total take(us): 17767 req_time(us): 88 req_bytes: 1620 server_process(us): 17679 response_time(us): 0 response_bytes: 946  
  6. 14:00:53.472286 client 172.20.154.45.3752_2455096098 round-trip 3 slient_before(us): 191073 total take(us): 9319 req_time(us): 53 req_bytes: 1620 server_process(us): 8517 response_time(us): 749 response_bytes: 10361  
  7. 14:00:54.587117 client 172.20.154.45.3752_2455096098 round-trip 4 slient_before(us): 1105512 total take(us): 13233 req_time(us): 92 req_bytes: 1618 server_process(us): 13113 response_time(us): 28 response_bytes: 2777  
  8. 14:01:14.598513 client 172.20.154.45.3752_2455096098 close take(us): 589 slient_before(us): 19998163 close_bytes: 0 direction: server->client result: full_close  

分析多个分类后含有包体的数据文件的交互过程(cd进入上一节分类后所生成的目录下执行命令):
[plain] view plain copy

  1. ls | xargs -n 10 awk 'BEGIN{f=""} {if(FILENAME!=f){print "newfile",FILENAME;f=FILENAME}if(substr($1,1,2)!="0x") print $0}' | ../parseTcp.awk 10.70.60.56.1521 > ../interaction.txt  

分析多个分类后含有包体的数据文件的交互过程(cd进入分类后文件所在目录下执行命令。支持识别包体中的特征数据,并打印出来便于后续业务分析。可编写类似oracleSqlParser.awk或httpParser.awk插件脚本进行新协议或业务扩展。源码附录在文章末尾):[plain] view plain copy

  1. ls | xargs -n 10 awk -f ../oracleSqlParser.awk --source 'function getLen(){if("length"==$(NF-1)) return $NF;t_c=split($7,a,/[()]/);if(3==t_c) return a[2];else return 0;} BEGIN{f="";h="";b=0;} {if(FILENAME!=f){if(1==b)parserEnd();if(""!=h)print h;print "newfile",FILENAME;f=FILENAME;h="";b=0;}if(substr($1,1,2)=="0x"){if(1==b)parserWork();}else{if(1==b)parserEnd();b=0;if(""!=h)print h;h=$0;bl=getLen();if(bl>0){parserInit(bl);b=1;}}} END{if(1==b)parserEnd();if(""!=h)print h;}' | ../parseTcp.awk 10.70.60.56.1521 > ../interaction.txt  
  2. ls | xargs -n 10 awk -f ../httpParser.awk --source 'function getLen(){if("length"==$(NF-1)) return $NF;t_c=split($7,a,/[()]/);if(3==t_c) return a[2];else return 0;} BEGIN{f="";h="";b=0;} {if(FILENAME!=f){if(1==b)parserEnd();if(""!=h)print h;print "newfile",FILENAME;f=FILENAME;h="";b=0;}if(substr($1,1,2)=="0x"){if(1==b)parserWork();}else{if(1==b)parserEnd();b=0;if(""!=h)print h;h=$0;bl=getLen();if(bl>0){parserInit(bl);b=1;}}} END{if(1==b)parserEnd();if(""!=h)print h;}' | ../parseTcp.awk 10.70.66.120.80 > ../interaction.txt  
  3. 示例:  
  4. sql:  
  5. 11:12:29.422380 client 10.64.12.14.59573_3961647293 connect take(us): 567 slient_before(us): 0 result: ok  
  6. 11:12:29.423124 client 10.64.12.14.59573_3961647293 round-trip 1 slient_before(us): 177 total take(us): 54042 req_time(us): 0 req_bytes: 211 server_process(us): 54042 response_time(us): 0 response_bytes: 8  
  7. 11:12:29.478165 client 10.64.12.14.59573_3961647293 round-trip 2 slient_before(us): 999 total take(us): 2021 req_time(us): 1409 req_bytes: 363 server_process(us): 612 response_time(us): 0 response_bytes: 127  
  8. 11:12:29.480257 client 10.64.12.14.59573_3961647293 round-trip 3 slient_before(us): 71 total take(us): 1420 req_time(us): 0 req_bytes: 33 server_process(us): 1420 response_time(us): 0 response_bytes: 188  
  9. 11:12:29.481825 client 10.64.12.14.59573_3961647293 round-trip 4 slient_before(us): 148 total take(us): 1036 req_time(us): 0 req_bytes: 779 server_process(us): 1036 response_time(us): 0 response_bytes: 834  
  10. 11:12:29.483414 client 10.64.12.14.59573_3961647293 round-trip 5 slient_before(us): 553 total take(us): 3983 req_time(us): 810 req_bytes: 184 server_process(us): 3173 response_time(us): 0 response_bytes: 73  
  11. 11:12:29.487836 client 10.64.12.14.59573_3961647293 round-trip 6 slient_before(us): 439 total take(us): 4891 req_time(us): 0 req_bytes: 574 server_process(us): 4891 response_time(us): 0 response_bytes: 1180  
  12. 11:12:29.492988 client 10.64.12.14.59573_3961647293 round-trip 7 slient_before(us): 261 total take(us): 3220 req_time(us): 0 req_bytes: 505 server_process(us): 3220 response_time(us): 0 response_bytes: 358  
  13. 11:12:29.496568 client 10.64.12.14.59573_3961647293 round-trip 8 slient_before(us): 360 total take(us): 2276 req_time(us): 0 req_bytes: 245 server_process(us): 2276 response_time(us): 0 response_bytes: 393 req_appflag: select.usrid,mailadd,mailflg,mobile,verifyflg,user_seq_id,is_oauth_type,lastlogin,pwd_strict.from.tab_users.where.mailadd.=:1--con_id_52d2c4  
  14. 11:12:29.499283 client 10.64.12.14.59573_3961647293 round-trip 9 slient_before(us): 439 total take(us): 704 req_time(us): 0 req_bytes: 17 server_process(us): 704 response_time(us): 0 response_bytes: 208  
  15. 11:12:29.500267 client 10.64.12.14.59573_3961647293 round-trip 10 slient_before(us): 280 total take(us): 766 req_time(us): 0 req_bytes: 245 server_process(us): 766 response_time(us): 0 response_bytes: 393 req_appflag: select.usrid,mailadd,mailflg,mobile,verifyflg,user_seq_id,is_oauth_type,lastlogin,pwd_strict.from.tab_users.where.mailadd.=:1--con_id_52d2c4  
  16. 11:12:29.501945 client 10.64.12.14.59573_3961647293 round-trip 11 slient_before(us): 912 total take(us): 681 req_time(us): 0 req_bytes: 17 server_process(us): 681 response_time(us): 0 response_bytes: 208  
  17. 11:12:29.503286 client 10.64.12.14.59573_3961647293 round-trip 12 slient_before(us): 660 total take(us): 4956 req_time(us): 0 req_bytes: 513 server_process(us): 4956 response_time(us): 0 response_bytes: 64 req_appflag: update.tab_users.tu.set.tu.lastlogin_third=tu.lastlogin,tu.lastlogin=to_date(:1,'yyyy-mm-dd.hh24:mi:ss'),tu.uct_time=to_date(:2,'yyyy-mm-dd.hh24:mi:ss'),tu.uct=:3,tu.auto_login_flag=:4,login_ip=:5.where.mailadd.=:6--con_id_52d2c4  
  18. 11:12:29.510362 client 10.64.12.14.59573_3961647293 round-trip 13 slient_before(us): 2120 total take(us): 3591 req_time(us): 0 req_bytes: 515 server_process(us): 3591 response_time(us): 0 response_bytes: 63 req_appflag: update.tab_users.tu.set.tu.lastlogin_third=tu.lastlogin,tu.lastlogin=to_date(:1,'yyyy-mm-dd.hh24:mi:ss'),tu.uct_time=to_date(:2,'yyyy-mm-dd.hh24:mi:ss'),tu.uct=:3,tu.auto_login_flag=:4,login_ip=:5.where.mailadd.=:6--con_id_52d2c4  
  19. 11:12:29.515085 client 10.64.12.14.59573_3961647293 round-trip 14 slient_before(us): 1132 total take(us): 3660 req_time(us): 0 req_bytes: 513 server_process(us): 3660 response_time(us): 0 response_bytes: 63 req_appflag: update.tab_users.tu.set.tu.lastlogin_third=tu.lastlogin,tu.lastlogin=to_date(:1,'yyyy-mm-dd.hh24:mi:ss'),tu.uct_time=to_date(:2,'yyyy-mm-dd.hh24:mi:ss'),tu.uct=:3,tu.auto_login_flag=:4,login_ip=:5.where.mailadd.=:6--con_id_52d2c4  
  20. 11:12:29.518969 client 10.64.12.14.59573_3961647293 round-trip 15 slient_before(us): 224 total take(us): 724 req_time(us): 0 req_bytes: 245 server_process(us): 724 response_time(us): 0 response_bytes: 392 req_appflag: select.usrid,mailadd,mailflg,mobile,verifyflg,user_seq_id,is_oauth_type,lastlogin,pwd_strict.from.tab_users.where.mailadd.=:1--con_id_52d2c4  
  21. 11:12:29.519737 client 10.64.12.14.59573_3961647293 round-trip 16 slient_before(us): 44 total take(us): 664 req_time(us): 0 req_bytes: 17 server_process(us): 664 response_time(us): 0 response_bytes: 208  
  22. 11:12:29.522030 client 10.64.12.14.59573_3961647293 round-trip 17 slient_before(us): 1629 total take(us): 4037 req_time(us): 0 req_bytes: 513 server_process(us): 4037 response_time(us): 0 response_bytes: 63 req_appflag: update.tab_users.tu.set.tu.lastlogin_third=tu.lastlogin,tu.lastlogin=to_date(:1,'yyyy-mm-dd.hh24:mi:ss'),tu.uct_time=to_date(:2,'yyyy-mm-dd.hh24:mi:ss'),tu.uct=:3,tu.auto_login_flag=:4,login_ip=:5.where.mailadd.=:6--con_id_52d2c4  
  23. 11:12:29.526610 client 10.64.12.14.59573_3961647293 round-trip 18 slient_before(us): 543 total take(us): 709 req_time(us): 0 req_bytes: 245 server_process(us): 709 response_time(us): 0 response_bytes: 392 req_appflag: select.usrid,mailadd,mailflg,mobile,verifyflg,user_seq_id,is_oauth_type,lastlogin,pwd_strict.from.tab_users.where.mailadd.=:1--con_id_52d2c4  
  24. 11:12:29.527617 client 10.64.12.14.59573_3961647293 round-trip 19 slient_before(us): 298 total take(us): 1490 req_time(us): 0 req_bytes: 17 server_process(us): 1490 response_time(us): 0 response_bytes: 208   
  25.   
  26. http:  
  27. 14:00:53.123517 client 172.20.154.45.3752_2455096098 connect take(us): 3291 slient_before(us): 72266270 result: ok  
  28. 14:00:53.132710 client 172.20.154.45.3752_2455096098 round-trip 1 slient_before(us): 5902 total take(us): 5927 req_time(us): 76 req_bytes: 1635 server_process(us): 5402 response_time(us): 449 response_bytes: 6587 req_appflag: GET./static/api/js/share.js?v=89860593.js?cdnversion=403517 response_appflag: 200.OK  
  29. 14:00:53.263446 client 172.20.154.45.3752_2455096098 round-trip 2 slient_before(us): 124809 total take(us): 17767 req_time(us): 88 req_bytes: 1620 server_process(us): 17679 response_time(us): 0 response_bytes: 946 req_appflag: GET./static/js/shell_v2.js?cdnversion=403519 response_appflag: 200.OK  
  30. 14:00:53.472286 client 172.20.154.45.3752_2455096098 round-trip 3 slient_before(us): 191073 total take(us): 9319 req_time(us): 53 req_bytes: 1620 server_process(us): 8517 response_time(us): 749 response_bytes: 10361 req_appflag: GET./static/js/bds_s_v2.js?cdnversion=403519 response_appflag: 200.OK  
  31. 14:00:54.587117 client 172.20.154.45.3752_2455096098 round-trip 4 slient_before(us): 1105512 total take(us): 13233 req_time(us): 92 req_bytes: 1618 server_process(us): 13113 response_time(us): 28 response_bytes: 2777 req_appflag: GET./static/js/logger.js?cdnversion=403519 response_appflag: 200.OK  
  32. 14:01:14.598513 client 172.20.154.45.3752_2455096098 close take(us): 589 slient_before(us): 19998163 close_bytes: 0 direction: server->client result: full_close  
  33.   
  34. https:  
  35. 16:53:29.658744 client 10.64.12.16.32769_169947140 connect take(us): 89 slient_before(us): 0 result: ok  
  36. 16:53:29.658857 client 10.64.12.16.32769_169947140 round-trip 1 slient_before(us): 24 total take(us): 6865 req_time(us): 0 req_bytes: 117 server_process(us): 1535 response_time(us): 5330 response_bytes: 5140  
  37. 16:53:29.670379 client 10.64.12.16.32769_169947140 round-trip 2 slient_before(us): 4657 total take(us): 6071 req_time(us): 0 req_bytes: 198 server_process(us): 6071 response_time(us): 0 response_bytes: 59  
  38. 16:53:29.676530 client 10.64.12.16.32769_169947140 round-trip 3 slient_before(us): 80 total take(us): 983303 req_time(us): 0 req_bytes: 133 server_process(us): 983303 response_time(us): 0 response_bytes: 842  
  39. 16:53:30.659883 client 10.64.12.16.32769_169947140 close take(us): 4412 slient_before(us): 50 close_bytes: 37 direction: server->client result: full_close  
  40. 16:54:39.540752 client 10.64.12.16.32769_239829149 connect take(us): 91 slient_before(us): 68876457 result: ok  
  41. 16:54:39.540866 client 10.64.12.16.32769_239829149 round-trip 1 slient_before(us): 23 total take(us): 7459 req_time(us): 0 req_bytes: 117 server_process(us): 2127 response_time(us): 5332 response_bytes: 5140  
  42. 16:54:39.552971 client 10.64.12.16.32769_239829149 round-trip 2 slient_before(us): 4646 total take(us): 5452 req_time(us): 0 req_bytes: 198 server_process(us): 5452 response_time(us): 0 response_bytes: 59  
  43. 16:54:39.558487 client 10.64.12.16.32769_239829149 round-trip 3 slient_before(us): 64 total take(us): 965470 req_time(us): 0 req_bytes: 133 server_process(us): 965470 response_time(us): 0 response_bytes: 842  
  44. 16:54:40.524004 client 10.64.12.16.32769_239829149 close take(us): 115 slient_before(us): 47 close_bytes: 37 direction: server->client result: full_close  


 

6.统计分析

        统计分析用于掌握一批数据包反映的整体交互规律和指标数据。配合使用上一节交互分析中获得的业务关键字过滤,还可以分析具有某些特定特征的交互指标数据。

分析多行模式输出的交互过程的请求响应对的平均响应时间(含请求响应的网络传输时间,但不含socket建立阶段):

[plain] view plain copy

  1. cat interaction.txt | grep round-trip | awk '{sum+=($10/1000000)} END {print "Lines = "NR", Sum = "sum"(seconds), Average = "sum/NR"(seconds)"}'   
  2. 示例:  
  3. Lines = 678796, Sum = 4234.81(seconds), Average = 0.00623871(seconds)  

分析多行模式输出的交互过程的请求响应对的服务器平均处理时间:[plain] view plain copy

  1. cat interaction.txt | grep round-trip | awk '{sum+=($16/1000000)} END {print "Lines = "NR", Sum = "sum"(seconds), Average = "sum/NR"(seconds)"}'  
  2. 示例:  
  3. Lines = 678796, Sum = 1612.32(seconds), Average = 0.00237526(seconds)  

分析多行模式输出的交互过程的请求响应对的平均请求大小:[plain] view plain copy

  1. cat interaction.txt | grep round-trip | awk '{sum+=$14} END {print "Lines = "NR", Sum = "sum"(bytes), Average = "sum/NR"(bytes)"}'  

分析多行模式输出的交互过程的请求响应对的平均响应大小:[plain] view plain copy

  1. cat interaction.txt | grep round-trip | awk '{sum+=$20} END {print "Lines = "NR", Sum = "sum"(bytes), Average = "sum/NR"(bytes)"}'  

分析某多行模式输出的https短连接交互过程的ssl握手阶段的平均处理时间:[plain] view plain copy

  1. cat interaction.txt | grep round-trip | awk '$5==1 {start=$1;r1_time=$10} $5==2 {slient=$7;r2_time=$10;print start, r1_time+slient+r2_time}' | awk '{sum+=($2/1000000)} END {print "Lines = "NR", Sum = "sum"(seconds), Average = "sum/NR"(seconds)"}'  
  2. 示例:  
  3. Lines = 284861, Sum = 12216.7(seconds), Average = 0.0428866(seconds)  

分析某多行模式输出的https短连接交互过程的ssl握手阶段的tps及每秒平均处理时间(可导入excel作图):[plain] view plain copy

  1. cat interaction.txt | grep round-trip | awk '$5==1 {start=$1;r1_time=$10} $5==2 {slient=$7;r2_time=$10;print start, r1_time+slient+r2_time}' | sort | awk '{print $2,$1}' | awk -F '.' '{print $1}' | awk 'BEGIN{sum=0;count=0;time=""} {if($2!=time){if(count>0) print time,count,sum/count/1000000;sum=$1;count=1;time=$2}else{sum+=$1;count++}} END{if(count>0) print time,count,sum/count/1000000}'  

上例做图如下:

分析某多行模式输出的https短连接交互过程的socket建立完成至服务器accept此连接经历的平均等待时间(可导入excel作图):

[plain] view plain copy

  1. cat interaction.txt | grep "round-trip 1 " | awk '{print $1,$7}' | sort | awk '{print $2,$1}' | awk -F '.' '{print $1}' | awk 'BEGIN{sum=0;count=0;time=""} {if($2!=time){if(count>0) printf("%s %s %.6f\n", time,count,sum/count/1000000);sum=$1;count=1;time=$2}else{sum+=$1;count++}} END{if(count>0) printf("%s %s %.6f\n", time,count,sum/count/1000000)}'  

分析某多行模式输出含有包体特征数据的oracle长连接交互过程中select语句及update语句的平均响应时间:[plain] view plain copy

  1. cat interaction.txt | grep select | awk '{sum+=($10/1000000)} END {print "Lines = "NR", Sum = "sum"(seconds), Average = "sum/NR"(seconds)"}'  
  2. cat interaction.txt | grep update | awk '{sum+=($10/1000000)} END {print "Lines = "NR", Sum = "sum"(seconds), Average = "sum/NR"(seconds)"}'  



 

附录:

parseTcp.awk源码(文件需有可执行权限):

[plain] view plain copy

  1. #!/bin/awk -f  
  2.   
  3. BEGIN \  
  4. {  
  5.   if(ARGC<2)  
  6.   {  
  7.     printf("Usage:\n");  
  8.     printf("      ./parseTcp.awk <server ip port> [<print in multi line, 0 or 1, default to 1> [client ip port]]\n");  
  9.     printf("Example:\n");  
  10.     printf("      cat ./pkg.txt | ./parseTcp.awk 10.64.12.14.443 1 10.64.12.16.60990\n");  
  11.     exit;  
  12.   }  
  13.   server=ARGV[1];  
  14.   multi_line=1;  
  15.   if(ARGC>2)  
  16.     multi_line=ARGV[2];  
  17.   default_client="";  
  18.   if(ARGC>3)  
  19.      default_client=ARGV[3];  
  20.   max_close_wait=240000000;  
  21.   max_connect_wait=max_close_wait;  
  22.   isn=0;  
  23.   need_newline=0;  
  24.   ARGC=1;  # don't delete this line!  
  25. }  
  26.   
  27. function checkflag(flag)  
  28. {  
  29.   pkgFlag=$6;  
  30.   if("Flags"==pkgFlag)  
  31.     pkgFlag=$7;  
  32.   if(pkgFlag~flag)  
  33.     return 1;  
  34.   else  
  35.     return 0  
  36. }  
  37.   
  38. function getBodyLen()  
  39. {  
  40.   if("length"==$(NF-1)) return $NF;  
  41.   count=split($7,a,/[()]/);  
  42.   if(3==count)  
  43.     return a[2];  
  44.   else  
  45.     return 0;  
  46. }  
  47.   
  48. function getTcpISN()  
  49. {  
  50.   if("seq"==$8)  
  51.     return substr($9,1,length($9)-1);  
  52.   count=split($7,a,":");  
  53.   if(2==count)  
  54.     return a[1];  
  55.   else  
  56.     return 0;  
  57. }  
  58.   
  59. function timeSub(start,end)  
  60. {  
  61.   split(substr(start,1,8),sA1,":");  
  62.   s1=sA1[1]*3600+sA1[2]*60+sA1[3];  
  63.   us1=substr(start,10);  
  64.   split(substr(end,1,8),sA2,":");  
  65.   s2=sA2[1]*3600+sA2[2]*60+sA2[3];  
  66.   us2=substr(end,10);  
  67.   return s2*1000000+us2-s1*1000000-us1;  
  68. }  
  69.   
  70. function printConnectInfo()  
  71. {  
  72.   if(1==connect_reset)  
  73.     connect_result="reset_by_server";  
  74.   else if(1==connect_timeout)  
  75.     connect_result="timeout";  
  76.   else  
  77.     connect_result="ok";  
  78.   printf("%s client %s_%s connect take(us): %s slient_before(us): %s result: %s",connect_start, client, isn, timeSub(connect_start,$1), slient_time, connect_result);  
  79.   need_newline=1;  
  80.   if("ok"!=connect_result)  
  81.   {  
  82.     printf("\n");  
  83.     need_newline=0;  
  84.   }  
  85. }  
  86.   
  87. function printRoundInfo()  
  88. {  
  89.   if(1==multi_line){printf("\n")}else{printf(" || ")}  
  90.   printf("%s client %s_%s round-trip %d slient_before(us): %s total take(us): %s req_time(us): %s req_bytes: %s server_process(us): %s response_time(us): %s response_bytes: %s",req_start, client, isn, round, slient_time, timeSub(req_start,response_end), timeSub(req_start,req_end), req_len, server_process, timeSub(response_start,response_end), response_len);  
  91.   if(""!=req_appflag)  
  92.     printf(" req_appflag: %s",req_appflag);  
  93.   if(""!=response_appflag)  
  94.     printf(" response_appflag: %s",response_appflag);  
  95.   need_newline=1;  
  96. }  
  97.   
  98. function printCloseInfo()  
  99. {  
  100.   if(1==server_close)  
  101.     direction="server->client";  
  102.   else  
  103.     direction="client->server";  
  104.   if(1==close_timeout)  
  105.     close_result="close_timeout";  
  106.   else if(2==client_close || 2==server_close)  
  107.     close_result="full_close";  
  108.   else  
  109.     close_result="half_close";  
  110.   if(1==multi_line){printf("\n")}else{printf(" || ")}  
  111.   printf("%s client %s_%s close take(us): %s slient_before(us): %s close_bytes: %s direction: %s result: %s\n", close_start, client, isn, timeSub(close_start,close_end), close_slient_time, close_bytes, direction, close_result);  
  112.   need_newline=0;  
  113. }  
  114.   
  115. function printResetInfo()  
  116. {  
  117.   if(1==multi_line){printf("\n")}else{printf(" || ")};  
  118.   if($3==server)  
  119.     resetPeer="server";  
  120.   else  
  121.     resetPeer="client";  
  122.   printf("%s client %s_%s reset connect by %s\n", $1, client, isn, resetPeer);  
  123.   need_newline=0;  
  124. }  
  125.   
  126. function onNewConnect()  
  127. {  
  128.   client=$3;  
  129.   isn=getTcpISN();  
  130.   slient_time=timeSub(slient_start,$1);  
  131.   connect_start=$1;  
  132.   connect_timeout=0;  
  133.   connect_reset=0;  
  134.   prepareClose();  
  135. }  
  136.   
  137. function onFirstRoundTrip()  
  138. {  
  139.   req_start="";  
  140.   round=0;  
  141. }  
  142.   
  143. function onNewRequest()  
  144. {  
  145.   req_start=$1;  
  146.   req_end=$1;  
  147.   req_len=bodyLen;  
  148.   round++;  
  149.   slient_time=timeSub(slient_start,$1);  
  150.   process_start=$1;  
  151.   req_appflag=last_appflag;  
  152. }  
  153.   
  154. function mergeRequest()  
  155. {  
  156.   req_end=$1;  
  157.   req_len+=bodyLen;  
  158.   process_start=$1;  
  159.   if(""!=last_appflag)  
  160.     req_appflag=last_appflag;  
  161. }  
  162.   
  163. function onNewResponse()  
  164. {  
  165.   response_start=$1;  
  166.   response_end=$1;  
  167.   response_len=bodyLen;  
  168.   server_process=timeSub(req_end,$1);  
  169.   slient_start=$1;  
  170.   response_appflag=last_appflag;  
  171. }  
  172.   
  173. function mergeResponse()  
  174. {  
  175.   response_end=$1;  
  176.   response_len+=bodyLen;  
  177.   slient_start=$1;  
  178.   if(""!=last_appflag)  
  179.     response_appflag=last_appflag;  
  180. }  
  181.   
  182. function prepareClose()  
  183. {  
  184.   close_start="";  
  185.   close_end="";  
  186.   close_bytes=0;  
  187.   close_timeout=0;  
  188.   client_close=0;  
  189.   server_close=0;  
  190.   close_slient_time=0;  
  191. }  
  192.   
  193. function checkCloseState()  
  194. {  
  195.   if(""==close_start)  
  196.   {  
  197.     if(1==checkflag("F") && ($3==client || $5==client":"))  
  198.     {  
  199.       close_start=$1;  
  200.       close_end=$1;  
  201.       if($3==server)  
  202.         server_close=1;  
  203.       else  
  204.         client_close=1;  
  205.       close_slient_time=timeSub(slient_start,$1);  
  206.       close_bytes+=bodyLen;  
  207.       return 1;  
  208.     }  
  209.     else  
  210.       return 0;  
  211.   }  
  212.   
  213.   if(timeSub(close_start,$1)>=max_close_wait)  
  214.   {  
  215.     close_end=$1;  
  216.     close_timeout=1;  
  217.     return 3;  
  218.   }  
  219.   
  220.   if($3==client || $5==client":")  
  221.   {  
  222.     close_bytes+=bodyLen;  
  223.     close_end=$1;  
  224.     if(1==checkflag("F"))  
  225.     {  
  226.       if($3==server && 1==client_close)  
  227.       {  
  228.         server_close=2;  
  229.         return 2;  
  230.       }  
  231.       else if($3==client && 1==server_close)  
  232.       {  
  233.         client_close=2;  
  234.         return 2;  
  235.       }  
  236.     }  
  237.   }  
  238.   
  239.   return 1;  
  240. }  
  241.   
  242. {  
  243.   last_appflag="";  
  244.   if("app_flag"==$1)  
  245.   {  
  246.     last_appflag=substr($0,length($1) + length(FS) + 1);  
  247.     getline;  
  248.   }  
  249.   
  250.   if("newfile"==$1)  
  251.   {  
  252.     if("response"==state)  
  253.       printRoundInfo();  
  254.     if(""!=close_start)  
  255.       printCloseInfo();  
  256.     if(1==need_newline)  
  257.       printf("\n");  
  258.     need_newline=0;  
  259.     isn=0;  
  260.     slient_start="";  
  261.     state="";  
  262.     next  
  263.   }  
  264.   
  265.   if(""==slient_start)  
  266.     slient_start=$1;  
  267.   
  268.   if($3!=server && $5!=server":")  
  269.     next;  
  270.   if(""!=default_client && $3!=default_client && $5!=default_client":")  
  271.     next;  
  272.   
  273.   bodyLen=getBodyLen();  
  274.     
  275.   if(""==state)  
  276.   {  
  277.     if($5!=server":")  
  278.       next;  
  279.     if(1==checkflag("S"))  
  280.       state="listen";  
  281.     else if(bodyLen>0)  
  282.     {  
  283.       client=$3;  
  284.       onFirstRoundTrip();  
  285.       prepareClose();  
  286.       state="request";  
  287.     }  
  288.     else  
  289.       next;  
  290.   }  
  291.   
  292.   if("listen"==state)  
  293.   {  
  294.     if($5==server":" && 1==checkflag("S"))  
  295.     {  
  296.       onNewConnect();  
  297.       slient_start=$1;  
  298.       state="syn_recv";  
  299.     }  
  300.   }  
  301.   else if("syn_recv"==state)  
  302.   {  
  303.     if(timeSub(connect_start,$1)>=max_connect_wait)  
  304.     {  
  305.       connect_timeout=1;  
  306.       printConnectInfo();  
  307.       slient_start=$1;  
  308.       state="listen";  
  309.     }  
  310.     else if($5==client":")  
  311.     {  
  312.       if(1==checkflag("S"))  
  313.         state="syn_ack";  
  314.       else if(1==checkflag("R"))  
  315.       {  
  316.         connect_reset=1;  
  317.         printConnectInfo();  
  318.         slient_start=$1;  
  319.         state="listen";  
  320.       }  
  321.     }  
  322.     else if($5==server":" && 1==checkflag("S"))  
  323.     {  
  324.       onNewConnect();  
  325.       slient_start=$1;  
  326.       state="syn_recv";  
  327.     }  
  328.   }  
  329.   else if("syn_ack"==state)  
  330.   {  
  331.     if(timeSub(connect_start,$1)>=max_connect_wait)  
  332.     {  
  333.       connect_timeout=1;  
  334.       printConnectInfo();  
  335.       slient_start=$1;  
  336.       state="";  
  337.     }  
  338.     else if(0==checkflag("R") && 0==checkflag("S") && $3==client)  
  339.     {  
  340.       printConnectInfo();  
  341.       onFirstRoundTrip();  
  342.       slient_start=$1;  
  343.       state="request";  
  344.     }  
  345.     else if(1==checkflag("R") && ($3==client || $5==client":"))  
  346.     {  
  347.       connect_reset=1;  
  348.       printConnectInfo();  
  349.       slient_start=$1;  
  350.       state="listen";  
  351.     }  
  352.   }  
  353.   else if("request"==state)  
  354.   {  
  355.     if(bodyLen>0)  
  356.     {  
  357.       if($3==client)  
  358.       {  
  359.         if(""==req_start)  
  360.           onNewRequest();  
  361.         else  
  362.           mergeRequest();  
  363.         if(checkCloseState()>1)  
  364.         {  
  365.           printCloseInfo();  
  366.           close_start="";            
  367.           state="listen";  
  368.         }  
  369.         slient_start=$1;  
  370.       }  
  371.       else if($5==client":")  
  372.       {  
  373.         onNewResponse();  
  374.         if(checkCloseState()>1)  
  375.         {  
  376.           printRoundInfo();  
  377.           printCloseInfo();  
  378.           close_start="";  
  379.           state="listen";  
  380.         }  
  381.         else  
  382.           state="response";  
  383.         slient_start=$1;  
  384.       }  
  385.     }  
  386.     else if(checkCloseState()>1)  
  387.     {  
  388.       printCloseInfo();  
  389.       close_start="";  
  390.       slient_start=$1;  
  391.       state="listen";  
  392.     }  
  393.     else if(1==checkflag("R") && ($3==client || $5==client":"))  
  394.     {  
  395.       printResetInfo();  
  396.       slient_start=$1;  
  397.       state="listen";  
  398.     }  
  399.   }  
  400.   else if("response"==state)  
  401.   {  
  402.     if(bodyLen>0)  
  403.     {  
  404.       if($5==client":")  
  405.       {  
  406.         mergeResponse();  
  407.         if(checkCloseState()>1)  
  408.         {  
  409.           printRoundInfo();  
  410.           printCloseInfo();  
  411.           close_start="";  
  412.           state="listen";  
  413.         }  
  414.         slient_start=$1;  
  415.       }  
  416.       else if($3==client)  
  417.       {  
  418.         printRoundInfo();  
  419.         if(checkCloseState()>1)  
  420.         {  
  421.           printCloseInfo();  
  422.           close_start="";  
  423.           state="listen";  
  424.         }  
  425.         else  
  426.         {  
  427.           onNewRequest();  
  428.           state="request";  
  429.         }  
  430.         slient_start=$1;  
  431.       }  
  432.     }  
  433.     else if(checkCloseState()>1)  
  434.     {  
  435.       printRoundInfo();  
  436.       printCloseInfo();  
  437.       close_start="";  
  438.       slient_start=$1;  
  439.       state="listen";  
  440.     }  
  441.     else if(1==checkflag("R") && ($3==client || $5==client":"))  
  442.     {  
  443.       printRoundInfo();  
  444.       printResetInfo();  
  445.       slient_start=$1;  
  446.       state="listen";  
  447.     }  
  448.   }  
  449. }  
  450.   
  451. END { \  
  452.   if("response"==state)  
  453.     printRoundInfo();  
  454.   if(""!=close_start)  
  455.     printCloseInfo();  
  456.   if(1==need_newline)  
  457.     printf("\n");  
  458. }  

 

fixLenParser.awk源码(这是一个插件,不可独立运行):

[plain] view plain copy

  1. function getHeaderBinLen()  
  2. {  
  3.   #check min length of (Ethernet + IP + TCP) packet header  
  4.   if(length(bin) < 108)  
  5.     return 0;  
  6.   if("08004" == substr(bin,25,5))  
  7.     ethernetHeaderLen=28;  
  8.   else if("08004" == substr(bin,29,5))  
  9.     ethernetHeaderLen=32;  
  10.   else  
  11.   {  
  12.     #unknown ethernet frame packet  
  13.     return -1;  
  14.   }  
  15.   ipHeaderLen = 8 * substr(bin,ethernetHeaderLen+2,1);  
  16.   tcpHeaderLen = 8 * substr(bin,ethernetHeaderLen+ipHeaderLen+25,1);  
  17.   return ethernetHeaderLen + ipHeaderLen + tcpHeaderLen;  
  18. }  
  19.   
  20. function parserInit(pkgBodyLen)  
  21. {  
  22.   maxLen=100;  
  23.   bin="";  
  24.   text="";  
  25.   pkgHeaderBinLen=0;  
  26.   ignore=0;  
  27. }  
  28.   
  29. function parserWork()  
  30. {  
  31.   if(1 == ignore)  
  32.     return;  
  33.   
  34.   for(field=2; field < NF; field++)  
  35.     bin=bin""$field;  
  36.   text=text""$NF;  
  37.     
  38.   if(pkgHeaderBinLen <= 0)  
  39.   {  
  40.     pkgHeaderBinLen=getHeaderBinLen();  
  41.     #print "pkgHeaderBinLen:", pkgHeaderBinLen  
  42.     if(-1 == pkgHeaderBinLen)  
  43.       ignore=1;  
  44.     if(pkgHeaderBinLen <= 0)  
  45.       return;  
  46.   }  
  47.   
  48.   if(length(text) >= pkgHeaderBinLen/2 + maxLen)  
  49.   {  
  50.     print "app_flag", substr(text,pkgHeaderBinLen/2+1, maxLen);  
  51.     ignore=1;  
  52.     return;  
  53.   }  
  54. }  
  55.   
  56. function parserEnd()  
  57. {  
  58.   if(1 == ignore)  
  59.     return;  
  60.   
  61.   print "app_flag", substr(text,pkgHeaderBinLen/2+1);  
  62. }  

 

lineParser.awk源码(这是一个插件,不可独立运行):

[plain] view plain copy

  1. function getHeaderBinLen()  
  2. {  
  3.   #check min length of (Ethernet + IP + TCP) packet header  
  4.   if(length(bin) < 108)  
  5.     return 0;  
  6.   if("08004" == substr(bin,25,5))  
  7.     ethernetHeaderLen=28;  
  8.   else if("08004" == substr(bin,29,5))  
  9.     ethernetHeaderLen=32;  
  10.   else  
  11.   {  
  12.     #unknown ethernet frame packet  
  13.     return -1;  
  14.   }  
  15.   ipHeaderLen = 8 * substr(bin,ethernetHeaderLen+2,1);  
  16.   tcpHeaderLen = 8 * substr(bin,ethernetHeaderLen+ipHeaderLen+25,1);  
  17.   return ethernetHeaderLen + ipHeaderLen + tcpHeaderLen;  
  18. }  
  19.   
  20. function parserInit(pkgBodyLen)  
  21. {  
  22.   maxline=1;  
  23.   bin="";  
  24.   text="";  
  25.   pkgHeaderBinLen=0;  
  26.   lineEndBin="0a";  
  27.   newLineStartInBodyBin0=0;  
  28.   lineCount=0;  
  29.   output="";  
  30.   if(pkgBodyLen < 2)  
  31.     ignore=1;  
  32.   else  
  33.     ignore=0;  
  34. }  
  35.   
  36. function parserWork()  
  37. {  
  38.   if(1 == ignore)  
  39.     return;  
  40.   
  41.   for(field=2; field < NF; field++)  
  42.     bin=bin""$field;  
  43.   text=text""$NF;  
  44.     
  45.   if(pkgHeaderBinLen <= 0)  
  46.   {  
  47.     pkgHeaderBinLen=getHeaderBinLen();  
  48.     #print "pkgHeaderBinLen:", pkgHeaderBinLen  
  49.     if(-1 == pkgHeaderBinLen)  
  50.       ignore=1;  
  51.     if(pkgHeaderBinLen <= 0)  
  52.       return;  
  53.   }  
  54.   
  55.   while(1)  
  56.   {  
  57.     pkgBodyBin=substr(bin,pkgHeaderBinLen+newLineStartInBodyBin0+1);  
  58.     #print "debug:pkgBodyBin", pkgBodyBin;  
  59.     lineEndPos=index(pkgBodyBin,lineEndBin);  
  60.     if(0 == lineEndPos)  
  61.       return;  
  62.     output=output""substr(text,(pkgHeaderBinLen+newLineStartInBodyBin0)/2+1,lineEndPos/2+1);  
  63.     #print "debug:output", output;  
  64.     lineCount++;  
  65.     if(lineCount >= maxline)  
  66.     {  
  67.       print "app_flag", output;  
  68.       ignore=1;  
  69.       return;  
  70.     }  
  71.     newLineStartInBodyBin0+=lineEndPos+1;  
  72.   }  
  73. }  
  74.   
  75. function parserEnd()  
  76. {  
  77.   if(1 == ignore)  
  78.     return;  
  79.   
  80.   output=output""substr(text,(pkgHeaderBinLen+newLineStartInBodyBin0)/2+1);  
  81.   print "app_flag", output;  
  82. }  

 

oracleSqlParser.awk源码(这是一个插件,不可独立运行):

[plain] view plain copy

  1. function getHeaderBinLen()  
  2. {  
  3.   #check min length of (Ethernet + IP + TCP) packet header  
  4.   if(length(bin) < 108)  
  5.     return 0;  
  6.   if("08004" == substr(bin,25,5))  
  7.     ethernetHeaderLen=28;  
  8.   else if("08004" == substr(bin,29,5))  
  9.     ethernetHeaderLen=32;  
  10.   else  
  11.   {  
  12.     #unknown ethernet frame packet  
  13.     return -1;  
  14.   }  
  15.   ipHeaderLen = 8 * substr(bin,ethernetHeaderLen+2,1);  
  16.   tcpHeaderLen = 8 * substr(bin,ethernetHeaderLen+ipHeaderLen+25,1);  
  17.   return ethernetHeaderLen + ipHeaderLen + tcpHeaderLen;  
  18. }  
  19.   
  20. function parserInit(pkgBodyLen)  
  21. {  
  22.   bin="";  
  23.   text="";  
  24.   pkgHeaderBinLen=0;  
  25.   sqlStartInBodyBin0=100;  
  26.   slqEndBin="01010";  
  27.   sql="";  
  28.   foundSqlStart=0;  
  29.   if(pkgBodyLen < sqlStartInBodyBin0/2 + 6)  
  30.     ignore=1;  
  31.   else  
  32.     ignore=0;  
  33. }  
  34.   
  35. function parserWork()  
  36. {  
  37.   if(1 == ignore)  
  38.     return;  
  39.   
  40.   for(field=2; field < NF; field++)  
  41.     bin=bin""$field;  
  42.   text=text""$NF;  
  43.   
  44.   if(pkgHeaderBinLen <= 0)  
  45.   {  
  46.     pkgHeaderBinLen=getHeaderBinLen();  
  47.     #print "pkgHeaderBinLen:", pkgHeaderBinLen  
  48.     if(-1 == pkgHeaderBinLen)  
  49.       ignore=1;  
  50.     if(pkgHeaderBinLen <= 0)  
  51.       return;  
  52.   }  
  53.   
  54.   if(0 == foundSqlStart)  
  55.   {  
  56.     if(length(text) >= (pkgHeaderBinLen+sqlStartInBodyBin0)/2 + 6)  
  57.     {  
  58.       sqlCmd=substr(text,(pkgHeaderBinLen+sqlStartInBodyBin0)/2 + 1,6);  
  59.       if("select" == sqlCmd || "update" == sqlCmd || "delete" == sqlCmd || "create" == sqlCmd)  
  60.         foundSqlStart=1;  
  61.       else  
  62.         ignore=1;  
  63.     }  
  64.   }  
  65.   else  
  66.   {  
  67.     tmpBin=substr(bin,pkgHeaderBinLen+sqlStartInBodyBin0);  
  68.     sqlEndPos=index(tmpBin,slqEndBin);  
  69.     if(sqlEndPos>0)  
  70.     {  
  71.       sql=substr(text,(pkgHeaderBinLen+sqlStartInBodyBin0)/2 + 1,(sqlEndPos - 1)/2);  
  72.       print "app_flag",sql;  
  73.       ignore=1;  
  74.     }  
  75.   }  
  76. }  
  77.   
  78. function parserEnd()  
  79. {  
  80.   if(1 == ignore)  
  81.     return;  
  82.   
  83.   if(1 == foundSqlStart)  
  84.   {  
  85.     sql=substr(text,(pkgHeaderBinLen+sqlStartInBodyBin0)/2 + 1);  
  86.     print "app_flag",sql;  
  87.   }  
  88. }  

httpParser.awk源码(这是一个插件,不可独立运行): 

[plain] view plain copy

  1. function getHeaderBinLen()  
  2. {  
  3.   #check min length of (Ethernet + IP + TCP) packet header  
  4.   if(length(bin) < 108)  
  5.     return 0;  
  6.   if("08004" == substr(bin,25,5))  
  7.     ethernetHeaderLen=28;  
  8.   else if("08004" == substr(bin,29,5))  
  9.     ethernetHeaderLen=32;  
  10.   else  
  11.   {  
  12.     #unknown ethernet frame packet  
  13.     return -1;  
  14.   }  
  15.   ipHeaderLen = 8 * substr(bin,ethernetHeaderLen+2,1);  
  16.   tcpHeaderLen = 8 * substr(bin,ethernetHeaderLen+ipHeaderLen+25,1);  
  17.   return ethernetHeaderLen + ipHeaderLen + tcpHeaderLen;  
  18. }  
  19.   
  20. function parserInit(pkgBodyLen)  
  21. {  
  22.   bin="";  
  23.   text="";  
  24.   pkgHeaderBinLen=0;  
  25.   lineEndBin="0d0a";  
  26.   spaceBin="20";  
  27.   maybeHttpReq="";  
  28.   maybeHttpResponse=0;  
  29.   if(pkgBodyLen < 16)  
  30.     ignore=1;  
  31.   else  
  32.     ignore=0;  
  33. }  
  34.   
  35. function parserWork()  
  36. {  
  37.   if(1 == ignore)  
  38.     return;  
  39.   
  40.   for(field=2; field < NF; field++)  
  41.     bin=bin""$field;  
  42.   text=text""$NF;  
  43.     
  44.   if(pkgHeaderBinLen <= 0)  
  45.   {  
  46.     pkgHeaderBinLen=getHeaderBinLen();  
  47.     #print "pkgHeaderBinLen:", pkgHeaderBinLen  
  48.     if(-1 == pkgHeaderBinLen)  
  49.       ignore=1;  
  50.     if(pkgHeaderBinLen <= 0)  
  51.       return;  
  52.   }  
  53.   
  54.   if("" == maybeHttpReq && 0 == maybeHttpResponse)  
  55.   {  
  56.     if(length(text) >= pkgHeaderBinLen/2 + 9)  
  57.     {  
  58.       tmp_count=split(substr(text,pkgHeaderBinLen/2+1,9),words,".");  
  59.       if(tmp_count <= 1)  
  60.       {  
  61.         ignore = 1;  
  62.         return;  
  63.       }  
  64.   
  65.       if("GET" == words[1] || "POST" == words[1] || "PUT" == words[1] || "DELETE" == words[1] || "OPTIONS" == words[1] || "HEAD" == words[1])  
  66.         maybeHttpReq = words[1];  
  67.       else if(words[1] ~ /^HTTP\//)  
  68.         maybeHttpResponse = 1;  
  69.       else  
  70.       {  
  71.         ignore = 1;  
  72.         return;  
  73.       }  
  74.     }  
  75.     else  
  76.       return;  
  77.   }  
  78.   
  79.   pkgBodyBin=substr(bin,pkgHeaderBinLen+1);  
  80.   lineEndPos=index(pkgBodyBin,lineEndBin);  
  81.   if(0 == lineEndPos)  
  82.     return;  
  83.     
  84.   firstLineBin=substr(pkgBodyBin,1,lineEndPos - 1);  
  85.   firstLineText=substr(text,pkgHeaderBinLen/2+1,lineEndPos/2);  
  86.   #print "debug:pkgBodyBin", pkgBodyBin;  
  87.   #print "debug:firstLineBin", firstLineBin;  
  88.   #print "debug:firstLineText", firstLineText;  
  89.   if("" != maybeHttpReq)  
  90.   {  
  91.     if(3 == split(firstLineBin, a1, spaceBin) && 2 == split(firstLineText, a2, ".HTTP/"))  
  92.       print "app_flag", a2[1];  
  93.     ignore = 1;  
  94.   }  
  95.   else if(1 == maybeHttpResponse)  
  96.   {  
  97.     if(split(firstLineBin, a1, spaceBin) >= 3 && split(firstLineText, a2, ".") >= 4 && a2[3] + 0 >= 100)  
  98.       print "app_flag", substr(firstLineText, length(a1[1])/2 + 2);  
  99.     ignore = 1;  
  100.   }  
  101. }  
  102.   
  103. function parserEnd()  
  104. {  
  105.   if(1 == ignore)  
  106.     return;  
  107.   
  108.   if("" != maybeHttpReq)  
  109.     print "app_flag", substr(text,pkgHeaderBinLen/2+1);  
  110. }  


   

版权声明:本文为博主原创文章,未经博主允许不得转载

linux抓包工具ngrep

阅读数 1268