【问题标题】:python non-privileged ICMPpython非特权ICMP
【发布时间】:2010-11-14 10:24:52
【问题描述】:

在试图找出从 python 中 ping (ICMP) 的最佳方法时,我遇到了以下问题:

答案通常归结为“使用具有 root 权限的第三方模块”或“使用系统的 ping 命令并解析输出”。在原生方法中,icmplibM. Cowles and J. Diemer's ping.py 明确提到需要 root 权限,scapy manual 也是如此。

因此,从这方面来说,在没有特殊权限的情况下本地发送 ICMP ping 似乎是不可能的。 system ping 命令确实以某种方式管理,但它的手册页没有说明如何进行。另一方面,man page for icmp 似乎说这是可能的:

非特权 ICMP ICMP 套接字可以使用 SOCK_DGRAM 套接字类型打开,而无需 需要root权限。概要如下: 套接字(AF_INET,SOCK_DGRAM,IPPROTO_ICMP) 面向数据报的 ICMP 套接字提供了可用功能的子集 能够原始 ICMP 套接字。只有以下的 IMCP 请求消息 可以发送类型:ICMP_ECHO、ICMP_TSTAMP 或 ICMP_MASKREQ。

因此,至少根据 icmp,这似乎是允许的。那么为什么所有的python工具都无法做到这一点呢? python 工具是否过于通用并期望特权套接字上的任何工作都具有特权?是否可以在 C 中编写一个无需 root 权限即可 ping 的 ping 函数,并以此扩展 python?有人做过吗?我是不是误解了这个问题?

【问题讨论】:

  • 您使用的是什么操作系统? Recent Linux kernels 和 Mac OS X 已知具有非特权 ICMP 套接字。您找到的手册页来自 OS X,它应该可以工作。我已经成功使用了非特权纯 Python ping program,它适用于 Linux(内核设置更改),但可能需要在 OS X 上进行一些调整。
  • 对于 Linux,请参见此处 stackoverflow.com/questions/8290046/icmp-sockets-linux/… ,您需要一个特殊的 sysctl 才能使用 socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP)

标签: python ping icmp


【解决方案1】:

icmplib 模块帮助我在不以 root 身份运行整个 django 应用程序的情况下进行 ping: https://pypi.org/project/icmplib/

【讨论】:

    【解决方案2】:

    现代 Linux ping 使用 libcap 并要求 libcap 完成工作。这会检查(capget/set 功能)并管理权限:

    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”将在没有 root 的情况下工作。也就是说,只要myping 实际上是一个二进制程序。如果是脚本,则必须在脚本解释器上设置此功能。

    【讨论】:

    • 好点,我几乎绝望,没有人提到能力。但是,必须注意,如果您的“程序”是脚本,则必须在脚本解释器而不是脚本中设置功能。
    【解决方案3】:

    您正在阅读的手册页是关于“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 下尝试,但无论如何这种套接字类型看起来不像是可移植的,至少可以这么说!

    【讨论】:

    • 你做错了,ICMP 消息被 DGRAM 套接字作为错误消息获取。在 DGRAM 上将 ICMP 指定为套接字协议是错误的。
    【解决方案4】:

    实际上,在 Windows 7 和 Vista 上,您确实需要“以管理员身份运行”:

    my_socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, icmp)
    

    正如您所注意到的,通过数据报套接字执行此操作会导致错误。

    【讨论】:

      【解决方案5】:

      我在 windows 7 下运行 python, 由于我在 Eclipse pydev 插件下编辑和“编译”代码, 我的解决方案是:以管理员身份运行 eclipse.exe:这解决了问题,

      此方案类似于以管理员身份运行 cmd。

      【讨论】:

      • 请不要建议人们以管理员身份运行任意程序。这就是 UAC 一开始就名声不佳的原因。您的回答对于部署到生产中的程序也没有帮助。
      【解决方案6】:

      我也在寻找一种不使用子进程或需要 root 来 ping 的 ping 实现。我的解决方案需要跨平台,即 Windows 和 Linux。

      将 Windows 上的套接字更改为 SOCK_DGRAM 会导致“协议不支持 100043”异常。所以看起来 Windows 正确地检查了 icmp 是否是通过 TCP 而不是 UDP 发送的。但是,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】:

        我不确定是否可以在似乎已经回答过一段时间的问题中发布内容。

        我一直在寻找相同的实现,并找到了一种通过 Python 以非 root 权限执行 ICMP 的方法。

        python-ping 使用相同的“need-root”方式执行 ping,但遇到了一个错误报告,其中用户建议在调用 sock 时将 SOCK_RAW 更改为 SOCK_DGRAM

        http://hg.io/delroth/python-ping/issue/1/icmp-without-root-privilege

        开发人员解释说这将是“WONT-FIX”情况,因为它是一个 UDP ping。

        由于我真的不在乎 ICMP 是否通过 UDP 发出,所以我继续获取代码并更改了建议。

        我现在可以在不调用子进程或需要 root 的情况下执行 ping!

        再次,不确定这么长时间后在这里发帖是否可以,但认为这是一件更好的事情!

        【讨论】:

        • 这是一个有趣的方法。应该可以正常工作,但严格来说,它不再是 ping。这意味着具有特殊 ping 处理的防火墙等可能最终表现不同。
        • 这种方法根本行不通。您不能使用 ICMP 协议创建 UDP 类型的套接字。我有一个 EPROTONOSUPPORT(不支持协议)。 – 原因很简单:不存在这样的协议组合。 (使用 UDP/TCP 可以进行无特权的响应测试,但这需要像这样的细微更改。)
        【解决方案8】:

        以下是 /sbin/ping “以某种方式管理”的方式(在大多数 Unix-y 系统上):

        $ ls -l /sbin/ping
        -r-sr-xr-x  1 root  wheel  68448 Jan 26 10:00 /sbin/ping
        

        看到了吗?它由root 拥有,并且在权限中具有关键的s 位--setuserid。因此,无论是哪个用户运行它,ping 都以 root 身份运行

        如果您正在使用带有新的“非特权 ICMP 套接字”的 BSD 内核,那么看看使用该功能从 Python ping 需要什么会很有趣(但这不会帮助任何使用 less当然是高级内核)。

        【讨论】:

        • 有趣,所以非特权 ICMP 套接字是新的?也许我会在有时间的时候尝试从 python 中实现它,主要是出于好奇。
        • 并非所有新的作为规范(我相信它可以一直追溯到辉煌的 BSD 4.3!-),而是一个工作 该规范的实施将是相当新的(而且确实是个好消息,恕我直言)。
        • 我在 Arch Linux 中的 ping 没有那个位。
        【解决方案9】:

        ping 程序是安装setuid root。这允许任何用户使用该程序,并且仍然能够打开原始套接字。

        在打开原始套接字后,它通常会删除 root 权限。

        您通常需要一个原始套接字才能正确执行 ICMP,而原始套接字通常受到限制。所以这根本不是python的错。

        关于上面关于 ICMP 的部分,显然许多实现并不能很好地支持这些标志组合。所以很可能大多数实现只是使用他们“知道”在大多数/所有架构上工作的方式。

        【讨论】:

        • 啊,少了一个谜——因为 ping 的短暂间隔仍然需要 sudo,我认为它没有 setuid root,但你显然是对的。
        • Ping 不一定使用 ICMP 探测,也不需要原始套接字,也不需要 root 权限。
        猜你喜欢
        • 1970-01-01
        • 2015-04-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-11-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多