网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
包捕获
sniffer Run
func (s *Sniffer) Run() error {
handle, err := s.open()
if err != nil {
return fmt.Errorf("failed to start sniffer: %w", err)
}
defer handle.Close()
var w *pcapgo.Writer
if s.config.Dumpfile != "" {
f, err := os.Create(s.config.Dumpfile)
if err != nil {
return err
}
defer f.Close()
w = pcapgo.NewWriterNanos(f)
err = w.WriteFileHeader(65535, handle.LinkType())
if err != nil {
return fmt.Errorf("failed to write dump file header to %s: %w", s.config.Dumpfile, err)
}
}
decoder, err := s.decoders(handle.LinkType())
if err != nil {
return err
}
// Mark inactive sniffer as active. In case of the sniffer/packetbeat closing
// before/while Run is executed, the state will be snifferClosing.
// => return if state is already snifferClosing.
if !s.state.CAS(snifferInactive, snifferActive) {
return nil
}
defer s.state.Store(snifferInactive)
var packets int
for s.state.Load() == snifferActive {
if s.config.OneAtATime {
fmt.Fprintln(os.Stdout, "Press enter to read packet")
fmt.Scanln()
}
data, ci, err := handle.ReadPacketData()
if err == pcap.NextErrorTimeoutExpired || isAfpacketErrTimeout(err) { //nolint:errorlint // pcap.NextErrorTimeoutExpired is not wrapped.
logp.Debug("sniffer", "timedout")
continue
}
if err != nil {
// ignore EOF, if sniffer was driven from file
if err == io.EOF && s.config.File != "" { //nolint:errorlint // io.EOF should never be wrapped.
return nil
}
s.state.Store(snifferInactive)
return fmt.Errorf("sniffing error: %w", err)
}
if len(data) == 0 {
// Empty packet, probably timeout from afpacket.
continue
}
packets++
if w != nil {
err = w.WritePacket(ci, data)
if err != nil {
return fmt.Errorf("failed to write packet %d: %w", packets, err)
}
}
logp.Debug("sniffer", "Packet number: %d", packets)
// 解析包
decoder.OnPacket(data, &ci)
}
return nil
}
decoder OnPacket
func (d *Decoder) OnPacket(data []byte, ci *gopacket.CaptureInfo) {
defer logp.Recover("packet decoding failed")
d.truncated = false
current := d.linkLayerDecoder
currentType := d.linkLayerType
packet := protos.Packet{Ts: ci.Timestamp}
debugf("decode packet data")
processed := false
if d.flowID != nil {
d.flowID.Reset(d.flowIDBufferBacking[:0])
// suppress flow stats snapshots while processing packet
d.flows.Lock()
defer d.flows.Unlock()
}
for len(data) > 0 {
err := current.DecodeFromBytes(data, d)
if err != nil {
logp.Info("packet decode failed with: %v", err)
break
}
nextType := current.NextLayerType()
data = current.LayerPayload()
// 分发
processed, err = d.process(&packet, currentType)
if err != nil {
logp.Info("Error processing packet: %v", err)
break
}
if processed {
break
}
// choose next decoding layer
next, ok := d.decoders[nextType]
if !ok {
break
}
// jump to next layer
current = next
currentType = nextType
}
// add flow s.tats
if d.flowID != nil {
debugf("flow id flags: %v", d.flowID.Flags())
}
if d.flowID != nil && d.flowID.Flags() != 0 {
flow := d.flows.Get(d.flowID)
d.statPackets.Add(flow, 1)
d.statBytes.Add(flow, uint64(ci.Length))
}
}
decoder process
func (d *Decoder) process(
packet *protos.Packet,
layerType gopacket.LayerType,
) (bool, error) {
withFlow := d.flowID != nil
switch layerType {
case layers.LayerTypeEthernet:
if withFlow {
d.flowID.AddEth(d.eth.SrcMAC, d.eth.DstMAC)
}
case layers.LayerTypeDot1Q:
d1q := &d.d1q[d.stD1Q.i]
d.stD1Q.next()
if withFlow {
d.flowID.AddVLan(d1q.VLANIdentifier)
}
case layers.LayerTypeIPv4:
debugf("IPv4 packet")
ip4 := &d.ip4[d.stIP4.i]
d.stIP4.next()
if withFlow {
d.flowID.AddIPv4(ip4.SrcIP, ip4.DstIP)
}
packet.Tuple.SrcIP = ip4.SrcIP
packet.Tuple.DstIP = ip4.DstIP
packet.Tuple.IPLength = 4
case layers.LayerTypeIPv6:
debugf("IPv6 packet")
ip6 := &d.ip6[d.stIP6.i]
d.stIP6.next()
if withFlow {
d.flowID.AddIPv6(ip6.SrcIP, ip6.DstIP)
}
packet.Tuple.SrcIP = ip6.SrcIP
packet.Tuple.DstIP = ip6.DstIP
packet.Tuple.IPLength = 16
case layers.LayerTypeICMPv4:
debugf("ICMPv4 packet")
d.onICMPv4(packet)
return true, nil
case layers.LayerTypeICMPv6:
debugf("ICMPv6 packet")
d.onICMPv6(packet)
return true, nil
case layers.LayerTypeUDP:
debugf("UDP packet")
d.onUDP(packet)
return true, nil
case layers.LayerTypeTCP:
debugf("TCP packet")
d.onTCP(packet)
return true, nil
}
![img](https://img-blog.csdnimg.cn/img_convert/2067d9e69238b45f10092b28dc375a54.png)
![img](https://img-blog.csdnimg.cn/img_convert/0a9824138d9ca1dbb6c11f170054c1bf.png)
![img](https://img-blog.csdnimg.cn/img_convert/c44e75e46e0f8996440c523db538f7ab.png)
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!**
**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**
**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618658159)**
[外链图片转存中...(img-i38pNvak-1715817663732)]
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!**
**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**
**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618658159)**