zl程序教程

您现在的位置是:首页 >  后端

当前栏目

Code a network packet sniffer in python for Linux

PythonLinuxcode for in Network packet
2023-09-14 08:59:45 时间
sudo python sniffer.py

The above sniffer works on the principle that a raw socket is capable of receiving all (of its type , like AF_INET) incoming traffic in Linux.

The output could look like this :


("E \x00x\xcc\xfc\x00\x000\x06j%J}G\x13\xc0\xa8\x01\x06\x01\xbb\xa3\xdc\x0b\xbeI\xbf\x1aF[\x83P\x18\xff\xff\x88\xf6\x00\x00\x17\x03\x01\x00\x1c\xbbT\xb3\x07}\xb0\xedqE\x1e\xe7;-\x03\x9bU\xb7\xb1r\xd2\x9e]\xa1\xb8\xac\xa4V\x9a\x17\x03\x01\x00*\xed\x1f\xda\xa4##Qe\x9a\xe9\xd6\xadN\xf4\x9b\xc4\xf0C\x01\xc4\x82\xdb\xb2\x8d(\xa5\xd0\x06\x95\x13WO\x0f\x8e\x1c\xa6f\x1d\xdf\xe1x", (74.125.71.19, 0))
  print Version :  + str(version) +  IP Header Length :  + str(ihl) +  TTL :  + str(ttl)+  Protocol :  + str(protocol) +  Source Address :  + str(s_addr) +  Destination Address :  + str(d_addr)
  print Source Port :  + str(source_port) +  Dest Port :  + str(dest_port) +  Sequence Number :  + str(sequence) +  Acknowledgement :  + str(acknowledgement) +  TCP header length :  + str(tcph_length)

The above code breaks down the packet into IP Header + TCP Header + Data.
The unpack function is used to break down the packet. Documentation

The output of the code should look like this :


Version : 4 IP Header Length : 5 TTL : 48 Protocol : 6 Source Address : 74.125.71.104 Destination Address : 192.168.1.6
Source Port : 80 Dest Port : 36454 Sequence Number : 3689394456 Acknowledgement : 2825932501 TCP header length : 5
Version : 4 IP Header Length : 5 TTL : 48 Protocol : 6 Source Address : 74.125.71.132 Destination Address : 192.168.1.6
Source Port : 80 Dest Port : 46534 Sequence Number : 2071060663 Acknowledgement : 2858668979 TCP header length : 5
Version : 4 IP Header Length : 5 TTL : 48 Protocol : 6 Source Address : 74.125.71.132 Destination Address : 192.168.1.6
Source Port : 80 Dest Port : 46533 Sequence Number : 377985304 Acknowledgement : 2869878012 TCP header length : 5
Version : 4 IP Header Length : 5 TTL : 48 Protocol : 6 Source Address : 74.125.71.17 Destination Address : 192.168.1.6
Source Port : 443 Dest Port : 59643 Sequence Number : 183723837 Acknowledgement : 3530935779 TCP header length : 5

If the IHL is 5 then total size is 20 bytes hence options+padding is absent.
For TCP packets the protocol is 6. Source address is the source IPv4 address in long format.

Next comes the TCP header :


and the balance after the TCP header is the data portion.

The C version of the code is here.
The Php version of the code is here.

Note :

1. The above sniffer picks up only TCP packets, because of the declaration :

s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP)

For UDP and ICMP the declaration has to be :

s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_UDP)
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP)

You might be tempted to think of doing :

s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_IP)

but this will not work , since IPPROTO_IP is a dummy protocol not a real one.

2. This sniffer picks up only incoming packets.

3. This sniffer delivers only IP frames , which means ethernet headers are not available.

Better Sniffer

Now let us see how we can overcome the above mentioned drawbacks. The solutions is quite simple.

This line :

s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP)

needs to be changed to :

s = socket.socket( socket.AF_PACKET , socket.SOCK_RAW , socket.ntohs(0×0003))

Now the same socket will receive :

1. All incoming and outgoing traffic.

2. All Ethernet frames , which means all kinds of IP packets(TCP , UDP , ICMP) and even other kinds of packets(like ARP) if there are any.

3. It will also provide the ethernet header as a part of the received packet.

Here is the source code :


#Convert a string of 6 characters of ethernet address into a dash separated hex string
  b = "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x" % (ord(a[0]) , ord(a[1]) , ord(a[2]), ord(a[3]),ord(a[4]) , ord(a[5]))
  print Destination MAC :  + eth_addr(packet[0:6]) +  Source MAC :  +eth_addr(packet[6:12]) +  Protocol :  + str(eth_protocol)
    print Version :  + str(version) +  IP Header Length :  + str(ihl) +  TTL :  +str(ttl) +  Protocol :  + str(protocol) +  Source Address :  + str(s_addr) +  Destination Address :  + str(d_addr)
      print Source Port :  + str(source_port) +  Dest Port :  + str(dest_port) +  Sequence Number :  + str(sequence) +  Acknowledgement :  + str(acknowledgement) +  TCP header length :  + str(tcph_length)
      print Type :  + str(icmp_type) +  Code :  + str(code) +  Checksum :  +str(checksum)
      print Source Port :  + str(source_port) +  Dest Port :  + str(dest_port) +  Length :  + str(length) +  Checksum :  + str(checksum)
Version : 4 IP Header Length : 5 TTL : 57 Protocol : 6 Source Address : 64.131.72.23 Destination Address : 192.168.1.6
Source Port : 80 Dest Port : 58928 Sequence Number : 1392138007 Acknowledgement : 2935013912 TCP header length : 6
Version : 4 IP Header Length : 5 TTL : 64 Protocol : 6 Source Address : 192.168.1.6 Destination Address : 64.131.72.23
Source Port : 58928 Dest Port : 80 Sequence Number : 2935013912 Acknowledgement : 1392138008 TCP header length : 5
Version : 4 IP Header Length : 5 TTL : 55 Protocol : 17 Source Address : 78.141.179.8 Destination Address : 192.168.1.6
Version : 4 IP Header Length : 5 TTL : 118 Protocol : 17 Source Address : 173.181.21.51 Destination Address : 192.168.1.6

It parses the Ethernet header and also the UDP and ICMP headers.

Ethernet header looks like this :


This kind of a sniffer does not depend on any external libraries like libpcap.

The C version of this code is here.

References :

1. Python Socket documentation.


一、今天在使用SSH,连接远程服务器的时候,刚开始是没问题的。 后来阿里云主机重装了一下系统后,再也连不上了。一直报一个错。