2009-07-27 10 views
17

Bei dem Versuch, die beste Methode, um herauszufinden, Ping (ICMP) etwas von Python, stieß ich auf diesen Fragen:Python nicht-privilegierter ICMP

Die Antworten laufen im Allgemeinen darauf hinaus, "dieses Drittanbietermodul mit Root-Rechten zu verwenden" oder "den Ping-Befehl des Systems zu verwenden und die Ausgabe zu analysieren". Von den systemeigenen Methoden erwähnen icmplib und M. Cowles and J. Diemer's ping.py explizit die Notwendigkeit für root-Berechtigungen, ebenso wie die scapymanual.

Von daher scheint das native Senden von ICMP-Pings ohne spezielle Berechtigungen unmöglich. Der System-Ping-Befehl funktioniert zwar irgendwie, aber seine Manpage wirft kein Licht darauf. Die man page for icmp, auf der anderen Seite scheint zu sagen, dass es möglich ist:

 
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.

So wäre es das scheint, zumindest nach icmp, ist es erlaubt. Warum können all die Python-Tools das nicht? Sind die Python-Tools zu allgemein und erwarten Sie, dass alle Arbeiten an privilegierten Sockets privilegiert sind? Wäre es möglich, eine Ping-Funktion in C zu schreiben, die ohne root-Rechte pingen kann, und python damit zu erweitern? Hat jemand das getan? Habe ich das Problem einfach missverstanden?

+0

