tcplstat網(wǎng)絡(luò)監(jiān)控工具
tcplstat是基于libpcap網(wǎng)絡(luò)嗅探程序包的網(wǎng)絡(luò)監(jiān)控工具,它能旁路捕獲所有經(jīng)過(guò)網(wǎng)絡(luò)設(shè)備過(guò)濾規(guī)則的TCP數(shù)據(jù),跟蹤當(dāng)前所有TCP連接會(huì)話,記錄所有經(jīng)過(guò)的TCP分組,當(dāng)連接斷開(kāi)或到達(dá)最大記錄數(shù)時(shí)倒出統(tǒng)計(jì)信息,包含但不限于連接兩端網(wǎng)絡(luò)地址、建立時(shí)間戳、三步握手各分組延遲、四步分手各分組延遲,數(shù)據(jù)分組明細(xì)、往來(lái)分組間延遲和相反方向分組延遲的最小、平均、最大統(tǒng)計(jì)值。
tcplstat在旁路工作,所以不會(huì)對(duì)應(yīng)用造成任何影響,也無(wú)需侵入應(yīng)用,即可獲得網(wǎng)絡(luò)數(shù)據(jù)往來(lái)分組明細(xì)和統(tǒng)計(jì)信息。
tcplstat在實(shí)現(xiàn)基礎(chǔ)網(wǎng)絡(luò)監(jiān)控功能時(shí)還實(shí)現(xiàn)了采集分析SQL耗時(shí)和HTTP耗時(shí)信息,同樣也是旁路捕獲,不影響應(yīng)用也無(wú)需改造應(yīng)用,幫助應(yīng)用優(yōu)化性能。
tcplstat是開(kāi)源的,除了引用了Linux內(nèi)核的紅黑樹(shù)和鏈表源碼外,自身源碼只有1500行左右,源碼結(jié)構(gòu)簡(jiǎn)單易讀。
安裝
(理論上tcplstat可以安裝在任何有l(wèi)ibpcap的環(huán)境,包括Linux、WINDOWS、AIX等,以下以Linux操作系統(tǒng)為例)
2.1. 源碼編譯安裝
從tcplstat源碼托管站點(diǎn)(網(wǎng)址在最后)下載最新源碼包,解開(kāi)并進(jìn)入源碼目錄
$ tar xvzf tcplstat.tar.gz ... ¥ cd tcplstat/src
按需修改安裝目錄
$ vi makeinstall _BINBASE = $(HOME)/bin
注意:編譯環(huán)境需要開(kāi)發(fā)包libpcap-devel,請(qǐng)預(yù)先安裝好。
編譯、安裝tcplstat
$ make -f makefile.Linux gcc -g -fPIC -O2 -Wall -Werror -fno-strict-aliasing -I/home/calvin/include -I. -I/home/calvin/include -c list.c gcc -g -fPIC -O2 -Wall -Werror -fno-strict-aliasing -I/home/calvin/include -I. -I/home/calvin/include -c rbtree.c gcc -g -fPIC -O2 -Wall -Werror -fno-strict-aliasing -I/home/calvin/include -I. -I/home/calvin/include -c rbtree_ins.c gcc -g -fPIC -O2 -Wall -Werror -fno-strict-aliasing -I/home/calvin/include -I. -I/home/calvin/include -c Util.c gcc -g -fPIC -O2 -Wall -Werror -fno-strict-aliasing -I/home/calvin/include -I. -I/home/calvin/include -c main.c gcc -g -fPIC -O2 -Wall -Werror -fno-strict-aliasing -I/home/calvin/include -I. -I/home/calvin/include -c PcapCallback.c gcc -g -fPIC -O2 -Wall -Werror -fno-strict-aliasing -I/home/calvin/include -I. -I/home/calvin/include -c ProcessTcpPacket.c gcc -g -fPIC -O2 -Wall -Werror -fno-strict-aliasing -I/home/calvin/include -I. -I/home/calvin/include -c AddTcpPacket.c gcc -g -fPIC -O2 -Wall -Werror -fno-strict-aliasing -I/home/calvin/include -I. -I/home/calvin/include -c OutputTcplSession.c gcc -g -fPIC -O2 -Wall -Werror -fno-strict-aliasing -o tcplstat list.o rbtree.o rbtree_ins.o Util.o main.o PcapCallback.o ProcessTcpPacket.o AddTcpPacket.o OutputTcplSession.o -L/home/calvin/lib -L. -L/home/calvin/lib -lpcap $ make -f makefile.Linux install cp -rf tcplstat /home/calvin/bin/
編譯鏈接只產(chǎn)生了一個(gè)可執(zhí)行程序tcplstat,也可自行復(fù)制到目標(biāo)目錄。
顯示版本信息
$ tcplstat -v tcplstat v0.5.0 build Feb 6 2018 22:40:44 copyright by calvin<[email protected]> 2018
使用
命令行參數(shù)說(shuō)明
不帶命令行參數(shù)執(zhí)行顯示所有命令行參數(shù)
$ tcplstat USAGE : tcplstat -v -l [ -i (network_interface) ] [ -f (filter_string) ] [ -o [ESPDd] ] [ --sql ] [ --http ] [ --max-packet-trace-count ] [ --log-file (pathfilename) ] -o E : Output EVENT S : Output SESSION P : Output PACKET D : Output PACKET DATA d : Output DEBUG --sql : Output SQL time elapse NOTICE : See pcap-filter(7) for the syntax of filter
-
-i設(shè)置網(wǎng)絡(luò)設(shè)備接口,不設(shè)置則默認(rèn)使用any -
-f設(shè)置網(wǎng)絡(luò)過(guò)濾規(guī)則,比如tcp port 445嗅探所有連接到端口445的往來(lái)TCP分組,具體參見(jiàn)pcap-filter(7) -
-o一旦捕獲到TCP分組,輸出數(shù)據(jù)類(lèi)型,E表示輸出分組事件,S表示連接斷開(kāi)輸出會(huì)話統(tǒng)計(jì)信息,P表示連接斷開(kāi)輸出TCP分組統(tǒng)計(jì)信息,D表示連接斷開(kāi)輸出TCP分組數(shù)據(jù)信息,d表示輸出調(diào)試信息 -
--sql捕獲SQL統(tǒng)計(jì)耗時(shí)信息 -
--http捕獲HTTP統(tǒng)計(jì)耗時(shí)信息 -
--max-packet-trace-count針對(duì)長(zhǎng)連接不釋放,總是不能偵測(cè)到連接斷開(kāi)也就不能輸出會(huì)話總結(jié)信息,該選項(xiàng)設(shè)置TCP分組累積到多少時(shí)強(qiáng)制輸出并清空TCP分組明細(xì)信息,默認(rèn)為1000,下次輸出會(huì)話統(tǒng)計(jì)信息時(shí)前綴從'E |'變成'E -' -
--log-file輸出到日志文件,不設(shè)置文件則輸出到屏幕
注意:執(zhí)行tcplstat需要root權(quán)限。
一個(gè)示例(即時(shí)輸出TCP分組事件)
第一屏運(yùn)行tcplstat
# tcplstat -f "tcp port 445" -o E
第二屏向445端口發(fā)送一個(gè)字符串,然后被samba服務(wù)器無(wú)情強(qiáng)行斷開(kāi)
$ echo "hello" | nc 114.215.179.129 445
第一屏輸出
E | 2018-02-07T20:09:21.249992 | LHT[113] | SMAC[] DMAC[] | SIP[114.215.179.129] DIP[114.215.179.129] | SPORT[44200] DPORT[445] SEQ[3750544418] ACKSEQ[0] SYN[1] ACK[0] FIN[0] PSH[0] RST[0] URG[0] | [0]BYTES E | 2018-02-07T20:09:21.250004 | LHT[113] | SMAC[] DMAC[] | SIP[114.215.179.129] DIP[114.215.179.129] | SPORT[445] DPORT[44200] SEQ[974809372] ACKSEQ[3767321634] SYN[1] ACK[1] FIN[0] PSH[0] RST[0] URG[0] | [0]BYTES E | 2018-02-07T20:09:21.250018 | LHT[113] | SMAC[] DMAC[] | SIP[114.215.179.129] DIP[114.215.179.129] | SPORT[44200] DPORT[445] SEQ[3767321634] ACKSEQ[991586588] SYN[0] ACK[1] FIN[0] PSH[0] RST[0] URG[0] | [0]BYTES E | 2018-02-07T20:09:21.251501 | LHT[113] | SMAC[] DMAC[] | SIP[114.215.179.129] DIP[114.215.179.129] | SPORT[44200] DPORT[445] SEQ[3767321634] ACKSEQ[991586588] SYN[0] ACK[1] FIN[0] PSH[1] RST[0] URG[0] | [6]BYTES E | 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF E | 0x00000000 68 65 6C 6C 6F 0A hello. E | 2018-02-07T20:09:21.251507 | LHT[113] | SMAC[] DMAC[] | SIP[114.215.179.129] DIP[114.215.179.129] | SPORT[445] DPORT[44200] SEQ[991586588] ACKSEQ[3867984930] SYN[0] ACK[1] FIN[0] PSH[0] RST[0] URG[0] | [0]BYTES E | 2018-02-07T20:09:21.251661 | LHT[113] | SMAC[] DMAC[] | SIP[114.215.179.129] DIP[114.215.179.129] | SPORT[44200] DPORT[445] SEQ[3867984930] ACKSEQ[991586588] SYN[0] ACK[1] FIN[1] PSH[0] RST[0] URG[0] | [0]BYTES E | 2018-02-07T20:09:21.256246 | LHT[113] | SMAC[] DMAC[] | SIP[114.215.179.129] DIP[114.215.179.129] | SPORT[445] DPORT[44200] SEQ[991586588] ACKSEQ[3884762146] SYN[0] ACK[1] FIN[1] PSH[0] RST[0] URG[0] | [0]BYTES E | 2018-02-07T20:09:21.256267 | LHT[113] | SMAC[] DMAC[] | SIP[114.215.179.129] DIP[114.215.179.129] | SPORT[44200] DPORT[445] SEQ[3884762146] ACKSEQ[1008363804] SYN[0] ACK[1] FIN[0] PSH[0] RST[0] URG[0] | [0]BYTES ...
E開(kāi)頭的行為一個(gè)TCP分組,各列分別是發(fā)生時(shí)間戳、鏈路層頭結(jié)構(gòu)、發(fā)送方MAC、接收方MAC、發(fā)送方IP、接收方IP、發(fā)送方PORT、接收方PORT、序列號(hào)、反饋序列號(hào)、分組類(lèi)型標(biāo)志集合、有效荷載數(shù)據(jù)長(zhǎng)度。
另一個(gè)示例(短連接斷開(kāi)后輸出統(tǒng)計(jì)信息)
第一屏運(yùn)行tcplstat
# tcplstat -f "tcp port 445" -o SPD
第二屏向445端口發(fā)送一個(gè)字符串,然后被samba服務(wù)器無(wú)情強(qiáng)行斷開(kāi)
$ echo "hello" | nc 114.215.179.129 445
第一屏輸出
S | [114.215.179.129:44205]->[114.215.179.129:445] | 2018-02-07T20:20:41.903338 | 0.016535 | 0.000016 0.000015 , 0.000006 0.000741 0.001477 0.000006 0.000749 0.001492 , 0.000036 0.014964 0.000021 | 2 6 P | 2018-02-07T20:20:41.903338 | 0.000000 0.000000 | [114.215.179.129:44205]->[114.215.179.129:445] | S..... 0 P | 2018-02-07T20:20:41.903354 | 0.000016 0.000016 | [114.215.179.129:44205]<-[114.215.179.129:445] | S..A.. 0 P | 2018-02-07T20:20:41.903369 | 0.000015 0.000015 | [114.215.179.129:44205]->[114.215.179.129:445] | ...A.. 0 P | 2018-02-07T20:20:41.904846 | 0.001477 0.001492 | [114.215.179.129:44205]->[114.215.179.129:445] | ..PA.. 6 D | 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF D | 0x00000000 68 65 6C 6C 6F 0A hello. P | 2018-02-07T20:20:41.904852 | 0.000006 0.000006 | [114.215.179.129:44205]<-[114.215.179.129:445] | ...A.. 0 P | 2018-02-07T20:20:41.904888 | 0.000036 0.000036 | [114.215.179.129:44205]->[114.215.179.129:445] | .F.A.. 0 P | 2018-02-07T20:20:41.919852 | 0.014964 0.014964 | [114.215.179.129:44205]<-[114.215.179.129:445] | .F.A.. 0 P | 2018-02-07T20:20:41.919873 | 0.000021 0.000021 | [114.215.179.129:44205]->[114.215.179.129:445] | ...A.. 0 ...
S開(kāi)頭的行為一個(gè)連接統(tǒng)計(jì)信息,各列分別是連接方地址、被連接方地址、建立連接時(shí)間戳、連接總存在時(shí)間、三步握手各分組延遲、四步分手各分組延遲、往來(lái)分組間延遲和相反方向分組延遲的最小、平均、最大統(tǒng)計(jì)值,總分組數(shù),有效載荷數(shù)據(jù)總大小。
P開(kāi)頭的行為一個(gè)連接中的一個(gè)TCP分組統(tǒng)計(jì)信息,各列分別是分組發(fā)生時(shí)間戳、往來(lái)分組間延遲和相反方向分組延遲、連接方地址、分組發(fā)送方向、被連接方地址、分組類(lèi)型標(biāo)志集合、有效荷載數(shù)據(jù)長(zhǎng)度。
可以看出,自己想獲得什么樣的數(shù)據(jù),就組合命令行參數(shù)-o后面的字母集合即可,最詳細(xì)的信息參數(shù)組合是ESPDd
再一個(gè)示例(采集統(tǒng)計(jì)SQL耗時(shí))
捕獲SQL的原理很簡(jiǎn)單,檢查每一個(gè)TCP分組中是否存在SQL語(yǔ)句,如果有則做個(gè)標(biāo)記,等待下一個(gè)有效載荷的反向TCP分組到來(lái)后,計(jì)算時(shí)間差即是SQL執(zhí)行時(shí)間。
這里以PostgreSQL為例,MySQL、Oracle等同樣有效。
第一屏運(yùn)行tcplstat
# tcplstat -f "tcp port 8432" --sql
第二屏用psql打開(kāi)數(shù)據(jù)庫(kù)連接,查詢(xún)所有表總記錄數(shù)
calvin=# \d 關(guān)聯(lián)列表 架構(gòu)模式 | 名稱(chēng) | 型別 | 擁有者 ----------+------------------------------------------+--------+-------- public | alphastock_company_info | 資料表 | calvin public | alphastock_company_ipo | 資料表 | calvin public | alphastock_stock_code | 資料表 | calvin public | alphastock_stock_kline | 資料表 | calvin public | alphastock_stock_kline_max_closing_price | 資料表 | calvin public | financing_chinawealth | 資料表 | calvin public | whoispider_domain | 資料表 | calvin (7 行記錄) calvin=# select count(*) from alphastock_company_info; count ------- 3596 (1 行記錄) calvin=# select count(*) from alphastock_company_ipo ; count ------- 3596 (1 行記錄) calvin=# select count(*) from alphastock_stock_code ; count ------- 3596 (1 行記錄) calvin=# select count(*) from alphastock_stock_kline ; count --------- 8826375 (1 行記錄) calvin=# select count(*) from financing_chinawealth ; calvin-# ; count -------- 168148 (1 行記錄)
第一屏輸出
Q | 2018-02-07T20:28:07.978745 0.000869 | select count(*) from alphastock_company_info; Q | 2018-02-07T20:28:10.427744 0.000605 | select count(*) from alphastock_company_ipo ; Q | 2018-02-07T20:28:12.923744 0.000737 | select count(*) from alphastock_stock_code ; Q | 2018-02-07T20:28:15.291747 42.884759 | select count(*) from alphastock_stock_kline ; Q | 2018-02-07T20:29:35.218747 3.505407 | select count(*) from financing_chinawealth ; ...
Q開(kāi)頭的行為一條SQL耗時(shí)統(tǒng)計(jì),各列是開(kāi)始執(zhí)行時(shí)間戳、執(zhí)行耗時(shí)、SQL語(yǔ)句。
可以看到表alphastock_stock_kline很大,SQLselect count(*) from alphastock_stock_kline花了42秒,表alphastock_company_ipo很小,SQLselect count(*) from alphastock_company_ipo花了0.6毫秒。
整個(gè)采集統(tǒng)計(jì)過(guò)程完全以旁路方式進(jìn)行,不影響應(yīng)用也無(wú)需侵入應(yīng)用。
最后
歡迎使用tcplstat,如果你使用中碰到了問(wèn)題請(qǐng)告訴我,謝謝 ^_^
源碼托管地址 : 開(kāi)源中國(guó)、github
