OpenGFW
OpenGFW copied to clipboard
增加对pcap的支持以方便调试
如题
附上简易实现代码
io/pcap.go
package io
import (
"context"
"hash/crc32"
"sort"
"strings"
"time"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
"github.com/google/gopacket/pcap"
)
var _ PacketIO = (*pcapPacketIO)(nil)
type pcapPacketIO struct {
pcap *pcap.Handle
lastTime *time.Time
}
func NewPcapPacketIO(pcapFile string) (PacketIO, error) {
handle, err := pcap.OpenOffline(pcapFile)
if err != nil {
return nil, err
}
return &pcapPacketIO{
pcap: handle,
lastTime: nil,
}, nil
}
func (n *pcapPacketIO) Register(ctx context.Context, cb PacketCallback) error {
go func() {
packetSource := gopacket.NewPacketSource(n.pcap, n.pcap.LinkType())
for packet := range packetSource.Packets() {
if n.lastTime == nil {
n.lastTime = &packet.Metadata().Timestamp
} else {
t := packet.Metadata().Timestamp.Sub(*n.lastTime)
time.Sleep(t)
n.lastTime = &packet.Metadata().Timestamp
}
ethernetLayer := packet.Layer(layers.LayerTypeEthernet)
var id uint32 = 0
var address []string
if ethernetLayer.(*layers.Ethernet).EthernetType == 0x0800 {
ipLayer := packet.Layer(layers.LayerTypeIPv4)
ipPacket := ipLayer.(*layers.IPv4)
address = append(address, string(ipPacket.DstIP))
address = append(address, string(ipPacket.SrcIP))
}
if ethernetLayer.(*layers.Ethernet).EthernetType == 0x86DD {
ipLayer := packet.Layer(layers.LayerTypeIPv6)
ipPacket := ipLayer.(*layers.IPv6)
address = append(address, string(ipPacket.DstIP))
address = append(address, string(ipPacket.SrcIP))
}
if len(address) != 0 {
sort.Sort(sort.StringSlice(address))
id = crc32.Checksum([]byte(strings.Join(address, ",")), crc32.IEEETable)
}
cb(&pcapPacket{
streamID: id,
data: ethernetLayer.LayerPayload(),
}, nil)
}
}()
return nil
}
func (n *pcapPacketIO) SetVerdict(p Packet, v Verdict, newPacket []byte) error {
return nil
}
func (n *pcapPacketIO) Close() error {
return nil
}
var _ Packet = (*pcapPacket)(nil)
type pcapPacket struct {
streamID uint32
data []byte
}
func (p *pcapPacket) StreamID() uint32 {
return p.streamID
}
func (p *pcapPacket) Data() []byte {
return p.data
}