通過wirshark可視化相關應用層使用gopacket來進行解析,或獲取指定結構內容。
首先使用wirshark抓取ping x.x.x.x 命令數據包
保存數據包爲pcap格式。
在使用wirshark打開pcap數據包。
嘗試使用go語言的gopacket來讀取指定數據包的字段數據。
可看到,數據包一共爲103個。先用go讀取文件,統計有多少個數據包。
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)
}
}
運行代碼
打印所有數據包中協議版本號(4、6)
目前的協議版本號是4,因此IP有時也稱作IPv4。該值存放在IP層中,所以利用程序解析IP層中的數據。
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)
}
}
}
獲取指定數據包的長度
要獲取指定數據包就需要找到數據包的唯一標識:
標識字段唯一地標識主機發送的每一份數據報。通常每發送一份報文它的值就會加1。
獲取唯一標識1917的總長度:
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層可使用以下相關字段
fmt.Println("ID:", ip.Id)
fmt.Println("Length:", ip.Length)
fmt.Println("源IP:", ip.SrcIP)
fmt.Println("目的IP:", ip.DstIP)
1917數據包向目的地址發送了一段字符串abcdef…嘗試使用程序獲取這段字符串
從wirshark中可看到,想要獲取的這段字符串在應用層上,可看到該協議爲ICMP協議。
gopacket內置的有ICMP包的解析方式,不需要我們在自定義。
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) //解析應用層ICMP數據包
if icmpLayer != nil {
fmt.Println(string(icmpLayer.LayerPayload()))
}
}
}
}
}
成功獲取數據內容。
熟悉TCP/IP協議族使用gopacket會非常的簡單,首先要知道需要解析的數據在哪一層上,如果在應用層上就使用相關應用協議進行解析,或者自定義解析其他協議。
查看源代碼可看到內置了很多支持的協議格式
本文相關參考:
https://blog.lab99.org/post/golang-2017-09-23-video-packet-capture-analysis-with-go.html
http://www.52im.net/topic-tcpipvol1.html?mobile=no