2009-07-27 72 views
17

雖然試圖找出最好的方法來ping從蟒蛇(ICMP)的東西,我碰到這樣的問題:蟒蛇非特權ICMP

答案通常歸結爲「以root權限使用此第三方模塊」或「使用系統的ping命令並解析輸出」。在本地方法中,icmplibM. Cowles and J. Diemer's ping.py明確提到了對root權限的需求,如同scapymanual

所以從這方面來看,本地發送無特殊權限的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

您使用的是什麼操作系統? [最近的Linux內核](https://lkml.org/lkml/2011/5/10/389)和Mac OS X中已知有非特權ICMP套接字。您找到的手冊頁來自OS X,它應該可以工作。我成功地使用了一個非特權的純Python [ping程序](https://github.com/lilydjwg/winterpy/blob/master/pylib/icmplib.py),它在Linux上工作(對內核設置進行更改)但可能需要對OS X進行一些調整。 – lilydjwg 2013-10-27 10:03:30

+0

對於Linuix,請參閱http://stackoverflow.com/questions/8290046/icmp-sockets-linux/20105379#20105379,您需要一個特殊的sysctl才能夠使用`socket( AF_INET,SOCK_DGRAM,IPPROTO_ICMP)` – nos 2013-11-20 19:57:29

回答

11

ping程序安裝了setuid root。這允許任何用戶使用該程序,並仍然能夠打開原始套接字。

打開原始套接字後,它通常會丟棄root privs。

您通常需要原始套接字才能正確執行ICMP,並且原始套接字通常會受到限制。所以這根本不是python的錯。

關於上面有關ICMP的一點,顯然很多實現並不能很好地支持那些標誌組合。因此,大多數實踐可能只是使用他們「知道」在大多數/所有架構上運行的方式。

+0

啊,這是一個謎 - 少,因爲ping的短時間間隔仍然需要sudo,我不認爲它已經setuid根,但你顯然是對的。 – Markus 2009-07-29 08:12:01

+0

Ping不一定使用ICMP探測器,也不需要原始套接字,也不需要root權限。 – 2015-03-27 14:52:00

11

下面是/ sbin目錄/平 「還是設法」(在大多數Unix-Y系統):

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

看到了嗎?它由root擁有,並且在權限setuserid中具有那個至關重要的s位。所以,無論用戶在運行什麼,ping 都以根用戶運行。

如果您在使用新的「非特權ICMP套接字」使用BSD內核,那麼看看使用該功能從Python進行ping操作需要什麼是非常有趣的(但這不會幫助任何處於不太高級的內核,當然)。

+0

有趣的是,非特權ICMP套接字是新的?也許我會嘗試從python那裏獲得工作時間,主要是出於好奇。 – Markus 2009-07-29 08:17:19

+0

不是所有新的**作爲規範**(我相信它一直回到良好的老BSD 4.3! - ),但是這個規範的_working_實現將是非常新的(並且確實是一個非常好的消息,恕我直言,恕我直言)。 – 2009-07-29 14:20:18

0

我不確定是否可以在似乎已經被回答的問題中發佈某些內容。

我一直在尋找相同的實現,並找到了一種通過非超級用戶權限來執行ICMP的方法。

python-ping使用相同的「需要根」的方式做平,而是跨越一個bug報告,其中用戶建議將SOCK_RAWSOCK_DGRAM打來電話sock時:

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

dev的解釋了這個將是一個「WONT-FIX」情況,因爲它是一個UDP ping。

因爲我真的不在乎ICMP是否會通過UDP傳出,所以我繼續獲取代碼並提出了改變建議。

我現在可以在不調用子進程或需要root的情況下執行ping操作!

再次,不知道在這麼長時間後發佈是否可以,但認爲這是一件好事!

+0

這是一個有趣的方法。應該工作得很好,但嚴格來說,這不是一個平。這意味着具有特殊ping處理功能的防火牆等最終可能會有不同的表現。 – DonGar 2012-01-15 22:06:33

-2

我也在尋找不使用子進程或需要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) 
1

其實,在Windows 7和Vista,你確實需要「以管理員身份運行」的事:

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

,當你注意,做了一個數據報套接字導致錯誤。

-8

我正在運行的Python在Windows 7下, 因爲我編輯和下的Eclipse插件的PyDev「編譯」的代碼, 我的解決辦法是:在運行的eclipse.exe作爲管理員:這個問題解決了,

此解決方案與以管理員身份運行cmd類似。

0

您正在閱讀的手冊頁是關於「BSD內核接口手冊」,似乎來自「Mac OS X 10.9」。我沒有在Mac OS X機子上試一試,但Linux的,下以根用戶或用戶我得到一個權限被拒絕的錯誤,當我嘗試這樣打開一個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系統試試,不過反正這套接字類型並不像便攜,至少可以這樣說!

3

現代Linuxes ping使用libcap並要求libcap來完成這項工作。此檢查(capget /套funcitons)和管理權限:

[email protected]:~/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」 計劃:

[email protected]:~/WORK$ getcap ./myping  
[email protected]:~/WORK$ (-> nothing!) 
[email protected]:~/WORK$ setcap cap_net_raw=ep ./myping 
unable to set CAP_SETFCAP effective capability: Operation not permitted 
[email protected]:~/WORK$ sudo setcap cap_net_raw=ep ./myping 

現在做:

[email protected]:~/WORK$ getcap ./myping 
./ping = cap_net_raw+ep 

現在,你的「 myping「將無根。也就是說,只要myping實際上是一個二進制程序。如果是腳本,則必須在腳本解釋器上設置此功能。