1. 程式人生 > 程式設計 >Netis Packet-Agent : 一種雲環境網路流量映象的通用解決方案(V2.0)

Netis Packet-Agent : 一種雲環境網路流量映象的通用解決方案(V2.0)

0x00 背景

目前,最流行的網路監控和故障分析工具是SPAN(Switch Port Analyzer),也就是埠映象。傳統網路資料分析會在交換機上配置網路資料映象, 將Packet複製後傳送到目標機器,實現網路流量映象的功能。

而在雲平臺上,目前網路資料採集還沒有統一的方案。針對私有云平臺,目前有流表資料包複製採集、在hypervisor上監聽採集、vmware平臺分散式虛交換機配置採集、libpcap抓包採集等方案。

對於vmware平臺分散式虛交換機配置採集的方案,效能較好,不佔用客戶機資源,但其屬於商業產品,且只適用於購買vmware私有云使用者;而在hypervisor上監聽採集,目前有產品開發,效能較好,但只適用於OpenStack私有云;採用OVS流表方案,優勢是免費,不佔用客戶機資源,但是配置複雜,且只能用於OpenStack私有云。

因此,開發基於libpcap + GRE轉發的應用,或許是雲平臺目前最優的網路流量映象方案。其使用簡單、開源、適用於各類公有云和私有云,只是需要在客戶機部署接收工具而佔用客戶機CPU、記憶體、網路資源。

0x01 GRE技術原理

GRE:通用路由封裝(Generic Routing Encapsulation)定義了在任意一種網路層協議上封裝任意一個其它網路層協議的協議。 通過對某些網路層協議(如IP 和IPX)的資料報文進行封裝,使這些被封裝的資料報文能夠在另一個網路層協議(如IP)中傳輸。

GRE採用了Tunnel(隧道)技術,是VPN(Virtual Private Network)的第三層隧道協議。 Tunnel 是一個虛擬的點對點的連線,提供了一條通路使封裝的資料報文能夠在這個通路上傳輸,並且在一個Tunnel 的兩端分別對資料報進行封裝及解封裝。一個X協議的報文要想穿越IP網路在Tunnel中傳輸,必須要經過加封裝與解封裝兩個過程。

標準的GRE的封裝和報頭格式如下:

前4位元組是必須出現的。第5~20位元組將根據第1位元組的相關bit位資訊,可選出現。例如,如果其中K位元設定為1,則金鑰部分的4位元組會出現在GRE頭部。此時頭部總長8位元組。需要注意的是,GRE頭部的長度將影響Tunnel口的mtu值。

在思科的網路裝置中,有一種專有的網路流量映象格式ERSPAN(Encapsulated Remote Switch Port Analyzer),即在SPAN的基礎上擴充套件了encapsulated remote的特性。ERSPAN封裝格式是基於GRE,可應用於IPv4及IPv6網路上。目前有三種型別:ERSPAN Type I、ERSPAN Type II 及ERSPAN Type III。其中ERSPAN Type I格式因為可擴充套件性差,已經被廢棄。三種型別的頭格式如下:

ERSPAN的幾個要點:

  • IP頭上層協議欄位統一為GRE(47);
  • Type I僅包含必選GRE頭,GRE協議欄位和Type II 相同(0x88BE),flag全部為0。總長僅4位元組(flag),所以比Type II更緊湊,但由於缺乏擴充套件性,目前已被廢棄;
  • Type II和Type III包括GRE頭部和ERSPAN頭。GRE頭部相同,都包含且只包含sequence可選欄位。其中Type III的協議值為0x22EB.

有關ERSPAN格式的詳細檔案,請參考 tools.ietf.org/html/draft-….

0x02 packet-agent簡介

Netis Packet Agent是一個用於解決如下問題的開源專案:裝置A上抓取的資料包,之後在裝置B上使用分析。在很多時候,當你希望監控網路的流量,但是並沒有可用的裝置,例如:

物理環境中不存在TAP和SPAN裝置。 虛擬環境中,Virtual Switch Flow Table不支援SPAN功能。 因此,該專案提供一套低開銷但是高效能的抓包工具,用於應對上述困難。

pktminerg是第一個釋出的工具。該工具可以輕鬆地在網路卡上抓資料包,用GRE頭進行封裝併傳送到遠端的裝置,來進行資料包監控和分析。

此外,還有另外3個工具:

  • pcapcompare用於比較兩個pcap檔案
  • gredump根據特定的過濾規則抓取GRE資料包,並儲存為pcap檔案。
  • gredemo是一個demo應用程式,可以從pcap檔案讀取資料包,然後把它們傳送到遠端網路卡。這個程式只能通過原始碼編譯生成。

目前,packet-agent已經支援了CentOS 6/7、Redhat 7、SUSE 12、Ubuntu 18.04、Windows 7/8/10的x86_64系統。當然,不僅僅是物理機可以執行,雲環境、docker容器同樣支援執行packet-agent工具集。

下面是一些簡單的使用方法:

# Capture packet from NIC "eth0",encapsulate with GRE header and send to 172.16.1.201
pktminerg -i eth0 -r 172.16.1.201

# Specify cpu 1 for this program with high priority to avoid thread switch cost.
pktminerg -i eth0 -r 172.16.1.201 --cpu 1 -p

# compare 2 pcap files
pcapcompare --lpcap /path/to/left_file.pcap --rpcap /path/to/right_file.pcap

# Capture packet from NIC "eth0" and save them to gredump_output.pcap
gredump -i eth0 -o /path/to/gredump_output.pcap

# Capture packet from NIC "eth0",do not set DF flag
pktminerg -i eth0 -r 172.16.1.201 -M dont
複製程式碼

packet-agent預設的封裝格式為帶key的標準GRE頭部封裝。通過指定可選的外掛擴充套件,使用者能夠使用其他協議封裝資料包。目前支援的擴充套件有:

  • proto_gre:支援key/sequence的啟用禁用,sequence初始值及key值設定。
  • proto_erspan_type1:ERSPAN Type I封裝。
  • proto_erspan_type2:ERSPAN Type II封裝。支援vlan/sequence的啟用禁用,sequence初始值及vlan值設定。
  • proto_erspan_type3:ERSPAN Type III封裝。支援vlan/sequence/timestamp的啟用禁用,sequence初始值及vlan值設定。目前僅支援必選頭的配置。

擴充套件目前處於實驗階段。僅支援linux平臺。

使用例項:


# 外掛以動態庫的形式存在。
# 配置欄位說明(下面的例子已經包含了所有的欄位)
# ext_file_path:外掛檔名(.so檔案路徑),支援相對/絕對路徑。
# entry:外掛入口函式,動態載入時被呼叫。第三方外掛開發者可以指定自己的入口函式。
# ext_param:外掛自定義的引數。ext_param內的欄位可以不配置,此時採用預設值(false / 0)
#     use_default_header:頭部欄位僅包括必選部分,可配值為0。如果設定為true,其餘欄位無效。
#     enable_vlan/vlan/enable_sequence/sequence_begin/enable_timestamp/enable/key/key:顧名思義。不同的外掛欄位不同。

# proto_erspan_type3 
JSON_STR=$(cat << EOF
[
    {
        "ext_file_path": "libproto_erspan_type3.so","ext_params": {
            "use_default_header": false,"enable_vlan": true,"vlan": 1024,"enable_sequence": true,"sequence_begin": 10000,"enable_timestamp": true
        }
    }
]
EOF
)
./pktminerg -i eth0 -r 10.1.1.37 --proto_config "${JSON_STR}"

# proto_erspan_type2 
JSON_STR=$(cat << EOF
[
    {
        "ext_file_path": "/path/to/libproto_erspan_type2.so","vlan": 1027,"sequence_begin": 10000
        }
    }
]
EOF
)
./pktminerg -i eth0 -r 10.1.1.37 --dump --proto_config "${JSON_STR}"


# proto_erspan_type1
JSON_STR=$(cat << EOF
[
    {
        "ext_file_path": "../libproto_erspan_type1.so","ext_params": {
        }
    }
]
EOF
)
./pktminerg -i eth0 -r 10.1.1.37 --proto_config "${JSON_STR}"


# proto_gre
JSON_STR=$(cat << EOF
[
    {
        "ext_file_path": "libproto_gre.so","enable_key": true,"key": 3,"sequence_begin": 10000
        }
    }
]
EOF
)
./pktminerg -i eth0 -r 10.1.1.36 --proto_config "${JSON_STR}"

複製程式碼