2

I am using the gopacket package and every time I have a TCP packet I want to check if the payload contains an HTTP request. Is there an easy way to do that instead of writing my own parser? There is also a function (see: func ReadRequest(b *bufio.Reader)) which returns a Request struct but I do not know what kind of input I should use. tcp.Payload is the byte[] array that seems to have the information I need to parse (see the following example):

// Get the TCP layer from this packet
if tcpLayer := packet.Layer(layers.LayerTypeTCP); tcpLayer != nil {
    fmt.Printf("TCP ")
    // Get actual TCP data from this layer
    tcp, _ := tcpLayer.(*layers.TCP)
    srcPort = tcp.SrcPort
    dstPort = tcp.DstPort
    if tcp.SYN {
        fmt.Print("[SYN] ")
    }
    if tcp.ACK {
        fmt.Print("[ACK] ")
    }
    if tcp.FIN {
        fmt.Print("[FIN] ")
    }
    fmt.Printf("%s:%d > %s:%d ", srcIP, srcPort, dstIP, dstPort)

    fmt.Println(string(tcp.Payload))
}

After sending an HTTP request I get the following output:

PKT [001] TCP [SYN] 192.168.2.6:59095 > 192.168.3.5:80
PKT [002] TCP [SYN] [ACK] 192.168.3.5:80 > 192.168.2.6:59095
PKT [003] TCP [ACK] 192.168.2.6:59095 > 192.168.3.5:80
PKT [004] TCP [ACK] 192.168.2.6:59095 > 192.168.3.5:80 GET /certificates/test.pdf HTTP/1.1
User-Agent: Wget/1.15 (linux-gnu)
Accept: */*
Host: 192.168.3.5
Connection: Keep-Alive

Any suggestions are welcome...

3
  • Do you mean you want to check if a packet has the start of an HTTP request? A single request is likely to span multiple packets. Commented Aug 22, 2016 at 14:50
  • Yes, let's go for the simple case where the payload has only one HTTP request and without missing parts Commented Aug 22, 2016 at 14:54
  • Yes, if the payload contains a the complete request you can feed it to http.ReadRequst. This simpler case isn't really useful, since you're operating on individual packets of a TCP stream. It fails immediately when you consider the possibility that a request can start in the middle of the packet payload, and it's still very likely that the request will span multiple packets. HTTP is at a higher level than TCP, and you need to reassemble the stream (flow) before you can parse the HTTP correctly. Commented Aug 22, 2016 at 15:08

1 Answer 1

1

With help from this question: How to parse http headers in Go the following attempt with http.ReadRequest() works...

if tcpLayer := packet.Layer(layers.LayerTypeTCP); tcpLayer != nil {
   tcp, _ := tcpLayer.(*layers.TCP)
   if len(tcp.Payload) != 0 {
      reader := bufio.NewReader(bytes.NewReader(tcp.Payload))
      httpReq, err := http.ReadRequest(reader)
      ...
  }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.