Подтвердить что ты не робот

Непривилегированный ICMP-питон

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

Ответы обычно сводятся к "использованию этого стороннего модуля с привилегиями root" или "используйте команду ping системы и проанализируйте вывод". Из собственных методов icmplib и M. Cowles и J. Diemer ping.py прямо указывают на необходимость привилегий root, а также scapy руководство.

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

4b9b3361

Ответ 1

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

После того, как он откроет сырой сокет, он обычно отключает корневые привилегии.

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

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

Ответ 2

Здесь как /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 (но это не поможет никому, что на менее конечно, расширенное ядро).

Ответ 3

Современный Linux ping использует libcap и просит libcap выполнить работу. Эти проверки (capget/set 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" будет работать без root. То есть, пока myping на самом деле является двоичной программой. Если это script, эта возможность должна быть установлена ​​вместо интерпретатора script.

Ответ 4

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

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

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

Ответ 5

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

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

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

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

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

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

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

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

Ответ 6

Страница man, которую вы читаете, относится к "Руководству по интерфейсам ядра 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, но в любом случае этот тип сокета не выглядит портативным, если не сказать больше!

Ответ 7

Я также искал реализацию ping, не используя подпроцесс или нуждающийся в корне для ping. Мое решение должно было быть кросс-платформенным, а именно Windows и Linux.

Изменение сокета в Windows на SOCK_DGRAM приводит к исключению "протокол не поддерживается 100043". Таким образом, похоже, что Windows правильно проверяет, отправляется ли icmp на TCP, а не в UDP. Тем не менее, окна все равно, работает ли он как "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)

Ответ 8

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

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