UNIX 网络协议的深度分析
https://www.ibm.com/developerworks/cn/aix/library/au-deepprotocolanalysis/index.html?mhq=http%E5%8D%8F%E8%AE%AE&mhsrc=ibmsearch_a
引言
網絡已經是無處不在,很多時候我們都會利用網絡與不同主機進行通信,包括網絡內部和外部的。大多數情況下這不會遇到問題,但是有時您需要仔細檢查您的網絡以查明問題原因。
仔細檢查網絡流量內容的原因有很多。其中第一個原因是您可能正在調試一個現有的網絡應用,或者您正在開發一個應用,而您想要監控通過您的網絡的流量。第二個原因是需要識別可能耗盡網絡帶寬和資源的流量。對于前一種情況,您可能已經知道協議的內容了,但是您希望能夠更深入地了解正在傳輸的實際數據,例如,在使用 Web 服務時。對于后一種情況,確定數據包的內容需要了解正在使用的協議的一些擴展知識。
在 TCP/IP 和 UDP/IP 的通信中,最主要的元素是用于確定主機和端口號的 IP 地址。端口號用于提供額外的通信通道,這樣您才能夠在兩個主機之間實現多個連接。其中端口定義還有一些標準。例如,端口 25 是專用于電子郵件(SMTP)傳輸,而大多數網站都是運行在端口 80(HTTP)上的。這些規范可以使程序之間通過一個熟悉的通道進行通信,這與您選擇電話或傳真號的道理是一樣的。
雖然有這樣一些規范,但是您實際想使用哪些端口是沒有任何限制或約束的。事實上,大多數情況下一些破壞性網絡應用和一些安全性方法會故意使用非標準端口。例如,有些應用會通過將一個標準端口用于不同的協議而隱藏內容,如在 端口 25 上使用 HTTP 協議。此外,有時某些應用也會使用與標準不同的端口,這樣端口的用途就明顯了(如,將端口 99 用于 HTTP),或者將特定的協議流量封裝到另一個協議中。最后的方法實際上是網絡通道和虛擬私有網絡(VPN)所使用的方法。
不管網絡流量原因和復雜性,第一個步驟都會開始記錄數據。
記錄原始數據
如果您希望記錄網絡原始數據,以便自己檢查這些信息,那么您可以使用許多不同的工具。大多數的網絡嗅探器也能夠解碼和解密特定的數據包內容,這能夠幫助您研究一個已知協議的內容。
在 Solaris 上,您可以使用 snoop 工具,而在 AIX 上,您可以使用 iptrace 工具。您也可以嘗試使用跨平臺的 tcpdump 工具,它支持大多數的 UNIX 和 Linux 操作系統。這些工具能夠幫您捕捉和解碼數據包,通常也能為您執行大多數的協議分析。注意,現代交換機不會將 Ethernet 數據包發送到每一個端口上,這通常會限制您從當前主機獲取的信息量。許多現代交換機具有一個管理端口,它通常帶有與這種監控完全相同的所有數據包的副本。
解碼網絡傳輸最復雜的是網絡數據包中信息的級別。此外,大部分信息也會經過二進制編碼后再發送,從網絡捕捉完全原始的數據包需要進行大量的操作才能捕捉您需要的數據。通過使用實現某些處理的工具,您可以簡化解碼網絡數據的過程。
例如,在一個 Ethernet 上查看一個典型的 TCP/IP 協議,您將會發現網絡中傳輸的數據包括:
- Ethernet 數據包頭,包括 Ethernet 來源和目標地址,數據包大小和 Ethernet 數據包類型。
- IP 報頭,由 IP 尋址(來源和目標),協議標識和 IP 標記。您也會得到關于分片和數據包順序的信息。
- TCP 報頭,它包含端口上的信息、隱含的協議、標記和順序編號。
即使有這些信息,我們仍然無法了解實際內容。在 TCP(或 UDP)協議之下還有額外的協議,標準數據協議(包括 HTTP、SMTP 和 FTP),或者封裝性協議,如 Remote Procedure Call (RPC) 和 RPC 的子類型,如 NFS。
通常這些工具必須使用協議和/或端口號來確定正在傳輸的內容。所以,如果流量是通過非標準端口傳輸的,那么這個些信息可能無法正確解碼。
基本的網絡分析
本文之前提到的許多網絡嗅探工具都提供了不同級別的協議解碼,它們是通過檢查端口和內容來確定所使用的協議實現的。
例如,snoop 和 tcpdump 都提供了關于 UDP 和 TCP 上不同協議的不同級別的詳細信息。例如,在 snoop 中,您可以獲得從頂級協議到所傳輸的單個數據塊的關于 NFS 操作的詳細信息。例如,您可以通過指定監控 RPC 使用 NFS 協議來實現對 NFS 流量的監控:$ snoop -v rpc nfs。
它能輸出非常詳細的數據包信息,并且它們應該進行更緊密的觀察。清單 1?提供了 Ethernet 報頭數據。
清單 1. Ethernet 報頭數據
| 1 2 3 4 5 6 7 8 | ETHER:? ----- Ether Header ----- ETHER:? ETHER:? Packet 64 arrived at 16:14:41.79434 ETHER:? Packet size = 238 bytes ETHER:? Destination = 0:1a:ee:1:1:c0, ETHER:? Source????? = 0:21:28:3c:c0:61, ETHER:? Ethertype = 0800 (IP) ETHER: |
這里的輸出表明 Ethernet 數據包包含了 IP 數據、全部數據包大小和時間,以及數據包的目標和來源地址。
清單 2?顯示的是 IP 報頭。其中除了協議和來源/目標地址信息,其余許多 IP 數據是沒有用的。
清單 2. IP 報頭
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | IP:?? ----- IP Header ----- IP:?? IP:?? Version = 4 IP:?? Header length = 20 bytes IP:?? Type of service = 0x00 IP:???????? xxx. .... = 0 (precedence) IP:???????? ...0 .... = normal delay IP:???????? .... 0... = normal throughput IP:???????? .... .0.. = normal reliability IP:???????? .... ..0. = not ECN capable transport IP:???????? .... ...0 = no ECN congestion experienced IP:?? Total length = 224 bytes IP:?? Identification = 27460 IP:?? Flags = 0x4 IP:???????? .1.. .... = do not fragment IP:???????? ..0. .... = last fragment IP:?? Fragment offset = 0 bytes IP:?? Time to live = 64 seconds/hops IP:?? Protocol = 6 (TCP) IP:?? Header checksum = 4d11 IP:?? Source address = 192.168.0.112, tiger.mcslp.pri IP:?? Destination address = 192.168.0.2, bear.mcslp.pri IP:?? No options IP: |
在?清單 3?中,您可以看到 TCP 報頭。同樣,這些信息中通常只有來源和目標端口號才是有用的,因為這些信息將可用于確定預期的協議,或者提供給您可用于更進一步觀察這個端口所傳輸流量的信息。
清單 3. TCP 報頭
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | TCP:? ----- TCP Header ----- TCP:? TCP:? Source port = 2049 TCP:? Destination port = 889 (Sun RPC) TCP:? Sequence number = 2834727685 TCP:? Acknowledgement number = 2654368001 TCP:? Data offset = 32 bytes TCP:? Flags = 0x18 TCP:??????? 0... .... = No ECN congestion window reduced TCP:??????? .0.. .... = No ECN echo TCP:??????? ..0. .... = No urgent pointer TCP:??????? ...1 .... = Acknowledgement TCP:??????? .... 1... = Push TCP:??????? .... .0.. = No reset TCP:??????? .... ..0. = No Syn TCP:??????? .... ...0 = No Fin TCP:? Window = 32806 TCP:? Checksum = 0x4852 TCP:? Urgent pointer = 0 TCP:? Options: (12 bytes) TCP:??? - No operation TCP:??? - No operation TCP:??? - TS Val = 34449495, TS Echo = 253458642 TCP: |
清單 4?的倒數第二部分顯示的是 RPC 報頭數據。
清單 4. RPC 報頭數據
| 1 2 3 4 5 6 7 8 9 10 | RPC:? ----- SUN RPC Header ----- RPC:? RPC:? Record Mark: last fragment, length = 168 RPC:? Transaction id = 3041181596 RPC:? Type = 1 (Reply) RPC:? This is a reply to frame 63 RPC:? Status = 0 (Accepted) RPC:? Verifier?? : Flavor = 0 (None), len = 0 bytes RPC:? Accept status = 0 (Success) RPC: |
最后,清單 5?提供了 NFS 數據包內容,包括權限(文件模式)、文件大小、擁有者和其他信息。在這里,這個 NFS 操作請求是進行文件系統統計(這等同于 ls 操作結果),因此這就是詳細信息。
清單 5. NFS 數據包內容
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | NFS:? ----- Sun NFS ----- NFS:? NFS:? Proc = 18 (Get filesystem statistics) NFS:? Status = 0 (OK) NFS:? Post-operation attributes: NFS:??? File type = 2 (Directory) NFS:??? Mode = 0777 NFS:???? Setuid = 0, Setgid = 0, Sticky = 0 NFS:???? Owner's permissions = rwx NFS:???? Group's permissions = rwx NFS:???? Other's permissions = rwx NFS:??? Link count = 24, User ID = 502, Group ID = 10 NFS:??? File size = 29, Used = 2560 NFS:??? Special: Major = 4294967295, Minor = 4294967295 NFS:??? File system id = 781684113418, File id = 4304616 NFS:??? Last access time????? = 28-Feb-10 15:49:51.042953989 GMT NFS:??? Modification time???? = 25-Feb-10 09:39:07.965422590 GMT NFS:??? Attribute change time = 25-Feb-10 09:39:07.965422590 GMT NFS:? NFS:? Total space = 759567510016 bytes NFS:? Available space = 659048374272 bytes NFS:? Available space - this user = 659048374272 bytes NFS:? Total file slots = 1288161604 NFS:? Available file slots = 1287203856 NFS:? Available file slots - this user = 1287203856 NFS:? Invariant time = 0 sec NFS: |
在這里,我們可以看到所查詢的文件事實上是一個目錄(見文件類型行)。雖然我們沒有得到文件的實際路徑,但是我們可以通過使用 Find 命令來查詢 inode 號對應的文件/路徑來查找上面提到的目錄(見?清單 6)。
清單 6. 查詢 inode 號對應的文件
| 1 2 | $ find /scratch -xdev -inum 4304616 /scratch/installed/mysql-6.0.11 |
如果您準備分辨流量,那么使用這些工具的最佳方法是首先運行它們,收集盡可能多的數據,然后手動檢查數據內容,找出您的網絡本來不應該出現的數據項。
一旦您識別出了可疑流量,您就可以開始在命令行上添加參數以便關注于流量細節。例如,您可以使用?清單 7?所示的命令之一,規定只顯示特定主機的流量。
清單 7. 規定只顯示一個特定主機的流量
| 1 2 | $ snoop host 192.168.0.2 $ tcpdump host 192.168.0.2 |
要進一步限制,您可以限制協議信息的端口:$ snoop host 192.168.0.2 and port 25。
解析原始數據以理解數據包內容
處理來自 tcpdump 的另一個方法是將原始網絡數據包數據保存到一個文件中,然后處理這個文件以便查找和解碼出您想要的信息。
有許多使用不同語言編寫的模塊具有讀取和解碼 tcpdump 和 snoop 捕捉的數據的功能。例如,有兩個用 Perl 編寫的模塊:Net::SnoopLog(針對 snoop)和 Net::TcpDumpLog(針對 tcpdump)。它們將讀取原始數據內容。這些模塊的基本接口是相同的。
要開始處理,您首先需要使用 snoop 或 tcpdump 將數據寫到一個文件,而創建一個通過網絡的數據包的二進制記錄。對于本例,我們將使用 tcpdump 和 Net::TcpDumpLog 模塊:$ tcpdump -w packets.raw。
收集網絡數據完成后,您就可以開始處理網絡數據內容以查找您想要的信息。Net::TcpDumpLog 會解析 tcpdump 所保存的原始網絡數據。因為這些數據是以原始的二進制格式保存的,解析這些信息就需要處理這個二進制數據。為了方便起見,您可以使用另一組模塊 NetPacket::* 來解碼原始數據。
例如,清單 8?顯示的是一個打印所有數據包的 IP 地址信息的簡單腳本。
清單 8. 打印所有數據包的 IP 地址的簡單腳本
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | use Net::TcpDumpLog; ????? use NetPacket::Ethernet; ????? use NetPacket::IP; ????? my $log = Net::TcpDumpLog->new(); ?? $log->read("packets.raw"); ?? ?? foreach my $index ($log->indexes) ???????? { ????? ????my $packet = $log->data($index); ???????????? ????my $ethernet = NetPacket::Ethernet->decode($packet); ??? ????if ($ethernet->{type} == 0x0800) ???????? ????{ ????? ????????my $ip = NetPacket::IP->decode($ethernet->{data}); ??????????? ????? ????????printf("? %s to %s protocol %s \n", ???????????????$ip->{src_ip},$ip->{dest_ip},$ip->{proto}); ???} } |
第一部分是提取每一個數據包。Net::TcpDumpLog?模塊會將每一個數據包序列化,這樣我們就能夠通過數據包 ID 讀取每一個數據包。然后?data()?函數就會返回整個數據包的原始數據。
通過 snoop 的輸出,我們必須從原始網絡數據包信息中提取每一個數據塊。所以在本例中,我們首先需要從原始網絡數據包中提取 Ethernet 數據包,包括數據有效負載。而?NetPacket::Ethernet?模塊能夠幫我們執行這個操作。
因為我們尋找的是 IP 數據包,所以我們能通過檢查 Ethernet 數據包類型來檢查 IP 數據包。IP 數據包的 ID 為 0x0800。
然后,NetPacket::IP?模塊會被用于從 Ethernet 數據包的數據負載中提取出 IP 信息。這個模塊能提供來源 IP、目標 IP 和協議信息等等,然后我們可以打印出這些信息。
通過使用這個基本的框架,您就能夠執行不依賴于 tcpdump 或 snoop 的自動化解決方案的更復雜查詢和解碼。例如,如果您懷疑 HTTP 流量是通過一個非標準端口傳輸的(如,不是端口 80),那么您可以使用?清單 9?中的腳本在懷疑的主機 IP 的非 80 端口上檢查 HTTP 數據包。
清單 9. 在非 80 端口上檢查 HTTP 數據包
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | use Net::TcpDumpLog; ????? use NetPacket::Ethernet; ????? use NetPacket::IP; ????? use NetPacket::TCP; ????? ????? my $log = Net::TcpDumpLog->new(); ???????? $log->read("packets.raw"); ???????? ????? foreach my $index ($log->indexes) ???????? { ????? ????my $packet = $log->data($index); ???????? ????? ????my $ethernet = NetPacket::Ethernet->decode($packet); ???????? ????? ????if ($ethernet->{type} == 0x0800) ???????? ????{ ????? ????????my $ip = NetPacket::IP->decode($ethernet->{data}); ??????????? ????? ????????if ($ip->{src_ip} eq '192.168.0.2') ???????? ????????{ ????? ????????????if ($ip->{proto} == 6) ???????? ????????????{ ????? ????????????????my $tcp = NetPacket::TCP->decode($ip->{data}); ???????? ????????????????if (($tcp->{src_port} != 80) && ???????????????? ????????????????????($tcp->{data} =~ m/HTTP/)) ???????? ????????????????{ ????? ????????????????????print("Found HTTP traffic on non-port 80\n"); ????? ????????????????????printf("%s (port: %d) to %s (port: %d)\n%s\n", ????? ???????????????????????????$ip->{src_ip}, ???????? ???????????????????????????$tcp->{src_port}, ???????? ???????????????????????????$ip->{dest_ip}, ???????? ???????????????????????????$tcp->{dest_port}, ???????? ???????????????????????????$tcp->{data}); ?? ????????????????} ????? ????????????} ????? ????????} ????? ???} ????? } |
在一個示例數據包集上運行上面的腳本會返回如?清單 10?所示的結果。
清單 10. 在一個示例數據包集上運行這個腳本
| 1 2 3 4 5 6 7 | $ perl http-non80.pl Found HTTP traffic on non-port 80 192.168.0.2 (port: 39280) to 168.143.162.100 (port: 80) GET /statuses/user_timeline.json HTTP/1.1 Found HTTP traffic on non-port 80 192.168.0.2 (port: 39282) to 168.143.162.100 (port: 80) GET /statuses/friends_timeline.json HTTP/1 |
在這種特定的情況下,我們發現主機的流量是通向一個外部網站(Twitter)。
顯然,在這個例子中我們處理的是原始數據,但是您可以使用相同的基本結構進行解碼,也可以使用任何公開或私有協議結構的格式的數據。如果您正在使用這個方法使用或開發一個協議,并且您知道協議格式,您就能夠提取和監控正在傳輸的數據。
使用一個協議分析器
雖然,正如之前提到的,諸如 tcpdump、iptrace 和 snoop 等工具都提供了基本的網絡分析和解碼功能,但是還有一些基于 GUI 的工具使這個過程更簡單。Wireshark 就是其中一個工具,它支持大量的網絡協議解碼和分析。
Wireshark 的最主要優點之一是您可以捕捉一段時間內的數據包(如 tcpdump 一樣),然后基于不同的協議、端口和其他數據交互地分析和過濾內容。Wireshark 也支持大量的協議解碼器,這使您能夠檢查每分鐘內數據包和會話的詳細內容。
您可以看到 Wireshark 的簡單截圖顯示了所有類型的所有數據包,如?圖 1?所示。這個窗口分成三個主要部分:過濾的數據包列表、解碼的協議明細和 HEX/ASCII 格式的原始數據包數據。
圖 1. Wireshark 界面
作為 Wireshark 工具所提供的一個級別的信息和解碼的例子,在撰寫本文時我注意網絡中的一個 MySQL 服務器返回了一些錯誤數據包。
為了專注于內容,我首先對輸出應用了 MySQL 過濾。您可以通過在 Filter 輸入框中輸入一個表達式(類似于 tcpdump、snoop 或 iptract)。或者,您可以單擊 Expression 按鈕,然后從內置的列表的中選擇一種過濾。您可以在?圖 2?中看到一組示例過濾。一旦您選擇了某個過濾,單擊 Apply 就可以過濾數據包列表。
圖 2. 選擇一個 Wireshark 過濾
通過過濾 MySQL 協議,我能夠確定錯誤的數據包。MySQL 協議會傳到一個帶有錯誤信息的特殊數據包類型。在這里,錯誤 1242 表示查詢操作失敗,由于子查詢有問題。您可以通過展開 Wireshark 窗口的 MySQL 協議部分查看 MySQL 協議的內容,如?圖 3?所示。
圖 3. 檢查一個 MySQL 錯誤數據包
在這里我們可以看到錯誤的明細。通過跟蹤之前的 ‘Request Query’ 數據包,我們就可能確定出導致產生錯誤響應的查詢(圖 4)、
圖 4. 導致產生錯誤響應的 MySQL 查詢
通過分析數據包,我能夠識別之前并沒有注意的錯誤代碼,并且能夠指出這個錯誤及導致發生問題的查詢。
Wireshark 支持廣泛的協議和過濾器,您可以用它們獲得詳細的信息。它的另一個常見用途是監控詳細協議的確切內容,如 Web 服務。圖 5?顯示了一個來自 SOAP 請求用于記錄狀態信息的詳細(且結構清晰的)信息。
圖 5. 查看 SOAP Web 服務請求的詳細信息
這些詳細信息在調試您使用的任何網絡協議時是非常有用的。
Wireshark 的另一個有用的特性是它能夠處理即時信息,并且它能夠記錄信息以備將來過濾和處理。這表示您可以使用它監控某個時期的可疑流量,然后您可以在恰當的時候分析這些信息,以查明您的網絡中發生了什么操作。
結束語
對于通過您的 UNIX 網絡的信息進行協議分析可能是一個復雜的過程。但是,通過使用一些簡單而廣泛使用的工具,您可以解碼和檢查您的流量的詳細信息,包括來源和目標等基本信息,以及具體的協議和傳輸的數據。
如本文所述,通過使用諸如 tcpdump、snoop 或 iptrace 的工具,您可以在命令行上提取大量的數據。通過使用諸如 Wireshark 的工具,您可以更一地步地了解更大范圍的協議和內容的更多詳細信息。對于自定義的協議和結構,您可以使用 Perl 提取原始數據,并獲得您需要的所有信息。
轉載于:https://www.cnblogs.com/davidwang456/articles/10660022.html
總結
以上是生活随笔為你收集整理的UNIX 网络协议的深度分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 实时流处理框架Storm、Spark S
- 下一篇: DNS协议详解及报文格式分析