Анализ пакетов ICMP без получения данных (Black Hat Python Book) - PullRequest
1 голос
/ 01 августа 2020

Я наткнулся на этот фрагмент кода из книги, Black hat Python, Глава 3. Сеть: Raw Sockets и Sniffing:

import socket
import os

host = "x.x.x.x"        # Host to listen on

# Create a raw socket and bind it to the public interface
if os.name == "nt":
    socket_protocol = socket.IPPROTO_IP
else:
    socket_protocol = socket.IPPROTO_ICMP
    
sniffer = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket_protocol)
sniffer.bind((host, 0))
sniffer.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)     # We want the IP headers included in the capture
# if we're using Windows, we need to send an IOCTL
# to set up promiscuous mode
if os.name == "nt":
    sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)
print(sniffer.recvfrom(65565))      # Read in a single packet

# If we're using Windows, turn off promiscuous mode
if os.name == "nt":
    sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)

И когда я это сделаю ping google.com приведенный выше код должен захватить первый пакет ping, но вместо этого ждет пакета бесконечно в строке print(sniffer.recvfrom(65565)).

Я пробовал с host в качестве локального ip и с localhost, и попытался изменить размер буфера, как показано в аналогичном вопросе . Но это не помогло.

Я работаю, когда устанавливаю host = "" и делаю ping 127.0.0.1, но не когда я пингую другие URL-адреса.

Может кто-нибудь, пожалуйста, скажите мне, что не так?

Я использую Python 3.8.2 и Ubuntu 18.04.

1 Ответ

1 голос
/ 01 августа 2020

Проблема на самом деле не в коде, это проблема совместимости, проверка связи с более современными серверами выполняется IPv6, в то время как код выбирает только IPv4 ICMP-пакеты. Простым решением будет ограничить ping до IPv4 следующим образом:

ping -4 google.com

Анализатор для IPv6 требует только небольших изменений из версии IPv4, это выглядит следующим образом:

import socket
import os

host = ""       # Host to listen on

# Create a raw socket and bind it to the public interface
if os.name == "nt":
    socket_protocol = socket.IPPROTO_IPV6
else:
    socket_protocol = socket.IPPROTO_ICMPV6
    
sniffer = socket.socket(socket.AF_INET6, socket.SOCK_RAW, socket_protocol)
sniffer.bind((host, 0))
sniffer.setsockopt(socket.IPPROTO_IPV6, socket.IP_HDRINCL, 1)       # We want the IP headers included in the capture
# if we're using Windows, we need to send an IOCTL
# to set up promiscuous mode
if os.name == "nt":
    sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)
print(sniffer.recvfrom(65565))      # Read in a single packet

# If we're using Windows, turn off promiscuous mode
if os.name == "nt":
    sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)
...