自由轉載 ^_^ 同時請注明原文出處:http://www.cnblogs.com/wangvsa/archive/2012/07/16/2593551.html
tcpdump - dump traffic on a network
問題:基於ip統計流量。
硬件:學校集群
難點:
1.當使用高速網卡(千兆或IB)並且網卡滿負荷時丟包率如何
2.程序的cpu占用率如何
3.日志文件過大
方案及分析:
1.抓包的實現方式有多種,如用libpcap庫、采用零拷貝方式、使用PF_RING接口、直接使用系統函數
我看了一些文章並測試了netsniff-ng程序(基於零拷貝),我認為零拷貝方式效率最高,丟包率最低。但是我
測試tcpdump時發現其效率也較高(測試時網卡幾乎滿負荷),並且幾乎沒有丟包,又由於其方便使用等其他
因素最終選用tcpdump。
2.測試tcpdump抓包時cpu占用率4%左右
3.tcpdump由於記錄每個數據包,雖然我們可以限制每個包記錄的字節數(-s選項),但是由於網卡滿負荷,
所以包的數量格外大。 如下,60秒已經抓到748168個包,導致pcap文件也格外大
Number of packets: 748168 File size: 58394582 bytes Data size: 3900660165 bytes Capture duration: 59.963470 seconds
因此,我使用-G選項每分鍾記錄一個pcap文件然后自己統計刪減其中數據,最后刪掉該pcap文件。即每分鍾
生成一個如下的文件(時間間隔可以根據需要改)
File name: /public/home/wangvsa/software/tcp-audit/2012-07-16,12:54:54.pcap File encapsulation: Ethernet Number of packets: 748168 File size: 58394582 bytes Data size: 3900660165 bytes Capture duration: 59.963470 seconds Start time: Mon Jul 16 12:54:53 2012 End time: Mon Jul 16 12:55:53 2012 Data rate: 65050607.75 bytes/s Data rate: 520404861.98 bits/s IPv4 total packet: 748037 source ip port dir dest ip port proto flow 10. 10. 10. 61: 9090 > 10. 10. 10. 49: 27884 tcp 1793 0. 0. 0. 0: 68 > 255.255.255.255: 67 UDP 5310 10. 10. 10. 49: - > 10. 10. 10. 62: - ICMP 234 10. 10. 10. 49: 22 > 10. 10. 10. 61: 47051 tcp 117124 10. 10. 10. 48: 38906 > 10. 10. 10. 49: 16797 tcp 44288974 10. 10. 10. 48: 64468 > 10. 10. 10. 49: 45094 tcp 171 10. 10. 10. 61: 47051 > 10. 10. 10. 49: 22 tcp 5406 10. 10. 10. 49: 27884 > 10. 10. 10. 61: 9090 tcp 2112 10. 10. 10. 49: 45094 > 10. 10. 10. 48: 64468 tcp 108 10. 10. 10. 62: - > 10. 10. 10. 49: - ICMP 234 10. 10. 10. 49: 16797 > 10. 10. 10. 48: 38906 tcp 3856230180
具體實現:
1.編寫針對pcap文件的統計腳本(如果對效率要求高可以寫成c語言程序),共兩個文件tcp-audit.sh 和
tcp-reduce.sh。在tcp-audit.sh中調用了tcp-reduce.sh,自己不要直接調用。
先看tcp-audit.sh,這個文件從ready.txt中讀取內容,每一行都是一個要統計的pcap文件的文件名,稍后
討論如何得到的ready.txt文件。
1 #!/bin/bash 2 # tcp-audit.sh 3 # 讀取ready.txt文件,每次讀取一行 4 # 將其內容作為參數傳給tcp-reduce.sh 5 # 執行完后刪除該行 6 7 DIR="/home/wangchen/shell_ex/" 8 9 while read line 10 do 11 # tcp-reduce.sh處理 12 $DIR/tcp-reduce.sh ${line} 13 # 刪除該pcap文件 14 rm $DIR/${line} 15 # 刪除該行 16 sed -i '1d' $DIR/ready.txt 17 done < $DIR/ready.txt
再看tcp-reduce.sh,這個腳本完成了所有的統計操作並且輸出到日志文件中。這個腳本中使用了grep和sed命令
來格式話pcap文件的輸出方便之后awk程序的使用。還是用了capinfos這個程序提供的一些分析數據。
注:tcpdump 和 capinfos 版本不同,其參數選項要注意修改。如capinfos 的-x在舊版本中是用-i
1 #!/bin/bash 2 # tcp-reduce.sh 3 DIR="/home/wangchen/shell_ex" 4 5 # 根據pcap文件名構造出日志文件名(以時間命名) 6 tmp1=$* 7 tmp2=(${tmp1//./ }) 8 LOG_FILE_NAME=${tmp2[0]}".log" 9 10 # 輸出文件信息,即網卡信息 11 capinfos -a -c -d -e -E -s -u -x -y $DIR/$* >> $DIR/$LOG_FILE_NAME 12 13 # 將tcpdump文件生成可讀文本 14 # 由grep,sed執行過濾、替換處理后交給awk 15 # 使用awk語言處理數據行,統計基於ip的流量信息 16 tcpdump -q -n -e -t -r $DIR/$* \ 17 | grep "IPv4" | sed 's/,/ /g; s/>/ /g; s/://g' \ 18 | awk ' 19 20 BEGIN { 21 printf("\n") 22 } 23 { 24 # $5:packet length 25 # $6:source ip.port 26 # $7:destination ip.port 27 # $8:proto 28 29 # array_flow是數組記錄每個方向的流量 30 # 其下標是數據傳輸方向(字符串) 31 32 count++ 33 way = $6"."$7"."$8 34 for(x in arr_total_flow) 35 { 36 if(way==x) 37 { 38 arr_total_flow[way] += $5 39 next 40 } 41 } 42 arr_total_flow[way] = $5 43 } 44 45 END { 46 printf("\nIPv4 total packet: %d\n",NR) 47 printf("%16s%6s%6s%19s%6s\tproto\tflow\n","source ip","port","dir","dest ip","port") 48 for(x in arr_total_flow) 49 { 50 # 格式化輸出 51 split(x,chunks,".") 52 if(chunks[9]=="ICMP") 53 { 54 printf("%3s.%3s.%3s.%3s:%6s > %3s.%3s.%3s.%3s:%6s\t%s\t%d\n", 55 chunks[1],chunks[2],chunks[3],chunks[4],"-", # 源地址 : 端口 56 chunks[5],chunks[6],chunks[7],chunks[8],"-", # 目的地址 : 端口 57 chunks[9],arr_total_flow[x]) # 協議 總流量 58 } 59 else 60 { 61 printf("%3s.%3s.%3s.%3s:%6s > %3s.%3s.%3s.%3s:%6s\t%s\t%d\n", 62 chunks[1],chunks[2],chunks[3],chunks[4],chunks[5], # 源地址 : 端口 63 chunks[6],chunks[7],chunks[8],chunks[9],chunks[10], # 目的地址 : 端口 64 chunks[11],arr_total_flow[x]) # 協議 總流量 65 } 66 } 67 } 68 ' >> $DIR/$LOG_FILE_NAME
2.接下來就是如何運行的問題,首先用root權限執行tcpdump抓包程序,我使用的命令如下:
sudo cpdump -i eth3 -s 84 -G 60 -z ./tcp-add.sh -w %F,%T.pcap
參數分析:-i eth3 在eth3上抓包; -s 84每個包最多記錄84字節; -G 60 每60秒就在打開一個文件記錄;
-z ./tcp-add.sh配合-G使用,每次記錄完一個文件后執行./tcp-add.sh腳本(后面講這個腳本)
-w %F,%T.pcap 輸出,文件名有時間組成%F表示年月日,%T表示時分秒,如2012-07-16,12:54:54.pcap
再來看這個tcp-add.sh,這個腳本十分簡單,實際就是將剛才的記錄完的pcap文件名寫到ready.txt文件中。
1 #!/bin/bash 2 # 作為tcpdump的-z參數使用 3 # 將已經存儲完的pcap文件名加入ready.txt等待處理 4 5 echo $* >> ready.txt
這樣就會每分鍾生成一個pcap文件,並將其文件名寫到ready.txt文件中。
3.下面就要用到cron來定時執行我們的統計任務。在開啟crond服務后執行如下命令
1 sudo crontab -e
此命令打開一個文件,在最后一行加入如下,之后保存退出
1 */2 * * * * /home/wangchen/shell_ex/tcp-audit.sh
這一條表示每兩分鍾(時間隨意定)執行一次tcp-audit.sh腳本。
到此功能就基本實現,在集群中實測可行。
當然以上方案僅僅是一個我在實驗室的一個練習,肯定有很多的不足,希望高手能不惜賜教。