Wireshark 基於 snmputil 分析 SNMP 協議


SNMP 服務配置

在 WIN10 系統下首先進入設置,選擇開發者選項。



選擇開發人員模式,才可以使用 SNMP。

然后進入應用和功能,選擇可選功能。


在可選功能找到 SNMP 協議,並且添加。

等待 SNMP 配置完成。

配置完成后,可以在 services.msc 中找到 SNMP 服務器的服務。


啟動之后進入“安全”,然后創建一個新的社區“public”。

然后划分接收 SNMP 數據包的主機,實驗方便可以直接選擇“接受任何數據包”。

Snmputil 工具

Snmputil 工具括 snmputil.exe和 snmputilg.exe 兩個小程序,是測試、學習 snmp 的工具,支持 xp、win7、win10 系統。Snmputil 是一個命令行下的軟件,使用語法如下:

usage: snmputil [get|getnext|walk] agent community oid [oid ...]
參數 說明
agent 代理進程的 IP 地址
community 團體名
oid 被獲取的 MIB 對象 ID

實驗用的設備的 IP 地址是 172.21.10.173,使用 snmputil 獲取實驗設備上的有關硬件和操作系統的描述,oid 是 .1.3.6.1.2.1.1.1.0。

snmputil get 172.21.10.173 public .1.3.6.1.2.1.1.1.0


使用 wireshark 抓包,過濾條件直接設為“snmp”,成功抓到包。Snmp 是應用層協議,也就是說一般情況下會源主機發一個包進行請求,目的主機發另一個包進行回復。例如 NO.59 的包就是一個請求信息,它的 data 類型是 get-request,說明它用於請求。“Object”指示了在請求的數據是 MIB 樹中的哪一個條目,value 還未知。

NO.60 的包就是一個響應信息,它的 data 類型是 get-response,說明它用於響應請求。“Object”指示了在響應的數據是MIB樹中的哪一個條目,value 填充了自己主機上的數據。

驗證 SNMP 協議的工作過程

PDU 一共有 GetRequest-PDU、GetNextRequest-PDU、GetResponse-PDU、SetRequest-PDU、Trap-PDU 五種,這些類型在 RFC1157 的第 4 節Protocol Specification 有給出。

IP 組提供了與 IP 協議有關的信息,可以在 RFC1213 的 3.7 看到。

實驗使用的設備的 IP 地址是 172.21.10.210,獲取其設備的 IP 地址使用如下命令。

snmputil walk 172.21.10.210 public .1.3.6.1.2.1.4.20.1.1


成功抓到如下數據包。

可以明顯地看出,SNMP 是基於請求/響應模型進行工作的,客戶端發送一個請求,服務器對請求的內容進行回應。


例如 NO.39 數據包是“get-next-request”,說明是請求下一個,請求的對象是“.1.3.6.1.2.1.4.20.1.1”。

NO.40 為服務器的響應,數據包是“get-response”說明是對上一個數據包的回應。回應的對象是“.1.3.6.1.2.1.4.20.1.1”,值是“127.0.0.1”。

注意此時客戶端是不知道服務器是有多少數據的,例如我舍友的設備只有 2 個
IP 地址。由於發送方不知道對方有多少 IP 地址,因此就發送了第 3 個請求。可以看到,接收方的最后一個包的 value 是“1”,這個值可以提示發送方已經獲取完畢,至此一次查詢結束。

SNMP PDU 分析

GetRequest PDU 分析

前文抓到的 NO.59 的包就是一個請求信息,它的 data 類型是 get-request,說明它用於請求。

首先看 version 的編碼,version 字段的 REC 文檔定義如下:

SNMP 第一個字段是 version(版本號),它是值為 0 的 INTEGER 類型。INTEGER 是 UNIVERSAL(通用標簽),因此前兩位(標簽)為 00。INTEGER是簡單類型,因此第三位類型值為 0。類型 INTEGER 的標簽號 UNIVERSAL 2,因此后五位為 00010。
綜上所述 TLV 中第一個字節 T 的值為二進制 00 0 00010,即 0000 0010,對應十六進制數為 02H。

第二部分L表示值 V 的長度,1 個字節,對應十六進制數為 01H。第三部分V表示值 0,對應十六進制數為 00H。綜上,版本號 0 的 BER 編碼為 02 01 00。

community 類型是 OCTET STRING 字節串為通用標簽 UNIVERSAL,標簽值為4。因此前兩位(標簽)為 00,類型為簡單類型,第三位為 0,標簽值為 4,后五位為 00100。T 字段為的值為 00000100,對應十六進制數為 04。variable-bindings 的值有6個字節,所以L字段的值為 00000110,十六進制為 06。V 字段的值為 public,也就是用 ASCII 碼表示的值為 70 75 62 6C 69 63。

