代码拉取完成,页面将自动刷新
package pcaphelper
import (
"io"
"net"
"time"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
"github.com/google/gopacket/pcap"
"github.com/pkg/errors"
)
// OnTrHook 发射包的钩子函数
type OnTrHook func([]byte) []byte
// WriteRaw 将给定的数据注入 pcap 句柄
func (p *PcapHelper) WritePacketData(bytes []byte) error {
return p.handle.WritePacketData(bytes)
}
// PlayPCAPFile 播放 pcap 文件,支持 bpf 过滤文件中的报文,可以设置或重置发包间隔,通过 hook 修改每一个数据包的内容
// 当 interval<0 将无间隔播放;当 interval=0 按 pcap 文件中默认的间隔播放,当 interval>0 时按 interval 间隔播放
func (p *PcapHelper) PlayPCAPFileWithHook(file, bpfExpr string, interval time.Duration, onTr OnTrHook) error {
handleRead, err := pcap.OpenOffline(file)
if err != nil {
return errors.Wrap(err, "open PCAP file")
}
if err := handleRead.SetBPFFilter(bpfExpr); err != nil {
return errors.Wrap(err, "set BPF filter on handle reader")
}
var (
sentCount int
lastPktTimestamp time.Time
)
for {
// read packet from handle
data, ci, err := handleRead.ReadPacketData()
if err != nil {
if err == io.EOF {
return nil
}
return errors.Wrap(err, "failed to read packet")
}
if ci.CaptureLength != ci.Length {
continue // do not write truncated packets
}
// interval time
if sentCount != 0 {
switch {
case interval == 0:
time.Sleep(ci.Timestamp.Sub(lastPktTimestamp))
case interval > 0:
time.Sleep(interval)
case interval < 0:
// no pause
}
}
data = onTr(data)
if data == nil {
continue
}
if err := p.WritePacketData(data); err != nil {
return errors.Wrap(err, "failed to write packet")
}
lastPktTimestamp = ci.Timestamp
sentCount++
}
}
// PlayPCAPFile 播放 pcap 文件,支持 bpf 过滤文件中的报文,可以设置或重置发包间隔
func (p *PcapHelper) PlayPCAPFile(file, bpfExpr string, interval time.Duration) error {
return p.PlayPCAPFileWithHook(file, bpfExpr, interval, func(bytes []byte) []byte { return bytes })
}
// MakeHookMutateEth 修改以太网层的 来源MAC 和 目的MAC
func MakeTrHookThatMutateEth(srcMAC, dstMAC net.HardwareAddr) OnTrHook {
return func(bytes []byte) []byte {
var (
pkt = gopacket.NewPacket(bytes, layers.LayerTypeEthernet, gopacket.Default)
eth = new(layers.Ethernet)
ethPayload = make(gopacket.Payload, 0, len(bytes))
buffer = gopacket.NewSerializeBuffer()
)
if ethLayer := pkt.Layer(layers.LayerTypeEthernet); ethLayer != nil {
eth = ethLayer.(*layers.Ethernet)
if srcMAC != nil {
eth.SrcMAC = srcMAC
}
if dstMAC != nil {
eth.DstMAC = dstMAC
}
if eth.Payload != nil {
ethPayload = eth.Payload
}
_ = gopacket.SerializeLayers(buffer, gopacket.SerializeOptions{ComputeChecksums: true, FixLengths: true},
eth, ethPayload,
)
return buffer.Bytes()
}
return bytes
}
}
// MakeHookMutateEthIP4 修改以太网层的 来源MAC 和 目的MAC,IP4 层的 源IP 和 目的IP
func MakeTrHookThatMutateEthIP4(srcMAC, dstMAC net.HardwareAddr, srcIP, dstIP net.IP) OnTrHook {
return func(bytes []byte) []byte {
var (
pkt = gopacket.NewPacket(bytes, layers.LayerTypeEthernet, gopacket.Default)
eth = new(layers.Ethernet)
ip4 = new(layers.IPv4)
ip4Payload = make(gopacket.Payload, 0, len(bytes))
buffer = gopacket.NewSerializeBuffer()
)
if ethLayer := pkt.Layer(layers.LayerTypeEthernet); ethLayer != nil {
eth = ethLayer.(*layers.Ethernet)
if srcMAC != nil {
eth.SrcMAC = srcMAC
}
if dstMAC != nil {
eth.DstMAC = dstMAC
}
}
if ip4Layer := pkt.Layer(layers.LayerTypeIPv4); ip4Layer != nil {
ip4 = ip4Layer.(*layers.IPv4)
if srcIP != nil {
ip4.SrcIP = srcIP
}
if dstIP != nil {
ip4.DstIP = dstIP
}
if ip4.Payload != nil {
ip4Payload = ip4.Payload
}
_ = gopacket.SerializeLayers(buffer, gopacket.SerializeOptions{ComputeChecksums: true, FixLengths: true},
eth, ip4, ip4Payload,
)
return buffer.Bytes()
}
return bytes
}
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。