2009-07-27 17 views
17

Al tratar de averiguar el mejor método para hacer ping a algo (ICMP) de pitón, me encontré con estas preguntas:pitón no privilegiado ICMP

Las respuestas generalmente se reducen a "usar este módulo de terceros con privilegios de raíz" o "usar el comando de ping del sistema y analizar el resultado". De los métodos nativos, icmplib y M. Cowles and J. Diemer's ping.py mencionan explícitamente la necesidad de privilegios de root, al igual que el scapymanual.

Así que desde ese frente, el envío nativo de ping ICMP sin privilegios especiales parece imposible. El comando system ping funciona de alguna manera, pero su página man no arroja ninguna luz sobre cómo. El man page for icmp, por el contrario, parece que decir que es posible:

 
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.

por lo que parece que, al menos según la ICMP, está permitido. Entonces, ¿por qué todas las herramientas de Python no pueden hacer esto? ¿Las herramientas de python son demasiado generales y se espera que se privilegie el trabajo en zócalos privilegiados? ¿Sería posible escribir una función de ping en C que pueda hacer ping sin privilegios de root y extender python con esto? ¿Alguien ha hecho esto? ¿Acabo de malinterpretar el problema?

+0

¿Qué sistema operativo está utilizando? [Núcleos recientes de Linux] (https://lkml.org/lkml/2011/5/10/389) y Mac OS X son conocidos por tener sockets ICMP no privilegiados. La página de manual que ha encontrado es de OS X y debería funcionar. He tenido éxito con un Python [ping program] sin privilegios (https://github.com/lilydjwg/winterpy/blob/master/pylib/icmplib.py) que funciona en Linux (con un cambio de configuración de kernel) pero puede necesitar algunos ajustes en OS X. – lilydjwg

+0

Para Linuix, consulte aquí http://stackoverflow.com/questions/8290046/icmp-sockets-linux/20105379#20105379, necesita un sysctl especial para poder usar 'socket (AF_INET, SOCK_DGRAM, IPPROTO_ICMP) ' – nos

Respuesta

11

El programa ping está instalado raíz setuid. Esto permite a cualquier usuario usar el programa y aún así poder abrir un socket sin formato.

Después de que abre el socket sin formato, normalmente deja caer privs de raíz.

Por lo general, necesita un socket sin formato para realizar ICMP correctamente, y los sockets sin formato suelen estar restringidos. Entonces realmente no es culpa de Python.

En cuanto al bit sobre ICMP anterior, aparentemente muchas implementaciones realmente no admiten bien esas combinaciones de banderas. Por lo tanto, es probable que la mayoría de las implementaciones utilicen la forma en que "saben" funciona en la mayoría de las arquitecturas.

+0

Ah, eso es un misterio menos, ya que los cortos intervalos de ping todavía requieren sudo, no pensé que tuviera una raíz estable, pero tienes razón en eso. – Markus

+0

Ping no utiliza necesariamente sondas ICMP ni sockets sin formato ni necesita privilegios de administrador. –

11

Así es como/sbin/ping "de alguna manera se las arregla" (en la mayoría de los sistemas Unix y):

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

Ver? Es propiedad de root y tiene ese bit crucial s en el permiso - setuserid. Por lo tanto, no importa qué usuario lo esté ejecutando, ping se ejecuta como root.

Si está utilizando un núcleo BSD con los nuevos "sockets ICMP no privilegiados", sería interesante ver qué se necesita para usar esa funcionalidad para hacer ping desde Python (pero eso no ayudará a ningún usuario que esté en núcleo menos avanzado, por supuesto).

+0

Interesante, por lo que los zócalos ICMP no privilegiados son nuevos? Tal vez intente hacer que funcione desde Python cuando tenga algo de tiempo, principalmente por curiosidad. – Markus

+0

No es tan nuevo ** como una especificación ** (creo que se remonta a la antigua gloriosa BSD 4.3! -), pero una implementación _working_ de esa especificación sería bastante nueva (y muy buena noticia, en mi humilde opinión)) –

0

No estoy seguro si está bien para publicar algo en una pregunta que parece que ya ha sido respondida hace un tiempo.

