Pythonから何かをping(ICMP)するための最良の方法を見つけようとしているときに、次の質問に出くわしました。
答えは一般的に「root権限でこのサードパーティモジュールを使用する」または「システムのpingコマンドを使用して出力を解析する」に要約されます。ネイティブメソッドのうち、 icmplib および M.CowlesおよびJ.Diemerのping.py は、 scapy と同様に、root権限の必要性について明示的に言及しています。 手動 。
したがって、その前から、特別な特権なしでICMPpingをネイティブに送信することは不可能に思えます。 system pingコマンドはなんとかして管理しますが、そのマニュアルページはその方法を明らかにしていません。 icmpのmanページ 一方、それは可能だと言っているようです:
非特権ICMP ICMPソケットは、root特権を必要とせずに SOCK_DGRAMソケットタイプで開くことができます。概要は次のとおりです。 socket(AF_INET、SOCK_DGRAM、IPPROTO_ICMP) データグラム指向のICMPソケットは、利用可能な機能のサブセットを提供します- ICMPソケットを生にすることができます。次の タイプのIMCP要求メッセージのみを送信できます:ICMP_ECHO、ICMP_TSTAMP、またはICMP_MASKREQ。
したがって、少なくともicmpによれば、それは許可されているように思われます。では、なぜすべてのpythonツールがこれを実行できないのですか?pythonツールは一般的すぎて、特権ソケットでの作業が特権化されることを期待しているのですか?ルート権限なしでpingできるping関数をCで記述し、これでpythonを拡張することは可能でしょうか?誰かがこれを行ったことがありますか?問題を誤解しただけですか?
Pingプログラムはsetuidrootにインストールされます。これにより、すべてのユーザーがプログラムを使用しながら、rawソケットを開くことができます。
Rawソケットを開いた後、通常はrootprivを削除します。
通常、ICMPを正しく実行するにはrawソケットが必要であり、rawソケットは通常制限されています。したがって、それは実際にはPythonのせいではありません。
上記のICMPについて少し言えば、明らかに多くの実装はこれらのフラグの組み合わせを実際にはうまくサポートしていません。したがって、ほとんどの実装では、ほとんど/すべてのアーキテクチャで「知っている」動作を使用している可能性があります。
/ 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として実行。
新しい「非特権ICMPソケット」でBSDカーネルを使用している場合、その機能を使用してPython)からpingを実行するために何が必要かを確認するのは興味深いでしょう(ただし、それは役に立ちません)もちろん、それほど高度でないカーネルを使用しているユーザー)。
最新のLinuxの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」はルートなしで機能します。つまり、myping
が実際にバイナリプログラムである限り。スクリプトの場合は、代わりにこの機能をスクリプトインタープリターで設定する必要があります。
実際、Windows 7およびVistaでは、次のことを行うために「管理者として実行」する必要があります。
my_socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, icmp)
お気づきのように、データグラムソケットを介して実行するとエラーが発生します。
しばらく前に回答済みのように見える質問に何かを投稿してもよいかどうかはわかりません。
私は同じ実装を探していて、root以外の権限でPythonを介してICMPを実行する方法を見つけました。
python-ping
は同じ 'need-root'方法を使用してpingを実行しますが、ユーザーがsock
を呼び出すときにSOCK_RAW
をSOCK_DGRAM
に変更することを提案したバグレポートに遭遇しました。
http://hg.io/delroth/python-ping/issue/1/icmp-without-root-privilege
開発者は、これはむしろUDP pingであるため、これは「WONT-FIX」状況になると説明しています。
ICMPがUDP経由で送信されるかどうかは本当に気にしないので、先に進んでコードを取得し、提案を変更しました。
サブプロセスを呼び出したり、rootを必要とせずに、pingを実行できるようになりました。
繰り返しになりますが、このような長い時間の後にここに投稿しても大丈夫かどうかはわかりませんが、これはより良いことだと思いました!
あなたが読んでいるmanページは「BSDカーネルインターフェースマニュアル」に関するもので、「Mac OSX10.9」から来ているようです。試すMacOS 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
誰かがMacOSXや他のBSDで試すことができるかもしれませんが、とにかくこのソケットタイプは控えめに言ってもポータブルのようには見えません!