Скапи, как получить время пинга?

Я пытаюсь написать scapy script, который может рассчитывать среднее время ping, поэтому мне нужно узнать время, прошедшее между отправкой ICMP эхо / ответного пакета и полученным ответным пакетом. На данный момент у меня есть это:

#! /usr/bin/env python
from scapy.all import *
from time import *

def QoS_ping(host, count=3):
  packet = Ether()/IP(dst=host)/ICMP()
  t=0.0
  for x in range(count):
      t1=time()
      ans=srp(packet,iface="eth0", verbose=0)
      t2=time()
      t+=t2-t1
  return (t/count)*1000

Проблема в том, что использование функции time () не дает хорошего результата. Например, я нашел 134 мс в одном домене, а с помощью функции системы ping в том же домене я нашел 30 мс (в среднем, конечно).

Мой вопрос: есть ли способ узнать точное время, прошедшее между отправленным и полученным пакетом с помощью scapy? Я не хочу использовать функцию popen () или другой системный вызов, потому что мне нужен scapy для будущего управления пакетами.


person user1789326    schedule 31.10.2012    source источник
comment
Возможно, вам больше повезет, если вы используете time.clock() вместо time.time().   -  person Nathan Villaescusa    schedule 31.10.2012
comment
Также может лучше работать с srp1 вместо srp.   -  person Nathan Villaescusa    schedule 31.10.2012
comment
Натан, все, что вы делаете в scapy, ужасно медленно ... scapy анализирует весь пакет в python (в пользовательском пространстве). Он не может конкурировать с реализацией C, использующей системные вызовы ОС.   -  person This    schedule 01.11.2012
comment
Добавьте это как ответ, не отвечайте на свой вопрос в вопросе   -  person This    schedule 02.11.2012
comment
несвязанный: ping в чистом Python   -  person jfs    schedule 02.11.2012


Ответы (3)


Scapy работает медленно, потому что это чистый питон, анализирующий весь пакет в пользовательском пространстве ... обойти ограничения производительности scapy - не так уж и необычно.

Сравнивая яблоки с яблоками ... У меня есть Xeon-сервер с прямым гигабитным Ethernet-каналом в Интернет, но мой трафик очень слабый. Когда я запускаю обычный эхо-запрос к маршрутизатору Cisco, к которому он подключен, я получаю в среднем около 60 микросекунд каждый ...

[mpenning@Bucksnort ~]$ ping -W 1 -c 3 192.0.2.1
PING 192.0.2.1 (192.0.2.6) 56(84) bytes of data.
64 bytes from 192.0.2.1: icmp_req=1 ttl=64 time=0.078 ms
64 bytes from 192.0.2.1: icmp_req=2 ttl=64 time=0.062 ms
64 bytes from 192.0.2.1: icmp_req=3 ttl=64 time=0.062 ms

--- 192.0.2.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 1998ms
rtt min/avg/max/mdev = 0.062/0.067/0.078/0.010 ms
[mpenning@Bucksnort ~]$

Тот же пункт назначения в scapy ... тоже измеряется в миллисекундах ...

[mpenning@Bucksnort ~]$ sudo python new_ping_ip.py
Ping: 0.285587072372
Ping: 0.230889797211
Ping: 0.219928979874
AVERAGE 245.468616486
[mpenning@Bucksnort ~]$

Результаты Scapy почти в 4000 раз больше, чем базовый пинг из командной строки bash (245,469 / 0,062) ... Я сам проложил кабель, это меньше десяти футов кабеля до маршрутизатора Cisco.

Что вы можете сделать, чтобы добиться лучших результатов? Как упоминалось в комментариях, посмотрите на sent_time и _4 _... Packet.time заполняется перед синтаксическим анализом ... это все еще медленнее, чем пинг из оболочки, но может помочь с вашим желанием захватывать пакеты в scapy.

#! /usr/bin/env python
from scapy.all import *

def QoS_ping(host, count=3):
  packet = Ether()/IP(dst=host)/ICMP()
  t=0.0
  for x in range(count):
      ans,unans=srp(packet,iface="eth0", filter='icmp', verbose=0)
      rx = ans[0][1]
      tx = ans[0][0]
      delta = rx.time-tx.sent_time
      print "Ping:", delta
      t+=delta
  return (t/count)*1000

if __name__=="__main__":
    total = QoS_ping('192.0.2.1')
    print "TOTAL", total

Пробный прогон ...

[mpenning@Bucksnort ~]$ sudo python ping_ip.py
Ping: 0.000389099121094
Ping: 0.000531911849976
Ping: 0.000631093978882
TOTAL 0.51736831665
[mpenning@Bucksnort ~]$

Хотя даже использование Packet.time и Packet.sent_time медленнее по сравнению с вызовом оболочки ...

>>> from subprocess import Popen, PIPE
>>> import re
>>> cmd = Popen('ping -q -c 3 192.0.2.1'.split(' '), stdout=PIPE)
>>> output = cmd.communicate()[0]
>>> match = re.search('(\d+\.\d+)\/(\d+\.\d+)\/(\d+\.\d+)\/(\d+\.\d+)\s+ms', output)
>>> if not (match is None):
...     print "Average %0.3f" % float(match.group(1))
... else:
...     print "Failure"
...
Average 0.073
>>>

ping -q -c 3 обеспечивает итоговый вывод 3 эхо-запросов без распечатки отдельных эхо-запросов.

Если вы хотите перехватывать свои пакеты ping (с помощью вызова ping оболочки) для дальнейшей scapy обработки, создайте tcpdump -c <num-packets> -w <filename> icmp and host <host-addr> & перед запуском ping CLI ... затем используйте scapy's _ 14_, чтобы прочитать файл pcap из tcpdump. Обязательно правильно рассчитайте количество пакетов, которые вы захватите в свой файл pcap.

person This    schedule 01.11.2012
comment
ОТВЕТ: Я обнаружил следующее: отправленные пакеты имеют атрибут sent_time ', отвеченные пакеты имеют атрибут'. на comments.gmane.org/gmane.comp.security.scapy.general / 4385 - person user1789326; 02.11.2012
comment
@ user1789326: вы можете оставить свой комментарий в качестве ответа - person jfs; 02.11.2012
comment
почему среднее значение 0,29, 0,23, 0,22 равно 245? - person jfs; 02.11.2012
comment
Среднее значение 285,5 мс + 230,9 мс + 219,9 мс - 245 мс; время отклика отдельных пакетов печатается в секундах, а среднее значение преобразуется в миллисекунды в течение return - person This; 02.11.2012
comment
Предупреждение для будущих читателей: использование rx.time-tx.sent_time может привести к отрицательным результатам измерения времени (scapy 2.4.0-2.4.3rc1). Я создал проблему (# 1952) по этому поводу для всех, кого это интересует. - person Felix ZY; 28.03.2019

Кстати, использование небуферизованного python (python -u для его запуска) увеличивает точность синхронизации, поскольку python не ждет, пока буферы решат сбросить. Используя ваш вышеупомянутый скрипт, он изменил мои результаты с выключения на 0,4 мс на отключение на 0,1-иш.

person fantadisco    schedule 19.06.2014

Майк, небольшое исправление, чтобы получить среднее время, измените:

print "Average %0.3f" % float(match.group(1))

to:

 print "Average %0.3f" % float(match.group(2))

поскольку (match.group (1)) получит минимальное время, а не среднее, как упомянуто.

person Naor Kalbo    schedule 29.12.2016