Pythonrawソケットは単純なスニファーを実装します



Python Raw Socket Implements Simple Sniffer



何:

rawソケット、つまりrawソケットは、ローカルネットワークカードでデータフレームまたはデータパケットを受信できます。これは、ネットワークトラフィックの監視と分析に非常に役立ちます。




どこ:

このソケットを作成するには、次の4つの方法があります。



1.ソケット(PF_INET、SOCK_RAW、IPPROTO_TCP | IPPROTO_UDP | IPPROTO_ICMP)は、IPデータパケットを送受信します

ソケット(AF_INET、SOCK_RAW、IPPROTO_UDP)

ソケットは、プロトコルタイプ(tcp udp icmpなど)でこのマシンに送信されたIPデータパケットを受信でき、ローカルIPに送信されていないデータパケットを受信できません(ipソフトフィルタリングは、に送信されていないこれらのデータを破棄します)ローカルIPパケット)、このマシンから送信されたデータパケットを受信できません。



送信するときは、tcp udp icmpおよびその他のヘッダーを自分で整理する必要があり、setsockoptでipヘッダーをラップできます。

pingプログラムに適しています

2.socket(PF_PACKET、SOCK_RAW、htons(ETH_P_IP | ETH_P_ARP | ETH_P_ALL))イーサネットデータフレームを送受信します

ソケット(AF_PACKET、SOCK_RAW、htons(x))

このソケットを作成して、ネットワークカード上のすべてのデータフレームを監視します。

ETH_P_IP0x800ローカルMacに送信されたIPタイプのデータフレームのみを受信します

ETH_P_ARP0x806ローカルMacに送信されたarpタイプのデータフレームのみを受け入れる

ETH_P_RARP0x8035ローカルMacに送信されたrarpタイプのデータフレームのみを受け入れる

ETH_P_ALL0x3ローカルMacに送信されたすべてのタイプのiparp rarpデータフレームを受信し、ローカルマシンから送信されたすべてのタイプのデータフレームを受信します。 (プロミスキャスモードをオンにすると、ローカルMacに送信されないデータフレームが受信されます)

3.socket(PF_PACKET、SOCK_DGRAM、htons(ETH_P_IP | ETH_P_ARP | ETH_P_ALL))イーサネットデータフレーム(イーサネットヘッダーを除く)を送受信します。

ソケット(AF_PACKET、SOCK_DGRAM、htons(x))

この機能は2番目の機能と似ていますが、イーサネットヘッダーは含まれていません。

彼は非IPプロトコルパケットを受信できます

4.ソケット(PF_INET、SOCK_PACKET、htons(ETH_P_IP | ETH_P_ARP | ETH_P_ALL))

ソケット(AF_INET、SOCK_PACKET、htons(ETH_P_ALL))

一般的にパケットキャプチャプログラムに使用されます


なぜ:

rawソケットと標準ソケットの違いは次のとおりです。

元のソケットはカーネルが処理していないIPパケットの読み取りと書き込みを行うことができますが、ストリームソケットはTCPプロトコルのデータのみを読み取ることができ、データグラムソケットはUDPプロトコルのデータのみを読み取ることができます。したがって、他のプロトコルにアクセスしてデータを送信する場合は、元のソケットを使用する必要があります。

画像

画像

画像


どうやって:

画像

画像

Pythonは単純なスニファを実装します

  1. ネットワークカードを無差別モードにします
  2. パケットをキャプチャする
  3. データパケットを分析します。
  4. 無差別モードをオフにする
import socket # the public network interface HOST = socket.gethostbyname(socket.gethostname()) # create a raw socket and bind it to the public interface s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_IP) s.bind((HOST, 0)) # Include IP headers s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1) # receive all packages s.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON) # receive a package print(s.recvfrom(65565)) # disabled promiscuous mode s.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)

ipパケットを解析します。

画像

import socket #Capture def sniffIpData(): host_ip = socket.gethostbyname(socket.gethostname()) #Get IP sniffer = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_IP) #Create socket, acceptable protocol types are UDP, TCP, ICMP, IP sniffer.bind((host_ip, 0)) sniffer.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1) #Set socket options, wrap ip header sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON) #receive all package recv_data, addr = sniffer.recvfrom(1500) s.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF) # disabled promiscuous mode sniffer.close() return recv_data #Analysis def decodeIpData(package): ip_data = {} #RFC791 ip_data['version'] = package[0] >> 4 ip_data['headLength'] = package[0] & 0x0f #& Bitwise AND operation ip_data['DSField'] = package[1] ip_data['totalLength'] = (package[2] << 8) + package[3] ip_data['identification'] = (package[4] << 8) + package[5] ip_data['flag'] = package[6] >> 5 ip_data['moreFragment'] = ip_data['flag'] & 1 ip_data['dontFragment'] = (ip_data['flag'] >> 1) & 1 ip_data['fragmentOffset'] = ((package[6] & 0x1f) << 8) + package[7] ip_data['TTL'] = package[8] ip_data['protocol'] = package[9] ip_data['headerCheckSum'] = (package[10] << 8) + package[11] #Store in the form of IP address ip_data['sourceAddress'] = '%d.%d.%d.%d' % (package[12], package[13], package[14], package[15]) ip_data['destinationAddress'] = '%d.%d.%d.%d' % (package[16], package[17], package[18], package[19]) ip_data['options'] = [] #Find options based on headerLength if ip_data['headLength'] > 5: #Generally speaking, the value here is 0101, which means the header length is 20 bytes, if it exceeds, it is greater than 5 (0101) temp = 5 while temp < ip_data['headLength']: ip_data['options'].append(package[temp * 4] + 0) ip_data['options'].append(package[temp * 4] + 1) ip_data['options'].append(package[temp * 4] + 2) ip_data['options'].append(package[temp * 4] + 3) temp += 1 #Find data according to totalLength ip_data['data'] = [] temp = ip_data['headLength'] * 4 while temp < ip_data['totalLength']: ip_data['data'].append(package[temp]) temp += 1 return ip_data package = sniffIpData() data_decode = decodeIpData(package) # for i, k in data_decode: # print('%d:%d' % (i, k)) for key in data_decode.items(): print(key)

これまでのところ、単純なバージョンが実装されています。

画像