通过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