原创 2016年02月01日 17:49:34
  • /******************************************************************************************
    *              版权声明
    *   本文为本人原创,本人拥有此文的版权。鉴于本人持续受益于开源软件社区,
    * 本人声明:任何个人及团体均可不受限制的转载和复制本文,无论是否用于盈利
    * 之目的,但不得修改文章内容,并必须在转载及复制时同时保留本版权声明,否
    *  则为侵权行为,本人保留追究相应主体法律责任之权利。
    *               speng2005@gmail.com
    *                  2016-1
    ******************************************************************************************/

    大道至简!

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

    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. function parserInit(pkgBodyLen)
    20. {
    21. maxLen=100;
    22. bin="";
    23. text="";
    24. pkgHeaderBinLen=0;
    25. ignore=0;
    26. }
    27. function parserWork()
    28. {
    29. if(1 == ignore)
    30. return;
    31. for(field=2; field < NF; field++)
    32. bin=bin""$field;
    33. text=text""$NF;
    34. if(pkgHeaderBinLen <= 0)
    35. {
    36. pkgHeaderBinLen=getHeaderBinLen();
    37. #print "pkgHeaderBinLen:", pkgHeaderBinLen
    38. if(-1 == pkgHeaderBinLen)
    39. ignore=1;
    40. if(pkgHeaderBinLen <= 0)
    41. return;
    42. }
    43. if(length(text) >= pkgHeaderBinLen/2 + maxLen)
    44. {
    45. print "app_flag", substr(text,pkgHeaderBinLen/2+1, maxLen);
    46. ignore=1;
    47. return;
    48. }
    49. }
    50. function parserEnd()
    51. {
    52. if(1 == ignore)
    53. return;
    54. print "app_flag", substr(text,pkgHeaderBinLen/2+1);
    55. }

    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. function parserInit(pkgBodyLen)
    20. {
    21. maxline=1;
    22. bin="";
    23. text="";
    24. pkgHeaderBinLen=0;
    25. lineEndBin="0a";
    26. newLineStartInBodyBin0=0;
    27. lineCount=0;
    28. output="";
    29. if(pkgBodyLen < 2)
    30. ignore=1;
    31. else
    32. ignore=0;
    33. }
    34. function parserWork()
    35. {
    36. if(1 == ignore)
    37. return;
    38. for(field=2; field < NF; field++)
    39. bin=bin""$field;
    40. text=text""$NF;
    41. if(pkgHeaderBinLen <= 0)
    42. {
    43. pkgHeaderBinLen=getHeaderBinLen();
    44. #print "pkgHeaderBinLen:", pkgHeaderBinLen
    45. if(-1 == pkgHeaderBinLen)
    46. ignore=1;
    47. if(pkgHeaderBinLen <= 0)
    48. return;
    49. }
    50. while(1)
    51. {
    52. pkgBodyBin=substr(bin,pkgHeaderBinLen+newLineStartInBodyBin0+1);
    53. #print "debug:pkgBodyBin", pkgBodyBin;
    54. lineEndPos=index(pkgBodyBin,lineEndBin);
    55. if(0 == lineEndPos)
    56. return;
    57. output=output""substr(text,(pkgHeaderBinLen+newLineStartInBodyBin0)/2+1,lineEndPos/2+1);
    58. #print "debug:output", output;
    59. lineCount++;
    60. if(lineCount >= maxline)
    61. {
    62. print "app_flag", output;
    63. ignore=1;
    64. return;
    65. }
    66. newLineStartInBodyBin0+=lineEndPos+1;
    67. }
    68. }
    69. function parserEnd()
    70. {
    71. if(1 == ignore)
    72. return;
    73. output=output""substr(text,(pkgHeaderBinLen+newLineStartInBodyBin0)/2+1);
    74. print "app_flag", output;
    75. }

    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. function parserInit(pkgBodyLen)
    20. {
    21. bin="";
    22. text="";
    23. pkgHeaderBinLen=0;
    24. sqlStartInBodyBin0=100;
    25. slqEndBin="01010";
    26. sql="";
    27. foundSqlStart=0;
    28. if(pkgBodyLen < sqlStartInBodyBin0/2 + 6)
    29. ignore=1;
    30. else
    31. ignore=0;
    32. }
    33. function parserWork()
    34. {
    35. if(1 == ignore)
    36. return;
    37. for(field=2; field < NF; field++)
    38. bin=bin""$field;
    39. text=text""$NF;
    40. if(pkgHeaderBinLen <= 0)
    41. {
    42. pkgHeaderBinLen=getHeaderBinLen();
    43. #print "pkgHeaderBinLen:", pkgHeaderBinLen
    44. if(-1 == pkgHeaderBinLen)
    45. ignore=1;
    46. if(pkgHeaderBinLen <= 0)
    47. return;
    48. }
    49. if(0 == foundSqlStart)
    50. {
    51. if(length(text) >= (pkgHeaderBinLen+sqlStartInBodyBin0)/2 + 6)
    52. {
    53. sqlCmd=substr(text,(pkgHeaderBinLen+sqlStartInBodyBin0)/2 + 1,6);
    54. if("select" == sqlCmd || "update" == sqlCmd || "delete" == sqlCmd || "create" == sqlCmd)
    55. foundSqlStart=1;
    56. else
    57. ignore=1;
    58. }
    59. }
    60. else
    61. {
    62. tmpBin=substr(bin,pkgHeaderBinLen+sqlStartInBodyBin0);
    63. sqlEndPos=index(tmpBin,slqEndBin);
    64. if(sqlEndPos>0)
    65. {
    66. sql=substr(text,(pkgHeaderBinLen+sqlStartInBodyBin0)/2 + 1,(sqlEndPos - 1)/2);
    67. print "app_flag",sql;
    68. ignore=1;
    69. }
    70. }
    71. }
    72. function parserEnd()
    73. {
    74. if(1 == ignore)
    75. return;
    76. if(1 == foundSqlStart)
    77. {
    78. sql=substr(text,(pkgHeaderBinLen+sqlStartInBodyBin0)/2 + 1);
    79. print "app_flag",sql;
    80. }
    81. }

    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. function parserInit(pkgBodyLen)
    20. {
    21. bin="";
    22. text="";
    23. pkgHeaderBinLen=0;
    24. lineEndBin="0d0a";
    25. spaceBin="20";
    26. maybeHttpReq="";
    27. maybeHttpResponse=0;
    28. if(pkgBodyLen < 16)
    29. ignore=1;
    30. else
    31. ignore=0;
    32. }
    33. function parserWork()
    34. {
    35. if(1 == ignore)
    36. return;
    37. for(field=2; field < NF; field++)
    38. bin=bin""$field;
    39. text=text""$NF;
    40. if(pkgHeaderBinLen <= 0)
    41. {
    42. pkgHeaderBinLen=getHeaderBinLen();
    43. #print "pkgHeaderBinLen:", pkgHeaderBinLen
    44. if(-1 == pkgHeaderBinLen)
    45. ignore=1;
    46. if(pkgHeaderBinLen <= 0)
    47. return;
    48. }
    49. if("" == maybeHttpReq && 0 == maybeHttpResponse)
    50. {
    51. if(length(text) >= pkgHeaderBinLen/2 + 9)
    52. {
    53. tmp_count=split(substr(text,pkgHeaderBinLen/2+1,9),words,".");
    54. if(tmp_count <= 1)
    55. {
    56. ignore = 1;
    57. return;
    58. }
    59. if("GET" == words[1] || "POST" == words[1] || "PUT" == words[1] || "DELETE" == words[1] || "OPTIONS" == words[1] || "HEAD" == words[1])
    60. maybeHttpReq = words[1];
    61. else if(words[1] ~ /^HTTP\//)
    62. maybeHttpResponse = 1;
    63. else
    64. {
    65. ignore = 1;
    66. return;
    67. }
    68. }
    69. else
    70. return;
    71. }
    72. pkgBodyBin=substr(bin,pkgHeaderBinLen+1);
    73. lineEndPos=index(pkgBodyBin,lineEndBin);
    74. if(0 == lineEndPos)
    75. return;
    76. firstLineBin=substr(pkgBodyBin,1,lineEndPos - 1);
    77. firstLineText=substr(text,pkgHeaderBinLen/2+1,lineEndPos/2);
    78. #print "debug:pkgBodyBin", pkgBodyBin;
    79. #print "debug:firstLineBin", firstLineBin;
    80. #print "debug:firstLineText", firstLineText;
    81. if("" != maybeHttpReq)
    82. {
    83. if(3 == split(firstLineBin, a1, spaceBin) && 2 == split(firstLineText, a2, ".HTTP/"))
    84. print "app_flag", a2[1];
    85. ignore = 1;
    86. }
    87. else if(1 == maybeHttpResponse)
    88. {
    89. if(split(firstLineBin, a1, spaceBin) >= 3 && split(firstLineText, a2, ".") >= 4 && a2[3] + 0 >= 100)
    90. print "app_flag", substr(firstLineText, length(a1[1])/2 + 2);
    91. ignore = 1;
    92. }
    93. }
    94. function parserEnd()
    95. {
    96. if(1 == ignore)
    97. return;
    98. if("" != maybeHttpReq)
    99. print "app_flag", substr(text,pkgHeaderBinLen/2+1);
    100. }

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

纯干货:Linux抓包命令集锦相关推荐

  1. 纯干货:Linux抓包命令集锦(tcpdump)

    /****************************************************************************************** * 版权声明 * ...

  2. Linux抓包命令集锦

    相信抓包是程序员,运维工程师,架构师,都必不可少的一项技能.但是能够深入掌握好这门技艺的人,确实需要有开发,网络,运维,架构等"跨界"背景才能比较好的发挥抓包神技的威力.本文是纯干 ...

  3. linux抓网卡数据包命令,Linux抓包命令tcpdump命令图解

    原标题:Linux抓包命令tcpdump命令图解 tcpdump命令-->用来将网络中传送的数据包的"头"完全截获下来提供分析,常见的有Wireshark.在Linux中输入 ...

  4. linux抓包命令tcptrace,每天学习一个命令:tcpdump 命令行下抓包

    tcpdump 是一个运行在命令行下的抓包工具,如果想知道网络中有什么在流通,那么 tcpdump 就是一个很好的工具.它允许用户拦截和显示发送或收到过程中网络连接到该计算机的 TCP/IP 和其他数 ...

  5. linux抓包命令到文件,Linux下抓包命令tcpdump详解

    tcpdump是一个命令行实用程序,可用于捕获和检查进出系统的网络流量. 它是网络管理员中用于排除网络问题和安全测试的最常用工具. 尽管名称如此,使用tcpdump,您也可以捕获非TCP流量,例如UD ...

  6. linux 抓包命令

    tcpdump -s 0 -i any port 7711 -w /opt/yxt/7711-316.cap 7711 监听的端口号 7711-316.cap 生成的文件

  7. linux下最全抓包命令使用方式学习和拓展

    为什么要抓包?抓包有什么作用? 抓包的好处: 1,分析出当前服务器存在的漏洞,接口参数,防盗链,流量工具,ip伪造,参数篡改,钓鱼网站等. 抓包的作用:端到端联调,包括不限制语言的参数请求,只要走up ...

  8. linux tcpdump抓包命令使用详解

    一.抓包命令概述 作用:(1)捕获网络协议包  (2)分析网络协议包 分类:(1)linux命令行工具,如tcpdump(2)windows图像界面工具,wireshark  (3)手机抓包工具,Fi ...

  9. Linux上的抓包命令

    命令:tcpdump -i em1 port 端口(2775) -vv -w 包名(aa1.cap) PS:tcpdump是一个用于截取网络分组,并输出分组内容的工具,简单说就是数据包抓包工具.tcp ...

  10. tcpdump linux服务器抓包命令

    linux服务器 抓包命令 tcpdump tcpdump -i any -s0 -w /home/tcp.pcap 单独总结tcpdump抓包的常用命令 主要语法 过滤主机/IP: tcpdump ...

最新文章

  1. 启动mysqld报 mysql the server quit without updating pid file
  2. SQLite 入门教程(四)增删改查,有讲究
  3. 直播中那几秒延时到底来自哪?
  4. 计算机系答辩麻烦,计算机专业的你,答辩时有多卑微?
  5. 陌屿授权系统V2.0全解
  6. jquery可拖拽式内容模块gridder
  7. GNU Assembler
  8. java+selnium爬取凡人修仙传
  9. 靖哥哥教你一步一步搭建redis集群环境
  10. Linux常用指令<三>
  11. 发现一个非常好用的编程字体 看起来非常舒服 - Tahoma
  12. 2021美食林全球餐厅精选榜公布,这里有一份美食地图请查收!
  13. 牛客网C语言编程初学者入门训练135题
  14. 网易免费企业邮箱的SMTP、POP服务地址和端口
  15. 百度地图配合java 代码制作地图
  16. 现代通信网复习资料(第一章:绪 论)
  17. python实现循环注册登录_Python入门案例-用户注册和登录
  18. 第10章第1节:iSlide的安装并使用iSlide统一演示文稿中的字体 [PowerPoint精美幻灯片实战教程]
  19. vsftpd配置多用户登陆的方法
  20. maven项目如何打包运行指定java程序(maven-shade-plugin插件的使用)

热门文章

  1. 实现省市县的两种方式
  2. 用计算机弹音乐的歌谱《奇迹再现》,奇迹再现曲谱_奇迹再现的歌谱
  3. 43.Django04
  4. 复合函数的极限与连续
  5. Vue学习(学习打卡Day12)
  6. gets和puts函数
  7. 家庭局域网_如何用电视盒子局域网共享电脑资源,赶紧Mark!
  8. 抢先体验 八九月间漫步最初秋色
  9. APPstore上架问题 ERROR ITMS-90096
  10. Poetry of Today3--琵琶行