0
votes

I'm writing a kernel module in C, and trying to get the Host field from a TCP packet's payload, carrying http request headers. I've managed to do something similar with FTP (scan the payload and look for FTP commands), but I can't seem to be able to do the same and find the field.

My module is connected to the POST_ROUTING hook. each packet that goes to that hook, if it has a dst port of 80, is being recognized as an HTTP packet, and so my module starts to parse it.
for some reason, I can't seem to be able to get the HOST line (matter of fact, I only see the server HTTP 200 ok)

are these headers always go on the packets that use port 80? if so, what is the best way to parse those packt's payload? seems like going char by char is a lot of work. is there any better way?

Thanks

EDIT: Got some progress. every packet I get from the server, I can read the payload with no problem. but every packet I send - it's like the payload is empty.

I thought it's a problem of skb pointer, but i'm getting the TCP ports fine. just can't seem to read this damn payload. this is how i parse it:

unsigned char* user_data = (unsigned char *)((int)tcphd + (int)(tcphd->doff * 4));
unsigned char *it;
for (it = user_data; it != tail; ++it) {
    unsigned char c = *(unsigned char *)it;

    http_command[http_command_index] = c;
    http_command_index++;
}

where tail:

 tail = skb_tail_pointer(skb);

The pointer doesn't advance at all on the loop. it's like it's empty from the start or something, and I can't figure out why. help, please.

1
So what does Wireshark tell you? - alk
HTTP 200 ok going to port 80? Really? - alk
I've managed to see the packts with wireshark. and HTTP 200 wasn't on port 80, but the port that I used to create the TCP connection. now I can see the packet, but still can't parse it. - TzurEl
What's wrong with pcap? - a3f
TCP is a byte stream. Unlike UDP, TCP has no concept of message boundaries. TCP does not guarantee any given multi-byte value, whether an integer or a character string, will be contained in a single TCP packet, it may span across packet boundaries. You have to account for that. FTP, HTTP, these are application-level protocols on top of TCP. You need to parse TCP payloads according to the rules of the protocol being used, not the individual packets. So you will have to cache the payload data into a separate buffer, parsing the buffer as new data is added to it... - Remy Lebeau

1 Answers

0
votes

I've managed to solve this.

using this , I've figured out how to parse all of the packet's payload. I hope this code explains it

int http_command_offset = iphd->ihl*4 + tcphd->doff*4; 
int http_command_length = skb->len - http_command_offset;
http_command =  kmalloc(http_command_length + 1, GFP_ATOMIC);
skb_copy_bits(skb, http_command_offset , (void*)http_command, http_command_length);

skb_cop_bits, just copies the payload entirely into the buffer i've created. parsing it now is pretty simple.