Welches Betriebssystem verwenden Sie? [Aktuelle Linux-Kernel] (https://lkml.org/lkml/2011/5/10/389) und Mac OS X-Versionen haben bekanntermaßen nicht-privilegierte ICMP-Sockets. Die Manpage, die du gefunden hast, stammt von OS X und sollte funktionieren. Ich war erfolgreich mit einem nicht-privilegierten Python [Ping-Programm] (https://github.com/lilydjwg/winterpy/blob/master/pylib/icmplib.py), das unter Linux funktioniert (mit einer Änderung der Kernel-Einstellungen) aber möglicherweise einige Anpassungen auf OS X. – lilydjwg

+0

Für Linuix, siehe hier http://StackOverflow.com/Questions/8290046/ICMP-Sockets-Linux/20105379#20105379, benötigen Sie eine spezielle sysctl, um in der Lage zu sein, Socket zu verwenden (AF_INET, SOCK_DGRAM, IPPROTO_ICMP) ' – nos

Antwort

11

Das Ping-Programm ist setuid root installiert. Dies ermöglicht jedem Benutzer, das Programm zu verwenden, und trotzdem in der Lage, einen unformatierten Socket zu öffnen.

Nachdem der rohe Socket geöffnet wurde, werden in der Regel Root-Einträge gelöscht.

Normalerweise benötigen Sie einen Raw-Socket, um ICMP korrekt auszuführen, und rohe Sockets sind normalerweise eingeschränkt. Es ist also nicht wirklich Pythons Schuld.

In Bezug auf das obige Bit über ICMP unterstützen anscheinend viele Implementierungen diese Kombinationen von Flags nicht wirklich gut. Es ist also wahrscheinlich, dass die meisten Implementierungen einfach so arbeiten, wie sie "wissen" auf den meisten/allen Architekturen arbeiten.

+0

Ah, das ist ein Mysterium weniger - da kurze Ping-Intervalle immer noch Sudo erfordern, habe ich nicht gedacht, dass es Root gesetzt hat, aber damit hast du ganz recht. – Markus

+0

Ping verwendet nicht unbedingt ICMP-Probes, noch Raw-Sockets oder root-Rechte. –

11

Hier ist, wie/sbin/ping "irgendwie schafft" (auf den meisten Unix-y-Systeme):

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

sehen? Es gehört root und hat das entscheidende s Bit in der Berechtigung - setuserid. Also, egal, welcher Benutzer es ausführt, läuft ping als root.

Wenn Sie einen BSD-Kernel mit den neuen "nicht-privilegierten ICMP-Sockets" verwenden, wäre es interessant zu sehen, was benötigt wird, um Ping von Python aus zu nutzen (aber das hilft keinem Benutzer, der auf einem weniger fortgeschrittener Kernel, natürlich).

+0

Interessante, also nicht-privilegierte ICMP-Sockets sind neu? Vielleicht werde ich versuchen, diese Arbeit von Python zu bekommen, wenn ich Zeit habe, meistens aus Neugier. – Markus

+0

Nicht alles so neu ** als Spezifikation ** (Ich glaube, es geht bis auf die gute alte glorreiche BSD 4.3! -), aber eine _working_ Umsetzung dieser Spezifikation wäre ziemlich neu (und sehr gute Nachrichten in der Tat, IMHO). –

0

Ich bin nicht sicher, ob es in Ordnung ist, etwas in einer Frage zu posten, die anscheinend schon vor einiger Zeit beantwortet wurde.

Ich habe nach der gleichen Implementierung gesucht und einen Weg gefunden, ICMP über Python mit nicht-root-Rechten zu machen.

python-ping verwendet die gleiche ‚need-root‘ Art und Weise einen Ping zu tun, aber über einen Fehlerbericht kam, wo ein Benutzer SOCK_RAW zu SOCK_DGRAM vorgeschlagen zu ändern, wenn sock Aufruf:

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

Die Entwickler dies erklärt wird eine "WONT-FIX" -Situation sein, weil es eher ein UDP-Ping ist.

Da es mir wirklich egal ist, ob ICMP über UDP geht, ging ich voran und bekam den Code und machte den vorgeschlagenen geändert.

Ich bin jetzt in der Lage, einen Ping zu tun, ohne Unterprozess aufzurufen oder root zu benötigen!

Noch einmal, nicht sicher, ob das Posting hier nach so langer Zeit in Ordnung ist, aber dachte, das wäre eine bessere Sache!

+0

Das ist ein interessanter Ansatz. Sollte gut funktionieren, aber streng genommen ist es kein Ping mehr. Das bedeutet, dass sich Firewalls und solche, die eine spezielle Ping-Behandlung haben, am Ende anders verhalten. – DonGar

+3

Dieser Ansatz funktioniert überhaupt nicht. Sie können keinen UDP-Socket mit Protokoll ICMP erstellen. Ich habe eine EPROTONOSUPPORT (Protokoll nicht unterstützt). - Der Grund ist einfach: Eine solche Protokollkombination existiert nicht. (Antworttests sind mit UDP/TCP nicht privilegiert, aber das erfordert mehr als nur subtile Änderungen.) –

-2

Ich war auch auf der Suche nach einer Implementierung von Ping ohne Subprozess zu verwenden oder Root zum Pingen zu benötigen. Meine Lösung musste plattformübergreifend sein, nämlich Windows und Linux.

Das Ändern des Sockets unter Windows zu SOCK_DGRAM führt zu einer Ausnahme "Protokoll nicht unterstützt 100043". Es sieht also so aus, als ob Windows korrekt überprüft, ob icmp auf TCP anstatt auf UDP gesendet wird. Windows ist jedoch egal, ob es als "root" läuft, da dies ein Linux-Konzept ist. Eigentlich

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

, auf Windows 7 und Vista brauchen Sie auf ‚Ausführen als Administrator‘ zu tun:

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

und wie Sie feststellen, verursacht es über einen Datagramm-Socket tun einen Fehler.

-8

Ich bin mit Python unter Windows 7, Da ich bin die Bearbeitung und der Code unter Eclipse-Plugin pydev "Kompilieren", Meine Lösung war: die eclipse.exe als Administrator ausgeführt wird: dies löste das Problem,

Diese Lösung ähnelt dem Ausführen des Cmd als Administrator.

+8

Bitte schlagen Sie nicht vor, dass Benutzer willkürliche Programme als Administrator ausführen. So hat UAC einen schlechten Ruf bekommen. Ihre Antwort hilft auch nicht für ein in der Produktion eingesetztes Programm. – AdmiralNemo

0

Die Man-Seite, die Sie lesen, handelt von "BSD Kernel Interfaces Manual" und scheint von "Mac OS X 10.9" zu stammen. Ich habe nicht eine Mac OS X-Rechner, um zu versuchen, aber unter Linux, als root oder als Benutzer ich eine Erlaubnis verweigert Fehler, wenn ich versuche, eine ICMP zu öffnen so:

$ 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 

Unter OpenBSD ich ein „Protokoll nicht unterstützt“ Fehler:

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

jemand sein kann, unter MacOS X oder anderem BSDs, aber trotzdem dieser Socket-Typ sieht nicht aus wie tragbaren versuchen könnte, die am wenigsten zu sagen!

+0

Sie tun es falsch, ICMP-Nachrichten werden von DGRAM-Sockets als Fehlermeldungen abgerufen. Die Angabe von ICMP als Socket-Protokoll auf DGRAM ist einfach falsch. –

+0

Ich mache was der OP getan hat ... und fragt nach. – Pierre

3

Moderne Linux-Ping verwendet libcap und fragt libcap, um die Arbeit zu erledigen.Diese Kontrollen (capget/set funcitons) und verwalten Berechtigungen:

[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) 

Können sagen, Sie ein "myping" Programm:

[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 

Jetzt tun:

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

jetzt Ihr " Myping "wird ohne Root funktionieren. Das heißt, solange myping tatsächlich ein Binärprogramm ist. Wenn es sich um ein Skript handelt, muss diese Fähigkeit stattdessen im Skript-Interpreter festgelegt werden.

+0

ausgezeichneter Punkt, ich war fast verzweifelt, dass niemand Fähigkeiten erwähnt hatte. Es ist jedoch zu beachten, dass, wenn Ihr "Programm" ein Skript ist, die Fähigkeit im Skript-Interpreter und nicht im Skript festgelegt werden muss. – 0xC0000022L