在尝试从python中找出ping(ICMP)的最佳方法时,我遇到了以下问题:
答案通常归结为“使用具有root权限的第三方模块”或“使用系统的ping命令并解析输出”。在本机方法中,icmplib和M. Cowles and J. Diemer's ping.py明确提到了对root权限的需求,scapy manual也是如此。
所以从那个方面来看,原本发送没有特权的ICMP ping似乎是不可能的。系统ping命令确实以某种方式进行管理,但其手册页并未阐明如何操作。另一方面,man page for icmp似乎表示有可能:
Non-privileged ICMP ICMP sockets can be opened with the SOCK_DGRAM socket type without requiring root privileges. The synopsis is the following: socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP) Datagram oriented ICMP sockets offer a subset of the functionality avail- able to raw ICMP sockets. Only IMCP request messages of the following types can be sent: ICMP_ECHO, ICMP_TSTAMP or ICMP_MASKREQ.
所以看起来,至少根据icmp,它是允许的。那么为什么所有的python工具都无法做到这一点呢? python工具是否过于笼统,并期望特权套接字上的任何工作都具有特权?是否有可能在C中编写ping函数,可以在没有root权限的情况下ping,并用此扩展python?有没有人这样做过?我只是误解了这个问题吗?
答案 0 :(得分:12)
ping程序安装了setuid root。这允许任何用户使用该程序,并且仍然可以打开原始套接字。
打开原始套接字后,它通常会丢弃root权限。
您通常需要一个原始套接字才能正确执行ICMP,并且通常会限制原始套接字。所以这根本不是python的错。
关于上面关于ICMP的一点,显然很多实现并不能真正支持这些标志组合。因此,大多数建议可能只是使用他们“知道”在大多数/所有架构上工作的方式。
答案 1 :(得分:11)
以下是/ sbin / ping“以某种方式管理”(在大多数Unix-y系统上):
$ ls -l /sbin/ping
-r-sr-xr-x 1 root wheel 68448 Jan 26 10:00 /sbin/ping
请参阅?它由root
拥有,并且在权限 - setuserid中具有关键s
位。因此,无论用户运行什么,ping 以root身份运行。
如果您正在使用带有新“非特权ICMP套接字”的BSD内核,那么看看使用该功能从Python进行ping操作需要什么是有趣的(但这对于任何少用的用户都没有帮助当然是高级内核。
答案 2 :(得分:3)
Modern Linuxes ping使用libcap并要求libcap完成工作。这将检查(capget / set funcitons)并管理权限:
linux@jacax:~/WORK$ ldd /bin/ping
linux-gate.so.1 => (0xb77b6000)
libcap.so.2 => /lib/i386-linux-gnu/libcap.so.2 (0xb7796000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb75e7000)
/lib/ld-linux.so.2 (0xb77b7000)
让我们说你有一个" myping"程序:
linux@jacax:~/WORK$ getcap ./myping
linux@jacax:~/WORK$ (-> nothing! )
linux@jacax:~/WORK$ setcap cap_net_raw=ep ./myping
unable to set CAP_SETFCAP effective capability: Operation not permitted
linux@jacax:~/WORK$ sudo setcap cap_net_raw=ep ./myping
现在做:
linux@jacax:~/WORK$ getcap ./myping
./ping = cap_net_raw+ep
现在,你的" myping"将无法工作。也就是说,只要myping
实际上是二进制程序。如果是脚本,则必须在脚本解释器上设置此功能。
答案 3 :(得分:1)
实际上,在Windows 7和Vista上,您需要“以管理员身份运行”才能执行以下操作:
my_socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, icmp)
并且如您所知,在数据报套接字上执行此操作会导致错误。
答案 4 :(得分:0)
我不确定是否可以在一个似乎已经回答过的问题中发帖。
我一直在寻找相同的实现,并找到了一种通过Python以非root权限进行ICMP的方法。
python-ping
使用相同的“need-root”方式进行ping,但遇到了一个错误报告,用户建议在调用{{1}时将SOCK_RAW
更改为SOCK_DGRAM
}:
http://hg.io/delroth/python-ping/issue/1/icmp-without-root-privilege
开发人员解释说这将是一个“WONT-FIX”情况,因为它是UDP ping。
因为我真的不在乎ICMP是否通过UDP出去,所以我继续获取代码并改变了建议。
我现在能够在不调用子进程或需要root的情况下执行ping操作!
再次,不确定在这么长时间后在这里发帖是否可以,但认为这是更好的事情!
答案 5 :(得分:0)
您正在阅读的手册页是关于“BSD内核接口手册”,似乎来自“Mac OS X 10.9”。我没有Mac OS X机器可以尝试,但在Linux下,以root或用户当我尝试打开这样的ICMP时,我收到了一个拒绝权限错误:
$ strace -e trace=socket python
Python 2.7.5+ (default, Sep 19 2013, 13:48:49)
[GCC 4.8.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import socket
>>> socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_ICMP)
socket(PF_INET, SOCK_DGRAM, IPPROTO_ICMP) = -1 EACCES (Permission denied)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.7/socket.py", line 187, in __init__
_sock = _realsocket(family, type, proto)
socket.error: [Errno 13] Permission denied
在OpenBSD下,我收到“不支持协议”错误:
>>> import socket
>>> socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_ICMP)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/lib/python2.7/socket.py", line 187, in __init__
_sock = _realsocket(family, type, proto)
socket.error: [Errno 43] Protocol not supported
可能有人可以在MacOS X或其他BSD下尝试,但无论如何这个插槽类型看起来不像便携式,至少可以说!
答案 6 :(得分:-2)
我也在寻找ping的实现而不使用子进程或需要root来ping。我的解决方案需要跨平台,即Windows和Linux。
将Windows上的套接字更改为SOCK_DGRAM会导致“协议不支持100043”异常。所以看起来Windows正确检查是否在TCP而不是UDP上发送icmp。但是,Windows并不关心它是否以“root”身份运行,因为这是一个Linux概念。
if os.name == 'nt':
#no root on windows
my_socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, icmp)
else:
#changed to UDP socket...gets around ROOT priv issue
my_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, icmp)
答案 7 :(得分:-8)
我在Windows 7下运行python, 因为我正在编辑和“编译”Eclipse pydev插件下的代码, 我的解决方案是:以管理员身份运行eclipse.exe:这解决了问题,
此解决方案类似于以管理员身份运行cmd。