天天看點

Linux程序網絡流量統計方法及實作1 前言2 基礎資料3 實作流程4 總結

1 前言

在某些應用安全場景需要結合程序級網絡連接配接、流入流出流量等資料直接分析出程序的異常。例如,在内網主機上是否存在持續惡意外傳敏感資料的現象、在網絡監控時發現伺服器大量帶寬被占用但不清楚由系統具體哪個程序占用。為此都需要擷取更細粒度的程序級網絡流量資料直接鎖定異常服務。

在Linux系統中都有相應開源工具采集網絡連接配接、程序、流量等資訊,像netstat指令檢視主機網絡連接配接資訊,一般包括最基本的五元組資訊(源位址、目标位址、源端口、目标端口、協定号);ps指令采集程序資訊,包括pid, user, exe, cmdline等;iftop指令擷取網卡的實時流量資料。

同時在linux /proc目錄下可直接讀取主機級網絡流量資料,例如/proc/net/snmp提供了主機各層IP、ICMP、ICMPMsg、TCP、UDP詳細資料,/proc/net/netstat檔案InBcastPkts、 OutBcastPkts、InOctets、OutOctets字段能擷取主機的收發包數、收包位元組資料。

但很可惜沒有一個細粒度程序級流入流出網絡流量資料。為此,本文旨在分享實作一種統計Linux程序級網絡流量方式。

2 基礎資料

涉及linux /proc目錄下網絡狀态檔案/proc/net/tcp、/proc/net/udp,程序檔案描述符目錄/proc/pid/fd。

2.1 網絡狀态檔案

以tcp的狀态檔案為例/proc/net/tcp:

sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode
6: 0100007F:22B8 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 623457565 1 ffff88004f918740 750 0 0 2 -1
           

重點關注網絡連接配接五元組+連接配接狀态+inode号,分别在第2、3(local_address)、4(st)、11列(inode)。

第2、3列分别是主機位元組序ip:port ,例如"0100007F:22B8" -> “10.93.122.33:8888”

第4列是網絡連接配接狀态資訊,狀态字段含義如下:

"01": "ESTABLISHED",
"02": "SYN_SENT",
"03": "SYN_RECV",
"04": "FIN_WAIT1",
"05": "FIN_WAIT2",
"06": "TIME_WAIT",
"07": "CLOSE",
"08": "CLOSE_WAIT",
"09": "LAST_ACK",
"0A": "LISTEN",
"0B": "CLOSING"
           

常見網絡狀态如0A,01 分别代表某程序正監聽和已建立連接配接狀态。

第11列是inode号,代表Linux系統中的一個檔案系統對象包括檔案、目錄、裝置檔案、socket、管道等的元資訊。如圖中623457565是某程序監聽socket(狀态0A)的inode号。

2.2 程序檔案描述符

/proc/pid/fd目錄是程序所有打開的檔案資訊,其中0、1、2表示标準輸入、輸出、錯誤,網絡連接配接是以socket:開頭的檔案描述符,其中[]号内的是socket對應inode号,這樣可以和網絡狀态檔案/proc/net/tcp下的inode号可對應起來。

以pid:30168程序為例,該程序監聽8888(0x22B8)端口,在/proc/30168/fd目錄下顯示檔案描述符是3、5代表的是sokcet連接配接,對應inode号分别是623457565、623457729。

ls -l /proc/30168/fd

lrwx------ 1 root root 64 Oct 30 10:46 0 -> /dev/pts/0
lrwx------ 1 root root 64 Oct 30 10:47 1 -> /dev/pts/0
lrwx------ 1 root root 64 Oct 30 10:46 2 -> /dev/pts/0
lrwx------ 1 root root 64 Oct 30 10:47 3 -> socket:[623457565]
lrwx------ 1 root root 64 Oct 30 10:47 4 -> anon_inode:[eventpoll]
lrwx------ 1 root root 64 Oct 30 10:48 5 -> socket:[623457729]
           

再從/proc/net/tcp過濾22B8,可以發現有兩條記錄,狀态分别為"0A",“01”,inode号是623457565, 623457729,與前面30168程序fd目錄下的inode号一緻,就可找到這連接配接歸屬的程序。

cat /proc/net/tcp |grep 22B8

6: 00000000:22B8 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 623457565 1 ffff8811f2fd1740 100 0 0 10 0
13: 0100007F:22B8 0100007F:ED2C 01 00000000:00000000 00:00000000 00000000     0        0 623457729 1 ffff8810880e1740 20 4 30 10 -1
           

根據上述檔案資訊可以從/proc/net/tcp建立起網絡連接配接五元組->inode的映射, 再從/proc/pid/fd建立起連接配接inode ->程序的映射。

這樣通過inode号作為橋梁關聯起系統内的程序與網絡連接配接的資訊。

3 實作流程

為了實時擷取網絡連接配接流量在linux主機上使用開源libpcap庫來抓取網絡封包。

整個實作流程圖如下包含以下5個關鍵步驟。

Linux程式網絡流量統計方法及實作1 前言2 基礎資料3 實作流程4 總結
  1. 抓包

    使用抓包Libpcap庫擷取到網絡封包packet結構。

  2. 解析封包

    解析出packet的五元組(源位址、目标位址、源端口、目标端口、協定号)資訊和目前封包的流量大小。

  3. 緩存更新

    在ConnInodeHash緩存查找五元組組成的key對應的inode号,如果不存在,重新讀取/proc/net/tcp與udp,重新整理ConnInodeHash緩存,建立起新連接配接與inode的映射; 并重新讀取/proc/pid/fd目錄對所有檔案描述符周遊,過濾出以socket:開頭的連接配接,重新整理InodeProcessHash緩存,重建立立inode與程序的映射。

  4. hash查找

    根據查找到inode号在InodeProcessHash緩存查找相應程序pid。

  5. 統計流量

    根據封包位址,判斷目前連接配接方向,累加程序流入、流出資料。

4 總結

通過對Linux主機抓包,結合網絡狀态檔案、程序檔案描述符實作一種細粒度的程序級網絡流量采集方式。利用Linux檔案inode号作為橋梁,關聯出程序、網絡連接配接的映射關系。

本文的實作方式可以按程序次元統計接收/發送的總量/平均值等各次元資料,也可以擴充按網絡連接配接次元統計流量資料,這些在主機流量安全分析、網絡監控排查等場景方面可作為重要依據。

本文介紹的流量統計方式是一種通用的實作方式,但持續使用libpcap抓包對主機性能有較明顯損耗; 滴滴雲的主機安全團隊研發了一種更高效的實作方式,主機上服務無任何感覺能力,目前已在數萬台主機上穩定運作,下篇文章進行詳細分析,敬請期待。

本文原作者:周峤

繼續閱讀