“Object”指示了在請求的數據是MIB樹中的哪一個條目,value 還未知。get-request PDU 的格式如下:

定義中 [0] 表明 GetRequest 的標簽為“上下文專用標簽”,標簽值為 0。類型為 SEQUENCE 序列類型,這是一種構造類型。IMPLICIT(隱含標簽)指用新標簽替換老標簽,因此編碼時只編碼新標簽(即上下文專用標簽)。
根據BER編碼規則,GetRequest 的標簽為“上下文專用標簽”,前兩位(標簽)為 10。類型為 SEQUENCE 是構造類型,因此第三位類型值為 1。“[0]”表示標簽值為 0,因此后五位為 00000。由此可見,TLV 中第一個字節 T 的值為二進制10 1 00000,即 1010 0000,對應十六進制數為a0。
第二部分 L 表示值 V 的長度,這次抓到的包 GetRequest PDU 的長度為 25 個字節,是十六進制 19。第三部分 V 表示 GetRequest PDU 的值,即協議數據單元的內容。根據 BER 定義,此處遞歸地再編碼為 TLV 結構。

Request-id、error-status 和 error-index都是 INTEGER 類型,因此 T 字段的前 2 位都是 00,INTEGER 類型是簡單類型,第 3 位是 0,INTEGER 類型的標簽號是 2,后 5 位是00000,因此 T 字段都是 02。這 3 個字段的長度都是 1 個字節,所以 L 字段的值為 1,Request-id、error-status 和error-index 的 V 字段值分別為 1、0、0。所以 Request-id 的編碼為 02 01 01:

error-status 的編碼和 error-index 編碼一樣,都是 02 01 00:


關於 variable-bindings 格式,在 RFC1157 中也可以找到其定義,在 4.1.1 中有寫到。

variable-bindings 類型為 SEQUENCE 是構造類型,是通用標簽
UNIVERSAL,因此前兩位(標簽)為 00,類型為簡單類型,第三位為 0,標簽值為 16,后五位為 10000。T 字段為的值為 00110000,對應十六進制數為 30。variable-bindings 的值有 12 個字節,所以 L 字段的值為 00001010,十六進制為 0C。

variable-bindings 下的第一個是 Object Name,類型是 OBJECT IDENTIFIER 為通用標簽 UNIVERSAL,標簽值為 6。因此前兩位(標簽)為
00,類型為簡單類型,第三位為 0,標簽值為 6,后五位為 00110。T字段為的值為 00000110,對應十六進制數為 06。variable-bindings 的值有8個字節,所以 L 字段的值為 00001000,十六進制為 08。V 字段的值為 oid,也就是1.3.6.1.2.1.1.1.0。
Value 的值是 NULL,NULL 類型只有一個值 NULL,其標簽是 UNIVERSAL 5。由於這個類型是空類型,無需存儲或傳送它的值,第二個字節 00 表示值長度為 0。

GetResponse-PDU 分析

GetResponse-PDU 在 RFC 文檔中的定義如下。

定義中 [2] 表明 GetResponse 的標簽為“上下文專用標簽”,標簽值為2。類型為 SEQUENCE 序列類型,這是一種構造類型。IMPLICIT(隱含標簽)指用新標簽替換老標簽,因此編碼時只編碼新標簽(即上下文專用標簽)。
根據 BER 編碼規則,GetResponse 的標簽為“上下文專用標簽”,前兩位(標簽)為 10。類型為SEQUENCE是構造類型,因此第三位類型值為 1。“[2]”表示標簽值為 2,因此后五位為00010。T 字段的值為二進制 10100010,對應十六進制數為 a2。這次抓到的包的長度為 287 個字節,此處超過了 127 個字節需要擴充,需要一個字節左邊第一位置為1標尺擴充,其余 7 位表示需要的字節數,此處 287 個字節需要 1 個字節來表示,所以是 1000 0001,擴充后的那個字節表示 287,也就是 1001 1111,所以 L 字段的值是十六進制 81 9F。

GetResponse 中的 variable-bindings 中的 value 類型是 OCTET STRING 字節串為通用標簽 UNIVERSAL,標簽值為 4。因此前兩位(標簽)為 00,類型為簡單類型,第三位為 0,標簽值為 4,后五位為 00100。T 字段為的值為
00000100,對應十六進制數為 04。
variable-bindings的 value 長度為 259 個字節,此處超過了 127 個字節需要擴充,需要一個字節左邊第一位置為 1 標尺擴充,其余 7 位表示需要的字節數,此處 259 個字節需要 1 個字節來表示,所以是 1000 0001,擴充后的那個字節表示 259,也就是 1001 0011,所以L字段的值是十六進制 81 83。

參考資料

《計算機網絡管理(第三版)》雷震甲 編著,西安電子科技大學出版社


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM