Code a network packet sniffer in PHP

Example of a packet sniffer is Wireshark. Packet sniffers pick up the packets going in and out of a system and analyse them and present them to user for further analysis.

In this post we are going to code a simple packet sniffer in php. The basic theory this packet sniffer is that , raw packets can sniff without much effort if they are put into receiving mode. This will work only on a Linux system , since we cannot create raw sockets on windows.

The IHL (IP Header Length) contains the length of the ip header / 4. So if its value is 5 then header length is 20 bytes. Generally header length is 5 and options and padding is not there. If options and padding is present then length would be 6. This has to be checked first before moving to the next part that is TCP header.

Since the $buf contains data in binary format , it needs to be unpacked using the unpack function of php. The unpack string should be:

12 thoughts on “Code a network packet sniffer in PHP”

Hi,
I saw the comments on problematic receiving raw socket headers, But the comments & replies seemed pretty much out-of subject. IS there any solution for receiving raw socket headers using php??
Already tried in administrate mode, but i am getting no response (not even errors, after setting error_reporting(E_ALL) ).

I tried your PHP sniffer for TCP connections and it works fine.
I would like to get a PHP sniffer to be able to get IGMP messages (not data) : like IGMP join, leave, issued on 224.0.0.22 but other IGMP messages as well.

I receive some data but at this time I did not code IP/IGMP packet decoding (I lack information about its structure), and I only get some “0” when transcoding incoming buffer to hexadecimal.
Can you tell me if I am right with this code or would I have to change something ?

Your code hold my attention so i tried it. While encountering no problem to start it and get the “Starting sniffing…\n” output I did not manage to capture any packet. Am I understanding the thing wrongly if I think this sniffer should be able to capture the packets sent and received when a page is loaded in a browser on my machine ?
I am wondering if the socket may be bound to the wrong interface (like lo0) thus receiving nothing.
Any idea ?

yes, the sniffer will capture packets that are received by the browser.
the program should be run with root privileges (sudo on ubuntu for example).
without root it will not be able to capture packets, because it uses raw sockets which require root privileges.
if the interface is correct, the program should pickup packets.

yes the script ran with root privileges through sudo (that’s why i got the start sniffing output and no errors). My question is how do I select the interface ? How do I know with interface the script reads from ?
The problem is not a privilege thing or something related to PHP i think because after compiling and running the same script in C (posted on this blog too) I got the same result. That is everything is set up correctly but no packet is captured…

Thanks a lot for your quick answer and for the SO_BINDTODEVICE explanation. It gave me access to a brand new field of google results :)

FYI, the SO_BINDTODEVICE option is not defined on *BSD systems (as Darwin/OS X). There is actually no way (unless the socket is multicast) to determine the interface it is bound to. This seems to be made automatically based on the routing table.

But the reason for getting nothing does not come from a wrong interface problem….

Quoting a post from http://stackoverflow.com/questions/6878603/strange-raw-socket-on-mac-os-x :
”
FreeBSD takes another approach. It *never* passes TCP or UDP packets to raw
sockets. Such packets need to be read directly at the datalink layer by using
libraries like libpcap or the bpf API. It also *never* passes any fragmented
datagram. Each datagram has to be completeley reassembled before it is passed
to a raw socket.
FreeBSD passes to a raw socket:
a) every IP datagram with a protocol field that is not registered in
the kernel
b) all IGMP packets after kernel finishes processing them
c) all ICMP packets (except echo request, timestamp request and address
mask request) after kernel finishes processes them
”

So, bad news, it won’t be possible to make a sniffer in PHP for OS X. Even opening /dev/bpf and try to read from it won’t give any result as the stream must be setup via ioctl calls and I see no way to do that from PHP (without coding an extension).

I am trying to run it, but can’t create the socket. How do you specify to run it as sudo to view/run the script in a browser (I have it saved in: htdocs/sniff/sniffer.php)? Your suggestion of “sudo php sniffer.php” from the command line results in a command not found msg.

Follow us

This site, binarytides.com is a participant in the Amazon Services LLC Associates Program, an affiliate advertising program designed to provide a means for sites to earn advertising fees by advertising and linking to Amazon.com.