непривилегированный ICMP python

пытаясь выяснить лучший метод для ping (ICMP) что-то из python, я наткнулся на эти вопросы:

ответы обычно сводятся к "использовать этот сторонний модуль с привилегии root " или "используйте команду ping системы и проанализируйте вывод". Из родных методов,icmplib и М. Коулс и Д. Димер по ping.py содержит положений о необходимости права root, как это делает scapy руководство.

таким образом, с этого фронта, изначально отправка ICMP-пингов без специальных привилегий кажется невозможной. Команда system ping каким-то образом справляется, но ее справочная страница не проливает свет на то, как это сделать. Этот man-страница для 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 слишком общими и ожидают, что любая работа над привилегированными сокетами будет привилегированной? Можно ли написать функцию ping в C, которая может пинговать без привилегий root, и расширить python с этим? Кто-нибудь это сделал? Я просто недопонял проблема?

8 ответов


в программе ping установлен setuid root. Это позволяет любому пользователю использовать программу и по-прежнему иметь возможность открывать необработанный сокет.

после того, как он открывает сырых сокетов, он обычно падает прав root.

вам обычно нужен необработанный сокет для правильной работы ICMP, а необработанные сокеты обычно ограничены. Так что это вообще не вина python.

Что касается бита об ICMP выше, по-видимому, многие реализации на самом деле не поддерживают эти комбинации флаги хорошо. Поэтому вполне вероятно, что большинство implmentations просто использовать так, как они "знают", работает на всех архитектурах.


вот как /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.

Если вы используете ядро BSD с новыми "непривилегированными сокетами ICMP", было бы интересно посмотреть, что необходимо для использования этой функции для ping от Python (но это не поможет любому пользователю, который находится на менее advanced kernel, конечно).


Modern Linuxes ping использует libcap и просит libcap выполнить работу.Это проверяет (capget/set funcitons) и управляет разрешениями:

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 на самом деле является двоичной программой. Если это сценарий, эта возможность должна быть установлена на интерпретаторе сценариев.


на самом деле, в Windows 7 и Vista вам нужно "запустить от имени администратора", чтобы сделать:

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

и, как вы заметили, выполнение этого через сокет дейтаграммы вызывает ошибку.


Я не уверен, что это нормально, чтобы опубликовать что-то в вопросе, который, кажется, уже ответил некоторое время назад.

Я искал ту же реализацию и нашел способ сделать ICMP через Python с некорневыми привилегиями.

python-ping использует тот же "need-root" способ сделать пинг, но наткнулся на отчет об ошибке, где пользователь предложил изменить SOCK_RAW to SOCK_DGRAM при вызове sock :

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

dev объясняет, что это будет ситуация "WONT-FIX", потому что это пинг UDP.

поскольку мне действительно все равно, выходит ли ICMP через UDP, я пошел вперед и получил код и сделал предлагаемое изменение.

теперь я могу сделать пинг без вызова подпроцесса или необходимости root!

опять же, не уверен, что публикация здесь после такого долгое время в порядке,но думал, что это было лучше!


страница man, которую Вы читаете, посвящена " руководству по интерфейсам ядра BSD "и, похоже, происходит от"Mac OS X 10.9". У меня нет машины Mac OS X, чтобы попробовать, но под Linux,как root или как пользователь!--4--> Я получаю разрешение отказано ошибка, когда я пытаюсь открыть такой 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 или другими BSDs, но в любом случае этот тип сокета не выглядит как портативный, чтобы по меньшей мере!


Я также искал реализацию ping без использования подпроцесса или необходимости root для 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)

Я запускаю python под windows 7 , Поскольку я редактирую и" компилирую " код под плагином Eclipse pydev, Мое решение было: запустить eclipse.exe как администратор: это решило проблему,

Это решение аналогично запуску cmd в качестве администратора.