Я пытаюсь читать входящие/исходящие пакеты TCP через интерфейс на хосте для проекта, над которым я работаю , Я действительно хочу, чтобы это было сделано с использованием сокетов вместо использования библиотеки, например scapy или pypcap. Чтобы лучше понять, что происходит, а также больше контроля над тем, что происходит. Это в системе Windows10.Python socket.bind() для хоста не отображает входящие пакеты с SIO_RCVALL при обнюхивании для трафика на интерфейсе
import socket
import threading
from PacketParse import PacketParse
host = socket.gethostbyname(socket.gethostname())
sniff = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_IP)
sniff.bind((host, 0))
#include ip headers - IP PROTOCOL, IP HEADER INCLUDE
sniff.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
#receive all packages - INPUT OUTPUT CONTROL
sniff.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)
def start_sniffing():
while True:
raw_packet = sniff.recvfrom(2000)
packet = PacketParse(raw_packet)
if packet:
print(packet.src_addr + ":" + str(packet.src_port) + " --> " + packet.dst_addr + ":" + str(packet.dst_port) + " Protocol: " + packet.ip_prot + "(" + str(packet.ip_prot_raw) + ")")
print("Data(" + str(packet.data_size) + "): " + str(packet.data))
#file.write(packet.src_addr + ":" + str(packet.src_port) + " --> " + packet.dst_addr + ":" + str(packet.dst_port) + " Protocol: " + packet.ip_prot + "(" + str(packet.ip_prot_raw) + ")")
#file.write("Data(" + str(packet.data_size) + "): " + str(packet.data))'''
file = open("dump.txt", "a")
t = threading.Thread(target=start_sniffing)
t.start()
t.join()
file.close()
sniff.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)
PacketParse - класс, который я сделал, чтобы «распаковать» пакет. Я использую документацию Python для большей части этого скрипта и учебников для обнюхивания пакетов из многих источников.
from struct import unpack
class PacketParse:
def __init__(self, packet):
self.extract(packet)
def extract(self, packet):
# extract ip header
packet = packet[0]
self.packet_raw = packet
'''
eth_raw = packet[:14]
eth_hdr = unpack('!6s6sH', eth_raw)
self.eth_prot = socket.ntohs(eth_hdr[2])
self.src_mac =
'''
ip_raw = packet[0:20]
ip_hdr = unpack('!BBHHHBBH4s4s', ip_raw)
#self.ip_length = ip_hdr[5]
self.ip_prot_raw = ip_hdr[6]
self.ip_prot = self.ip_prot_parse(ip_hdr[6])
self.src_addr = socket.inet_ntoa(ip_hdr[8])
self.dst_addr = socket.inet_ntoa(ip_hdr[9])
version = ip_hdr[0] >> 4
ihl_length = version & 0xF
iph_len = ihl_length * 4
tcp_raw = packet[20:40]
tcp_hdr = unpack('!HHLLBBHHH', tcp_raw)
self.src_port = tcp_hdr[0]
self.dst_port = tcp_hdr[1]
self.seq_num = tcp_hdr[2]
self.ack_num = tcp_hdr[3]
doff_reserved = tcp_hdr[4]
tcp_length = doff_reserved >> 4
header_size = (iph_len) + (tcp_length * 4)
self.data_size = len(packet) - header_size
self.data = packet[header_size:]
def ip_prot_parse(self, num):
return {
1: 'ICMP',
6: 'TCP',
17: 'UDP',
}.get(num, "Unknown")
Проблема заключается только в том, что пакеты отправляются с этого хоста. Входящие пакеты не отображаются. Другой скрипт, который я пытался использовать scapy, также способен отображать входящие пакеты. Почему это происходит? SIO_RCVALL должен разрешать доступ ко всем пакетам с помощью интерфейса, который нужно увидеть. Я не пробовал эквивалент Linux этого скрипта ... поэтому я не знаю, является ли проблема конкретной для Windows. Большинство скриптов чтения TCP, которые я нашел, были специфичными для Linux.
какое значение имеет 'host'? если 127.0.0.1, то вы получаете только локальные пакеты. Возможно, используйте стандартный '0.0.0.0' для получения от всех сетевых карт (Netwok Cinterface Cards). Как я знаю, программа нуждается в библиотеке 'pcap', чтобы тегировать все пакеты, даже не добавляемые на этот компьютер (если только коммутатор посылает вопросы на ваш компьютер) – furas
Значение хоста - 192.168.2.110': локальный адрес моего компьютера. Изменение хоста на «0.0.0.0» или '' '' не отображает никаких пакетов ... но по какой-то причине я получаю сообщение об ошибке с 'sniff.ioctl' при использовании' 0.0.0.0'. 'sniff.ioctl (socket.SIO_RCVALL, socket.RCVALL_ON) OSError: [WinError 10022] Был указан недопустимый аргумент' – David