Pytanie Sprawdź, jak uzyskać czas pingowania?


Próbuję napisać skrypt scapy, który może uczynić średnią w czasie pingowania, więc potrzebuję uzyskać czas, jaki upłynął między wysłaniem pakietu echo / odpowiedzi ICMP a odebranym pakietem odpowiedzi. Na razie mam to:

#! /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

Problem polega na tym, że użycie funkcji time () nie daje dobrego wyniku. Na przykład znajduję 134 ms na jednej domenie, a przy funkcji systemu ping w tej samej domenie znalazłem 30 ms (oczywiście średnio).

Moje pytanie brzmi: czy istnieje sposób, aby uzyskać dokładnie czas, w którym wysłano pakiet pomiędzy wysłanym pakietem a otrzymanym pakietem? Nie chcę używać funkcji popen () ani innych wywołań systemowych, ponieważ potrzebuję scapy do zarządzania pakietami futur.


12
2017-10-31 17:27


pochodzenie


Możesz mieć więcej szczęścia przy użyciu time.clock() zamiast time.time(). - Nathan Villaescusa
Może również lepiej działać z srp1 zamiast srp. - Nathan Villaescusa
Nathan, wszystko, co robisz w scrypcie, jest strasznie wolne ... scapy analizuje cały pakiet w pythonie (w przestrzeni użytkownika). Nie może konkurować z implementacją C wykorzystującą wywołania systemowe OS. - Mike Pennington
Dodaj to jako odpowiedź, nie odpowiadaj na swoje pytanie w pytaniu - Mike Pennington
nie związane: ping w czystym pytonie - jfs


Odpowiedzi:


Scapy jest powolna, ponieważ jest czystym pythonem analizującym cały pakiet w przestrzeni użytkownika ... nie jest niczym nadzwyczajnym zhakowanie się wokół ograniczeń wydajnościowych scapy.

Porównanie jabłek z jabłkami ... Mam serwer Xeon z bezpośrednim przewodem ethernetowym do internetu, ale mój ruch jest bardzo lekki. Kiedy uruchomię normalny ping do routera Cisco, do którego jest podłączony, uśredniam około 60 mikrosekund ...

[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 ~]$

To samo miejsce w scapy ... mierzone w milisekundach ...

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

Wyniki Scapy są prawie 4000 razy większy niż ping podstawowy z wiersza poleceń bash (245.469 / 0.062) ... Sam przeprowadziłem kabel, to jest mniej niż dziesięć stóp kabla do routera Cisco.

Co możesz zrobić, aby uzyskać lepsze wyniki? Jak wspomniano w komentarzach, spójrz na sent_time i time... Packet.time jest zapełniany przed analizą ... to wciąż jest wolniejsze niż polecenie ping z powłoki, ale może pomóc w próbie przechwycenia pakietów w 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

Próbka uruchom ...

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

Nawet za pomocą Packet.time i Packet.sent_time jest powolny w porównaniu do wywołania powłoki ...

>>> 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 dostarcza wynik podsumowania 3 pingi bez wydrukowania poszczególnych pingów.

Jeśli chcesz przechwycić pakiety ping (przez wywołanie ping powłoki) na później scapy przetwarzanie, spawn tcpdump -c <num-packets> -w <filename> icmp and host <host-addr> & przed uruchomieniem twojego pinga CLI ... następnie użyj scapy rdpcap() odczytać plik pcap z tcpdump. Pamiętaj, aby poprawnie obliczyć liczbę pakietów przechwyconych w pliku pcap.


6
2017-11-01 09:40



ODPOWIEDŹ: Znalazłem to: "Wysłane pakiety mają czas wysłany", odpowiedziano na atrybuty w pakiecie ". w comments.gmane.org/gmane.comp.security.scapy.general/4385 - user1789326
@ user1789326: możesz opublikować komentarz jako odpowiedź - jfs
dlaczego średnia 0,29, 0,23, 0,22 wynosi 245? - jfs
Średnia 285,5 ms + 230,9 ms + 219,9 ms to 245 ms; czasy odpowiedzi poszczególnych pakietów są drukowane w sekundach, a średnia jest konwertowana na milisekundy podczas return - Mike Pennington


BTW, używając niebuforowanego pythona (python -u, aby go uruchomić) zwiększa dokładność taktowania, ponieważ python nie czeka na bufory, aby zdecydować się na zrzut. Używając powyższego skryptu, zmieniłem moje wyniki z wyłączenia o 0,4 ms na wyłączenie przez 0.1-ish.


0
2018-06-19 20:28





Mike, wystarczy drobna poprawka, aby uzyskać średni czas, zmienić:

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

do:

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

ponieważ (match.group (1)) otrzymamy minimalny czas, a nie średnią, jak wspomniano.


0
2017-12-29 09:03