最近有个预研工作,涉及到SIP和HTTPS报文的抓包和数据分析,正好可以使用gopacket进行一番实践,在这里记录一下学习心得。
首先从最基本的gopacket抓包开始
1 func pcapStartLoop(cfg *PcapDataConfigs, packetListener func(packet gopacket.Packet)) { 2 logger.Info("Try start open-live device for pcap : ", cfg) 3 handle, err := pcap.OpenLive(cfg.Device, cfg.SnapshotLen, cfg.Promiscuous, cfg.Timeout) 4 // 参数含义依次为:网卡设备名,可根据ifconfig输出确定;单次抓取报文的存储缓冲区最大长度,比如普通计算机的TCP报文长度为1514字节,若设置为1500,则可能会被截断,因此,需要设置为合适的大小;是否混淆模式,其影响后续再通过试验进行分析;超时时间 5 if err != nil { 6 logger.Error(err) 7 return 8 } 9 defer func() { 10 handle.Close() 11 handle = nil 12 }() 13 14 if cfg.Filters != "" { 15 err = handle.SetBPFFilter(cfg.Filters)//设置过滤规则 16 if err != nil { 17 logger.Error(err) 18 return 19 } 20 logger.Info("Only capturing packets for filters : " + cfg.Filters) 21 } 22 23 packetSource := gopacket.NewPacketSource(handle, handle.LinkType()) 24 for packet := range packetSource.Packets() { 25 packetListener(packet) 26 packetCount++ 27 if cfg.MaxPacketCount > 0 && packetCount >= cfg.MaxPacketCount { 28 break 29 } 30 } 31 }
抓到报文后进行解析:
1 func parsePacket(packet gopacket.Packet) { 2 for _, layer := range packet.Layers() { 3 switch layer.LayerType() { 4 case layers.LayerTypeEthernet: 5 parseEthernetLayer(layer) 6 case layers.LayerTypeIPv4: 7 parseIPV4Layer(layer) 8 case layers.LayerTypeTCP: 9 parseTcpLayer(layer) 10 case layers.LayerTypeUDP: 11 parseUdpLayer(layer) 12 default: 13 logger.Info("- ", layer.LayerType()) 14 } 15 } 16 //parseEthernetLayer(packet) 17 //parseIPV4Layer(packet) 18 } 19 20 func parseEthernetLayer(layer gopacket.Layer) { 21 logger.Info("Ethernet layer detected.") 22 ethernetPacket, _ := layer.(*layers.Ethernet) 23 logger.Info("Source MAC: ", ethernetPacket.SrcMAC) 24 logger.Info("Destination MAC: ", ethernetPacket.DstMAC) 25 logger.Info("Ethernet type: ", ethernetPacket.EthernetType) 26 } 27 28 func parseIPV4Layer(layer gopacket.Layer) { 29 logger.Info("IPv4 layer detected.") 30 ip, _ := layer.(*layers.IPv4) 31 32 logger.Infof("From %s to %s\n", ip.SrcIP, ip.DstIP) 33 logger.Info("Protocol: ", ip.Protocol) 34 } 35 36 func parseTcpLayer(layer gopacket.Layer) { 37 logger.Info("TCP layer detected.") 38 tcp, _ := layer.(*layers.TCP) 39 40 logger.Infof("From %s to %s\n", tcp.SrcPort, tcp.DstPort) 41 42 //tcpassembly.NewAssembler(nil) 43 44 } 45 46 func parseUdpLayer(layer gopacket.Layer) { 47 logger.Info("UDP layer detected.") 48 udp, _ := layer.(*layers.UDP) 49 50 logger.Infof("From %s to %s\n", udp.SrcPort, udp.DstPort) 51 logger.Infof("UDP payload is %s \n", string(udp.Payload)) 52 }
好,到此为止,报文已经可以抓取并打印到控制台上了。
其他见下文。
-----------------------
张作桃