使用gopacket解析協(xié)議層中的相關(guān)數(shù)據(jù)方式
通過(guò)wirshark可視化相關(guān)應(yīng)用層
使用gopacket來(lái)進(jìn)行解析,或獲取指定結(jié)構(gòu)內(nèi)容。
首先使用wirshark抓取ping x.x.x.x 命令數(shù)據(jù)包

保存數(shù)據(jù)包為pcap格式。
在使用wirshark打開(kāi)pcap數(shù)據(jù)包。

嘗試使用go語(yǔ)言的gopacket來(lái)讀取指定數(shù)據(jù)包的字段數(shù)據(jù)。
可看到,數(shù)據(jù)包一共為103個(gè)。先用go讀取文件,統(tǒng)計(jì)有多少個(gè)數(shù)據(jù)包。
package main
import (
"fmt"
"github.com/google/gopacket"
"github.com/google/gopacket/pcap"
)
func main() {
handle, _ := pcap.OpenOffline("ping.pcap")
defer handle.Close()
packetSource := gopacket.NewPacketSource(
handle,
handle.LinkType(),
)
num := 0
for packet := range packetSource.Packets() {
num += 1
fmt.Println(num)
fmt.Println(packet)
}
}
運(yùn)行代碼

打印所有數(shù)據(jù)包中協(xié)議版本號(hào)(4、6)

目前的協(xié)議版本號(hào)是4,因此IP有時(shí)也稱作IPv4。該值存放在IP層中,所以利用程序解析IP層中的數(shù)據(jù)。
package main
import (
"fmt"
"github.com/google/gopacket/layers"
"github.com/google/gopacket"
"github.com/google/gopacket/pcap"
)
func main() {
handle, _ := pcap.OpenOffline("ping.pcap")
defer handle.Close()
packetSource := gopacket.NewPacketSource(
handle,
handle.LinkType(),
)
for packet := range packetSource.Packets() {
ipLayer := packet.Layer(layers.LayerTypeIPv4) //解析IP層
if ipLayer != nil {
ip, _ := ipLayer.(*layers.IPv4)
fmt.Println("Version:", ip.Version)
}
}
}

獲取指定數(shù)據(jù)包的長(zhǎng)度
要獲取指定數(shù)據(jù)包就需要找到數(shù)據(jù)包的唯一標(biāo)識(shí):
標(biāo)識(shí)字段唯一地標(biāo)識(shí)主機(jī)發(fā)送的每一份數(shù)據(jù)報(bào)。通常每發(fā)送一份報(bào)文它的值就會(huì)加1。

獲取唯一標(biāo)識(shí)1917的總長(zhǎng)度:
package main
import (
"fmt"
"github.com/google/gopacket/layers"
"github.com/google/gopacket"
"github.com/google/gopacket/pcap"
)
func main() {
handle, _ := pcap.OpenOffline("ping.pcap")
defer handle.Close()
packetSource := gopacket.NewPacketSource(
handle,
handle.LinkType(),
)
for packet := range packetSource.Packets() {
ipLayer := packet.Layer(layers.LayerTypeIPv4) //解析IP層
if ipLayer != nil {
ip, _ := ipLayer.(*layers.IPv4)
//fmt.Println("Version:", ip.Version)
if ip.Id == 1917 {
fmt.Println("ID:", ip.Id)
fmt.Println("Length:", ip.Length)
}
}
}
}
查看源代碼,IP層可使用以下相關(guān)字段

fmt.Println("ID:", ip.Id)
fmt.Println("Length:", ip.Length)
fmt.Println("源IP:", ip.SrcIP)
fmt.Println("目的IP:", ip.DstIP)


1917數(shù)據(jù)包向目的地址發(fā)送了一段字符串a(chǎn)bcdef…嘗試使用程序獲取這段字符串
從wirshark中可看到,想要獲取的這段字符串在應(yīng)用層上,可看到該協(xié)議為ICMP協(xié)議。
gopacket內(nèi)置的有ICMP包的解析方式,不需要我們?cè)谧远x。
package main
import (
"fmt"
"github.com/google/gopacket/layers"
"github.com/google/gopacket"
"github.com/google/gopacket/pcap"
)
func main() {
handle, _ := pcap.OpenOffline("ping.pcap")
defer handle.Close()
packetSource := gopacket.NewPacketSource(
handle,
handle.LinkType(),
)
for packet := range packetSource.Packets() {
ipLayer := packet.Layer(layers.LayerTypeIPv4)
if ipLayer != nil {
ip, _ := ipLayer.(*layers.IPv4)
if ip.Id == 1917 {
icmpLayer := packet.Layer(layers.LayerTypeICMPv4) //解析應(yīng)用層ICMP數(shù)據(jù)包
if icmpLayer != nil {
fmt.Println(string(icmpLayer.LayerPayload()))
}
}
}
}
}

成功獲取數(shù)據(jù)內(nèi)容。
熟悉TCP/IP協(xié)議族使用gopacket會(huì)非常的簡(jiǎn)單,首先要知道需要解析的數(shù)據(jù)在哪一層上,如果在應(yīng)用層上就使用相關(guān)應(yīng)用協(xié)議進(jìn)行解析,或者自定義解析其他協(xié)議。
查看源代碼可看到內(nèi)置了很多支持的協(xié)議格式

總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Go語(yǔ)言學(xué)習(xí)之操作MYSQL實(shí)現(xiàn)CRUD
Go官方提供了database包,database包下有sql/driver。該包用來(lái)定義操作數(shù)據(jù)庫(kù)的接口,這保證了無(wú)論使用哪種數(shù)據(jù)庫(kù),操作方式都是相同的。本文就來(lái)和大家聊聊Go語(yǔ)言如何操作MYSQL實(shí)現(xiàn)CRUD,希望對(duì)大家有所幫助2023-02-02
Golang語(yǔ)言如何避免空指針引發(fā)的panic詳解
Go1.21新增內(nèi)置函數(shù)(built-in?functions)詳解
Go讀取yaml文件到struct類的實(shí)現(xiàn)方法
使用Go語(yǔ)言實(shí)現(xiàn)發(fā)送HTTP請(qǐng)求并給GET添加參數(shù)
Golang WebView跨平臺(tái)的桌面應(yīng)用庫(kù)的使用
Windows下Goland的環(huán)境搭建過(guò)程詳解
Go語(yǔ)言數(shù)據(jù)結(jié)構(gòu)之二叉樹(shù)必會(huì)知識(shí)點(diǎn)總結(jié)

