Go语言解析pcap包,提取http请求

公西永嘉
2023-12-01

使用gopacket包对pcap流量包进行解析。

go get github.com/google/gopacket

首先打开一个pcap流量包文件,然后过滤tcp流量中的每一个包,遍历每一个包进行下一步处理。

针对每一个包,首先从以太网层可以获取到ip协议是ipv4还是ipv6,只需要ipv4的,同时还能获取到源MAC地址,目的MAC地址,源ip和目的ip。

 ethernetLayer := packet.Layer(layers.LayerTypeEthernet)
 fmt.Println("Source MAC: ", ethernetPacket.SrcMAC)
 fmt.Println("Destination MAC: ", ethernetPacket.DstMAC)
 fmt.Println("Ethernet type: ", ethernetPacket.EthernetType)
 fmt.Printf("From %s to %s\n", ip.SrcIP, ip.DstIP)
 fmt.Println("Protocol: ", ip.Protocol)
 fmt.Printf("From port %d to %d\n", tcp.SrcPort, tcp.DstPort)
 fmt.Println("Sequence number: ", tcp.Seq)

然后从包的应用层获取到payload,解析payload内容,判断是不是以“GET ”或者“POST ”开头的字符串,如果是的话就判定为http请求。然后使用正则表达式匹配出payload中的uri和host字段,并拼接出url。

package main

// Use tcpdump to create a test file
// tcpdump -w test.pcap
// or use the example above for writing pcap files

import (
	"fmt"
	"github.com/google/gopacket"
	"github.com/google/gopacket/layers"
	"github.com/google/gopacket/pcap"
	"log"
	"regexp"
	"strings"
)

var (
	pcapFile string = "http2.pcapng"
	handle   *pcap.Handle
	err      error
)

func main() {
	// Open file instead of device
	handle, err = pcap.OpenOffline(pcapFile)
	if err != nil {
		log.Fatal(err)
	}
	defer handle.Close()

	// Set filter
	var filter string = "tcp"
	err = handle.SetBPFFilter(filter)
	if err != nil {
		log.Fatal(err)
	}

	packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
	for packet := range packetSource.Packets() {
		// Do something with a packet here.
		//println(packet)
		printPacketInfo(packet)
	}
}

func printPacketInfo(packet gopacket.Packet) {
	// Let's see if the packet is an ethernet packet
	ethernetLayer := packet.Layer(layers.LayerTypeEthernet)
	if ethernetLayer != nil {
		ethernetPacket, _ := ethernetLayer.(*layers.Ethernet)

		//fmt.Println(reflect.TypeOf(ethernetPacket.EthernetType))
		if ethernetPacket.EthernetType.String() == "IPv4" {
			ipLayer := packet.Layer(layers.LayerTypeIPv4)
			if ipLayer != nil {
				ip, _ := ipLayer.(*layers.IPv4)

				// IP layer variables:
				// Version (Either 4 or 6)
				// IHL (IP Header Length in 32-bit words)
				// TOS, Length, Id, Flags, FragOffset, TTL, Protocol (TCP?),
				// Checksum, SrcIP, DstIP

				tcpLayer := packet.Layer(layers.LayerTypeTCP)
				if tcpLayer != nil {
					tcp, _ := tcpLayer.(*layers.TCP)

					// TCP layer variables:
					// SrcPort, DstPort, Seq, Ack, DataOffset, Window, Checksum, Urgent
					// Bool flags: FIN, SYN, RST, PSH, ACK, URG, ECE, CWR, NS

					applicationLayer := packet.ApplicationLayer()

					if applicationLayer != nil {
						payload := string(applicationLayer.Payload())
						if strings.HasPrefix(payload, "GET") || strings.HasPrefix(payload, "POST") {
							fmt.Println("--------------------------------------------------------------------")
							fmt.Println("Source MAC: ", ethernetPacket.SrcMAC)
							fmt.Println("Destination MAC: ", ethernetPacket.DstMAC)
							// Ethernet type is typically IPv4 but could be ARP or other
							fmt.Println("Ethernet type: ", ethernetPacket.EthernetType)
							fmt.Printf("From %s to %s\n", ip.SrcIP, ip.DstIP)
							fmt.Println("Protocol: ", ip.Protocol)
							fmt.Printf("From port %d to %d\n", tcp.SrcPort, tcp.DstPort)
							fmt.Println("Sequence number: ", tcp.Seq)

							//fmt.Printf("%s\n", applicationLayer.Payload())
							//a := packet.TransportLayer().TransportFlow()
							//fmt.Println(a.EndpointType())
							//fmt.Println("HTTP found!")
							//fmt.Println(payload)
							//解释正则表达式
							reg := regexp.MustCompile(`(?s)(GET|POST) (.*?) HTTP.*Host: (.*?)\n`)
							if reg == nil {
								fmt.Println("MustCompile err")
								return
							}
							//提取关键信息
							result := reg.FindStringSubmatch(payload)
							//fmt.Println(result)
							//fmt.Println(len(result))
							//fmt.Println(result[2], result[3])
							if len(result) == 4 {
								strings.TrimSpace(result[2])
								url := "http://" + strings.TrimSpace(result[3]) + strings.TrimSpace(result[2])
								fmt.Println("url:", url)
								fmt.Println("host:", result[3])
							} else {
								fmt.Println("error===================")
							}

						}

					}
				}
			}
		}
	}

}

 类似资料: