12

我正在尝试编写一个可以平均 ping 时间的 scapy 脚本,因此我需要获取发送 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 来进行未来的数据包管理。

4

3 回答 3

7

Scapy 很慢,因为它是纯 python 解析用户空间中的整个数据包......绕过 scapy 的吞吐量限制并不是什么不寻常的事情

做一个苹果对苹果的比较......我有一个 Xeon 服务器,它有一个直接连接到互联网的千兆以太网管道,但我的流量非常少。当我对它所连接的 Cisco 路由器运行正常 ping 时,我平均每个大约 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 的结果几乎是 bash 提示符 (245.469 / 0.062) 的基线 ping 的4000倍...我自己运行电缆,它不到 Cisco 路由器的 10 英尺电缆。

你能做些什么来获得更好的结果?正如评论中提到的,在解析之前先查看sent_time并填充time...Packet.time这仍然比来自 shell 的 ping 慢,但可能有助于您在 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.timeandPacket.sent_time与 shell 调用相比也很慢......

>>> 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。

如果要捕获 ping 数据包(通过 shell ping 调用)以供以后scapy处理,tcpdump -c <num-packets> -w <filename> icmp and host <host-addr> &请在运行 CLI ping 之前生成...然后使用 scapyrdpcap()tcpdump. 请务必正确计算您将在 pcap 文件中捕获的数据包数量。

于 2012-11-01T09:40:17.863 回答
0

顺便说一句,使用无缓冲的 python(python -u 启动它)增加了计时精度,因为 python 不等待缓冲区决定转储。使用上面的脚本,它将我的结果从 0.4 毫秒关闭到 0.1-ish 关闭。

于 2014-06-19T20:28:49.427 回答
0

迈克,只是为了获得平均时间的一个小修复,改变:

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

至:

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

因为 (match.group(1)) 将获得最小时间,而不是前面提到的平均值。

于 2016-12-29T09:03:56.373 回答