непривилегированный ICMP python
пытаясь выяснить лучший метод для ping (ICMP) что-то из python, я наткнулся на эти вопросы:
- как я могу выполнить ping или traceroute в python, получая доступ к выходу по мере его создания?
- ping сайт в python
- как я могу выполнить ping или traceroute с помощью собственного 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 в качестве администратора.