He estado buscando la misma implementación y he encontrado una manera de hacer ICMP vía Python con privilegios que no sean root.

python-ping utiliza de la misma manera 'necesidad-root' hacer un ping, pero se encontró con un informe de error cuando un usuario sugirió cambiar SOCK_RAW a SOCK_DGRAM al llamar sock:

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

El dev explica este será una situación "WONT-FIX" porque en su lugar es un ping UDP.

ya que realmente no me importa si ICMP está saliendo a través de UDP, que siguió adelante y consiguió el código y hizo que la propuso cambiar.

ahora soy capaz de hacer un ping sin llamar subproceso o la necesidad de raíz!

Una vez más, no estoy seguro si publicar aquí después de tanto tiempo está bien, pero pensó que esto era algo mejor!

+0

Ese es un enfoque interesante. Debería funcionar bien, pero estrictamente hablando, ya no es un ping. Eso significa que los firewalls y aquellos que tienen un manejo especial de ping pueden terminar comportándose de manera diferente. – DonGar

+3

Ese enfoque no funciona en absoluto. No puede crear un socket de tipo UDP con el protocolo ICMP. Obtuve EPROTONOSUPPORT (Protocolo no admitido). - La razón es simple: tal combinación de protocolo no existe. (Las pruebas de respuesta son posibles sin privilegios con UDP/TCP, pero eso necesita más que cambios sutiles como este.) –

-2

También estaba buscando una implementación de ping sin usar un subproceso o necesitando root a ping. Mi solución debe ser multiplataforma, es decir, Windows y Linux.

Cambiar el socket en Windows para SOCK_DGRAM resultados en un "protocolo no soportado 100043" excepción. Entonces parece que Windows verifica correctamente si icmp se está enviando en TCP en lugar de UDP. Sin embargo, a Windows no le importa si se ejecuta como "raíz", ya que es un concepto de 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

En realidad, en Windows 7 y Vista sí es necesario 'Ejecutar como administrador' hacer:

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

y como señalas, haciéndolo sobre un socket de datagramas provoca un error.

-8

Me postulo pitón bajo Windows 7, Desde que estoy editando y "compilar" el código bajo Eclipse plug-in pydev, Mi solución fue: Ejecución de la eclipse.exe como administrador: esto soluciona el problema,

Esta solución es similar a ejecutar el cmd como administrador.

+8

No sugiera que las personas ejecuten programas arbitrarios como administrador. Así es como UAC tuvo un mal rap en primer lugar. Su respuesta tampoco ayuda con un programa implementado en producción. – AdmiralNemo

0

La página del manual que está leyendo se trata de "BSD Kernel Interfaces Manual" y parece provenir de "Mac OS X 10.9". Yo no tengo una máquina Mac OS X para probar, pero bajo Linux, como root o como usuario me sale un error de permiso denegado cuando intento abrir un ICMP como:

$ 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 

En OpenBSD consigo un "Protocolo no compatible" error:

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

puede ser alguien podría tratar en MacOS X o de otro tipo BSD, pero de todos modos este tipo de socket no parecerse portátil, por decir lo menos!

+0

Lo está haciendo mal, los mensajes ICMP son captados por los sockets de DGRAM como mensajes de error. Especificar ICMP como protocolo de socket en DGRAM es simplemente incorrecto. –

+0

Hago lo que el OP ha hecho ... y me pide. – Pierre

3

Ping Linuxes modernos usa libcap y le pide a libcap que haga el trabajo.Esto comprueba (funcitons capget/set) y gestionar permisos:

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

Digamos que tiene un programa "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 

Ahora hacer:

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

Ahora, su " myping "funcionará sin raíz. Es decir, siempre que myping sea de hecho un programa binario. Si se trata de un script, esta capacidad debe configurarse en el intérprete del script.

+0

excelente punto, estaba casi en la desesperación de que nadie había mencionado las capacidades. Sin embargo, debe tenerse en cuenta que si su "programa" es una secuencia de comandos, la capacidad debe establecerse en el intérprete de secuencia de comandos en lugar de la secuencia de comandos. – 0xC0000022L