Scapy не может прослушивать пакеты при использовании нескольких потоков

Я постараюсь продемонстрировать свою проблему на упрощенном примере.

Ниже приведен очень простой (однопоточный) анализатор пакетов (ICMP):

from scapy.all import *

m_iface = "wlan0"
m_dst = "192.168.0.1"

def print_summary(pkt):
  print pkt.summary()

def plain_sniff():
  sniff(iface = m_iface, count = 10, filter = "icmp and src {0}".format(m_dst), prn = print_summary)

Этот сниффер работает просто отлично, и я получаю вывод:

WARNING: No route found for IPv6 destination :: (no default route?)
Ether / IP / ICMP 192.168.0.1 > 192.168.0.9 echo-reply 0 / Raw
Ether / IP / ICMP 192.168.0.1 > 192.168.0.9 echo-reply 0 / Raw
Ether / IP / ICMP 192.168.0.1 > 192.168.0.9 echo-reply 0 / Raw
...

Затем я создаю отдельный поток для отслеживания пакетов и использую очередь для передачи захваченных пакетов между потоком анализатора и основным потоком:

from threading import Thread
from Queue import Queue, Empty
from scapy.all import *

m_iface = "wlan0"
m_finished = False
m_dst = "192.168.0.1"

def print_summary(pkt):
  print pkt.summary()

def threaded_sniff_target(q):
  global m_finished
  sniff(iface = m_iface, count = 10, filter = "icmp and src {0}".format(m_dst), prn = lambda x : q.put(x))
  m_finished = True

def threaded_sniff():
  q = Queue()
  sniffer = Thread(target = threaded_sniff_target, args = (q,))
  sniffer.daemon = True
  sniffer.start()
  while (not m_finished):
    try:
      pkt = q.get(timeout = 1)
      print_summary(pkt)
    except Empty:
      pass

Этот сниффер также работает нормально, и я получаю тот же вывод, что и выше. Однако, когда я немного изменяю основной поток, чтобы он использовал send() функция между чтениями из очереди пакетов, как показано ниже:

def threaded_sniff_with_send():
  q = Queue()
  sniffer = Thread(target = threaded_sniff_target, args = (q,))
  sniffer.daemon = True
  sniffer.start()
  while (not m_finished):
    send(IP(dst = m_dst) / ICMP()) # Here
    try:
      pkt = q.get(timeout = 1)
      print_summary(pkt)
    except Empty:
      pass

Затем я получаю следующий причудливый вывод (фильтр, похоже, не работает):

WARNING: No route found for IPv6 destination :: (no default route?)
Sent 1 packets.
Ether / ARP who has 192.168.0.1 says 192.168.0.9
Sent 1 packets.
Ether / ARP is at a0:21:b7:1a:7a:db says 192.168.0.1
Sent 1 packets.
Ether / IP / ICMP 192.168.0.9 > 192.168.0.1 echo-request 0
Sent 1 packets.
Ether / IP / ICMP 192.168.0.1 > 192.168.0.9 echo-reply 0
...

Сценарий для трех снифферов можно скачать здесь.

Моя текущая конфигурация системы:

Python: 2.7.3
Scapy: 2.2.0
OS: Fedora 18

Интересно, что все три сниффера отлично работают на моем старом компьютере:

Python: 2.6.4
Scapy: 2.0.0.10 (beta)
OS: Fedora 13

Сначала я подумал, что это могут быть версии Scapy / Python. Но даже когда я установил точно такие же версии на мой новый компьютер, поведение сохранялось.

Я не совсем уверен, подходит ли этот вопрос для SO (может быть сообщение об ошибке в Scapy?). Пожалуйста, извините меня в этом случае.

1 ответ

Решение

Основная причина этого, скорее всего, из-за блокировки ресурсов. Scapy-х sniff() Функция, вероятно, должна блокировать сетевые ресурсы низкого уровня, чтобы иметь возможность перехватывать пакеты.

Задержка двух потоков (после запуска потока анализатора) гарантирует, что Scapy получит время, необходимое для этого.

Чтобы увидеть, как мы пришли к такому выводу, смотрите обсуждение выше в разделе комментариев. Gl Asiri Rathnayake:)

Другие вопросы по тегам