Python非特权ICMP
在尝试找出从Python中发送ping(ICMP)请求的最佳方法时,我遇到了一些问题:
这些问题的答案通常归结为“使用这个第三方模块并需要管理员权限”或者“使用系统的ping命令并解析输出”。在原生方法中,icmplib和M. Cowles和J. Diemer的ping.py明确提到需要管理员权限,scapy的手册也是如此。
所以,从这一点来看,似乎在没有特殊权限的情况下,原生发送ICMP ping是不可行的。系统的ping命令似乎可以做到这一点,但它的手册并没有解释具体是怎么实现的。而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函数,并将其扩展到Python中?有没有人做过这个?我是否误解了这个问题?
9 个回答
我不太确定在一个问题下发帖是否合适,因为这个问题似乎早就有人回答过了。
我一直在寻找相同的实现方法,发现可以用Python在不需要管理员权限的情况下进行ICMP操作。
python-ping
这个库也需要管理员权限来执行ping命令,但我看到一个bug报告,里面有用户建议在调用sock
时把SOCK_RAW
改成SOCK_DGRAM
:
http://hg.io/delroth/python-ping/issue/1/icmp-without-root-privilege
开发者解释说,这种情况将会是“不会修复”的,因为这实际上是一个UDP ping。
因为我并不在乎ICMP是通过UDP发送的,所以我就拿到了代码,并做了建议的修改。
现在我可以在不调用子进程或不需要管理员权限的情况下进行ping操作了!
再次说一下,我不确定在这么久之后发帖是否合适,但我觉得这是一件好事!
这是关于 /sbin/ping 在大多数类Unix系统上是如何工作的:
$ ls -l /sbin/ping
-r-sr-xr-x 1 root wheel 68448 Jan 26 10:00 /sbin/ping
看到了吗?它的拥有者是 root
,而且权限中有一个重要的 s
位,叫做设置用户ID。所以,不管哪个用户在运行它,ping 都是以root身份运行。
如果你使用的是BSD内核,并且有新的“非特权ICMP套接字”,那么了解如何用Python利用这个功能来ping会很有趣(不过这对使用较老内核的用户就没什么帮助了)。
ping程序是以root身份安装的,这样任何用户都可以使用这个程序,并且能够打开一个原始套接字。
在打开原始套接字之后,它通常会放弃root权限。
要正确使用ICMP,通常需要一个原始套接字,而原始套接字通常是有限制的。所以这并不是python的问题。
关于上面提到的ICMP,显然很多实现并不太支持那些标志的组合。因此,大多数实现可能只是使用他们“知道”的在大多数或所有架构上有效的方法。