Skip to content Skip to sidebar Skip to footer

Python Non-privileged Icmp

While trying to figure out the best method to ping (ICMP) something from python, I came across these questions: How can I perform a ping or traceroute in python, accessing the out

Solution 1:

The ping program is installed setuid root. This allows any user to use the program, and still be able to open a raw socket.

After it opens the raw socket, it typically drops root privs.

You generally need a raw socket to do ICMP correctly, and raw sockets are usually restricted. So it's not really python's fault at all.

Regarding the bit about ICMP above, apparently many implementations don't really support those combinations of flags well. So it is likely that most implmentations just use the way they "know" works on most / all architectures.

Solution 2:

Here's how /sbin/ping "somehow manages" (on most Unix-y systems):

$ ls -l /sbin/ping
-r-sr-xr-x  1 root  wheel  68448 Jan 26 10:00 /sbin/ping

See? It's owned by root and has that crucial s bit in the permission -- setuserid. So, no matter what user is running it, ping runs as root.

If you're using a BSD Kernel with the new "non-privileged ICMP sockets" it would be interesting to see what's needed to use that functionality to ping from Python (but that won't help any user that's on a less advanced kernel, of course).

Solution 3:

I'm not sure if it is OK to post something in a question that seems it has already been answered a while ago.

I have been searching for the same implementation and found a way to do ICMP via Python with non-root privileges.

python-ping uses the same 'need-root' way to do a ping, but came across a bug report where a user suggested changing SOCK_RAW to SOCK_DGRAM when calling sock :

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

The dev explains this will be a "WONT-FIX" situation because it is a UDP ping rather.

Since I really do not care if ICMP is going out via UDP, I went ahead and got the code and made the proposed changed.

I am now able to do a ping without calling subprocess or needing root!

Again, not sure if posting here after such a long time is OK, but thought this was a better thing!

Solution 4:

Modern Linuxes ping uses libcap and asks libcap to do the work.This checks (capget/set funcitons) and manage permissions:

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)   

Lets say you have a "myping" program:

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  

Now do:

linux@jacax:~/WORK$ getcap ./myping  
./ping = cap_net_raw+ep

Now, your "myping" will work without root. That is, as long as myping is in fact a binary program. If it is a script, this capability has to be set on the script interpreter instead.

Solution 5:

icmplib module helped me with ping without running whole django app as root: https://pypi.org/project/icmplib/

Post a Comment for "Python Non-privileged Icmp"