2009-07-27 3 views
17

При попытке выяснить, лучший способ Пинг (ICMP) кое-что из питона, я наткнулся на эти вопросы:питон Непривилегированная ICMP

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

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

Так что, казалось бы, что, по крайней мере, согласно ИКМП, это разрешено. Итак, почему все инструменты python не могут это сделать? Являются ли инструменты python слишком общими и ожидаем, что любая работа над привилегированными сокетами будет привилегированной? Можно ли написать функцию ping в C, которая может ping без привилегий root, и расширять python этим? Кто-нибудь сделал это? Я просто неправильно понял проблему?

+0

Какая операционная система вы используете? [Недавние ядра Linux] (https://lkml.org/lkml/2011/5/10/389) и Mac OS X, как известно, имеют непривилегированные ICMP-сокеты. Страница man, которую вы нашли, находится в OS X, и она должна работать. Я преуспел с непривилегированной программой pure-Python [ping program] (https://github.com/lilydjwg/winterpy/blob/master/pylib/icmplib.py), которая работает в Linux (с изменением настроек ядра) но могут потребоваться некоторые корректировки в OS X. – lilydjwg

+0

Для Linuix, см. здесь http://stackoverflow.com/questions/8290046/icmp-sockets-linux/20105379#20105379, вам нужен специальный sysctl, чтобы иметь возможность использовать 'socket (AF_INET, SOCK_DGRAM, IPPROTO_ICMP) ' – nos

ответ

11

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

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

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

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

+0

А, это одна минута меньше - поскольку короткие интервалы в ping все еще требуют sudo, я не думал, что у этого есть setuid root, но вы явно правы в этом. – Markus

+0

Ping не обязательно использует ICMP-зонды, ни сырые сокеты, ни корневые привилегии. –

11

Вот как/SBIN/пинг "как-то управляет" (на большинстве Unix-систем, у):

$ 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 (но это не поможет ни одному пользователю, находящемуся на менее развитое ядро, конечно).

+0

Интересные, поэтому непривилегированные сокеты ICMP новы? Возможно, я попытаюсь заставить это работать с python, когда у меня есть время, в основном из любопытства. – Markus

+0

Не все это новое ** как спецификация ** (я верю, что это все возвращается к добрым старым славным BSD 4.3!), Но реализация этой спецификации будет очень новой (и очень хорошие новости действительно, IMHO). –

0

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

Я искал ту же реализацию и нашел способ выполнить 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, я пошел вперед и получил код и внес предложение.

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

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

+0

Это интересный подход. Должна работать хорошо, но, строго говоря, это уже не пинг. Это означает, что брандмауэры и такие, которые имеют специальную обработку ping, могут в конечном итоге вести себя по-другому. – DonGar

+3

Этот подход не работает вообще. Вы не можете создать сокет типа UDP с протоколом ICMP. Я получил EPROTONOSUPPORT (протокол не поддерживается). - Причина проста: такой комбинации протоколов не существует. (Ответное тестирование возможно непривилегировано с UDP/TCP, но для этого требуются более тонкие изменения, подобные этому.) –

-2

Я также искал реализацию 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) 
1

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

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

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

-8

Я бег питона под Windows 7, Поскольку я редактирование и «компиляция» код под Eclipse, Pydev плагина, Моего решения было: Запуск eclipse.exe в качестве администратора: это решило проблему,

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

+8

Пожалуйста, не предлагайте людям запускать произвольные программы в качестве администратора. Именно так UAC получил плохой рэп в первую очередь. Ваш ответ также не помогает для программы, развернутой в производство. – AdmiralNemo

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 или другого BSDs, но в любом случае этот тип сокета не похож на портативном, чтобы по меньшей мере!

+0

Вы делаете это неправильно, сообщения ICMP извлекаются сокетами DGRAM в качестве сообщений об ошибках. Указание ICMP как протокола сокетов в DGRAM просто неверно. –

+0

Я делаю то, что сделал OP ... и просит. – Pierre

3

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

+0

Отличная точка, я был почти в отчаянии, о котором никто не упомянул о возможностях. Тем не менее, следует отметить, что если ваша «программа» является скриптом, возможность должна быть установлена ​​в интерпретаторе сценария, а не в скрипте. – 0xC0000022L