12

用Python获取本机网卡IP数据包

 3 years ago
source link: https://www.cnblogs.com/MikeZhang/archive/2012/08/30/pythonSniffer20120829.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

用Python获取本机网卡IP数据包

这几天用到了raw socket,用python写了些demo程序,这里记录下,也方便我以后查阅。

首先我们看一个简单的sniffer程序:

#! /usr/bin/python
# code for linux
import socket
#s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_UDP)
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP)
while True:
    print s.recvfrom(65535)

这里直接用raw socket接收数据,直接print操作。这个就几行代码,也没什么好解释的了,不懂的google下。

得到IP数据包后,接下来的工作就是对IP头进行解析,在这之前,我们先看看RFC中是怎么定义的(RFC791 : http://www.ietf.org/rfc/rfc791.txt ):

    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |Version|  IHL  |Type of Service|          Total Length         |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |         Identification        |Flags|      Fragment Offset    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |  Time to Live |    Protocol   |         Header Checksum       |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                       Source Address                          |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                    Destination Address                        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                    Options                    |    Padding    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

即对应的图:
2012083000201059.png
从RFC和上图中可以看到IP数据包头各个字段所占的位数,我们可以根据这些定义去解析IP数据包头,然后根据相应的策略处理数据。
这里给出一段用python实现的解析IP头的代码(呵呵,是demo中的代码,只解析了前20个字节,这里贴出来,欢迎拍砖……):
def decodeIpHeader(packet):
    mapRet = {}
    mapRet["version"] = (int(ord(packet[0])) & 0xF0)>>4
    mapRet["headerLen"] = (int(ord(packet[0])) & 0x0F)<<2
    mapRet["serviceType"] = hex(int(ord(packet[1])))
    mapRet["totalLen"] = (int(ord(packet[2])<<8))+(int(ord(packet[3])))
    mapRet["identification"] = (int( ord(packet[4])>>8 )) + (int( ord(packet[5])))
    mapRet["id"] = int(ord(packet[6]) & 0xE0)>>5
    mapRet["fragOff"] = int(ord(packet[6]) & 0x1F)<<8 + int(ord(packet[7]))
    mapRet["ttl"] = int(ord(packet[8]))
    mapRet["protocol"] = int(ord(packet[9]))
    mapRet["checkSum"] = int(ord(packet[10])<<8)+int(ord(packet[11]))
    mapRet["srcaddr"] = "%d.%d.%d.%d" % (int(ord(packet[12])),int(ord(packet[13])),int(ord(packet[14])), int(ord(packet[15])))
    mapRet["dstaddr"] = "%d.%d.%d.%d" % (int(ord(packet[16])),int(ord(packet[17])),int(ord(packet[18])), int(ord(packet[19])))
    return mapRet

调用代码:

proto = socket.getprotobyname('tcp') # only tcp
sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, proto)

while True:
    packet = sock.recvfrom(65535)[0]
    if len(packet) == 0:
        sck.close()
    else:
        #print str(packet)
        mapIpTmp = decodeIpHeader(packet)
        for k,v in mapIpTmp.items():
            print k,"\t:\t",v

    print ""    

Windows版本参考这里,有相应的demo,自己根据情况改写下啦。

好,就这些了,希望对你有帮助。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK