Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Any work around to run w/o root priv? #6

Closed
csulit opened this issue Jun 6, 2020 · 18 comments
Closed

Any work around to run w/o root priv? #6

csulit opened this issue Jun 6, 2020 · 18 comments

Comments

@csulit
Copy link

csulit commented Jun 6, 2020

I'm planning to include this on my flask api project something like http://url/icmplib/ping/192.168.1.1 and will give a response of json.

@ValentinBELYN
Copy link
Owner

Unfortunately, icmplib uses raw sockets to forge ICMP packets, which require root privileges to run. ICMP is a network-layer protocol. Only raw sockets allow us to modify the IP header.

However, I will see if there is a solution. If there is one, it will certainly be implemented in the v2 scheduled for the beginning of next year.

@ValentinBELYN
Copy link
Owner

Hi 👋

There is a solution to allow the library to be used without being root. It consists of using a SOCK_DGRAM socket (normally used to transmit UDP datagrams). Unfortunately, this solution is not perfect. Indeed, it isn't compatible with Windows systems. In addition, the original ID of the ICMP packets is not kept. Consequently, it's more difficult to correctly link requests and responses, especially when these operations are parallelized. I'm not sure if this solution is viable.

I continue my tests.

@hramcovdv
Copy link

sudo setcap 'CAP_NET_RAW+eip CAP_NET_ADMIN+eip' .venv/bin/python3

@ValentinBELYN
Copy link
Owner

@hramcovdv Thank you for your participation. I hadn't thought about it and it's a good solution for those who want to use this library without root privileges. However, cap_net_admin is not required.

@hramcovdv @csulit Here is the command line to execute:

sudo setcap cap_net_raw+ep $(realpath $(which python3))

The downside of this method is that it allows all python scripts to use raw sockets without being root. Anyway, I'm not sure there is a better solution.

@nvannote
Copy link

nvannote commented Aug 6, 2020

Just passing through during a late night of code spelunking and I noticed your comments in regards to the ICMP ECHO identifier getting lost with DGRAM/ICMP.

I have been down this road before and yes, that tidbit of information was a bit difficult to track down.

In that configuration, Linux is replacing the identifier with the local port number of the socket. And yes, for some reason Linux assigns a (seemingly fictitious) port number to these DGRAM/ICMP sockets. macOS/Darwin/BSD don't seem to do any of this trickery.

https://lwn.net/Articles/420800/

So, if you are ok with the local "port" number (getsockname will get that) as an identifier under Linux; you're all set. Note, in Python of course you will get that from getsockname pre-flipped in host byte order; but it will come back to you in the reply in network byte order.

Best Regards

@ValentinBELYN
Copy link
Owner

@nvannote Your comment is very interesting. A big thank you for your participation! I hadn't noticed this behavior. However, this solution doesn't work on Windows. I have to think about it.

@ValentinBELYN
Copy link
Owner

Hello everyone!

I am pleased to announce that the next major version of icmplib (2.0) will no longer require you to be root to use the library. You will have the choice.

For this, all the foundations of the library will be completely reworked without loss of compatibility with the current high-level functions ping, multiping and traceroute.

The performances will also be improved with a single thread for the multiping function compared to as many threads as hosts to reach currently. It will also make this function more memory efficient.

Many more cool features to come 🎉 Of course the library will always be as light.
The version 2.0 will be launched at the end of the year! Stay tuned 🍻

Thank you for using and participating in this project 😄

@csulit
Copy link
Author

csulit commented Oct 31, 2020

Hello everyone!

I am pleased to announce that the next major version of icmplib (2.0) will no longer require you to be root to use the library. You will have the choice.

For this, all the foundations of the library will be completely reworked without loss of compatibility with the current high-level functions ping, multiping and traceroute.

The performances will also be improved with a single thread for the multiping function compared to as many threads as hosts to reach currently. It will also make this function more memory efficient.

Many more cool features to come 🎉 Of course the library will always be as light.
The version 2.0 will be launched at the end of the year! Stay tuned 🍻

Thank you for using and participating in this project 😄

Exciting!!

@ValentinBELYN
Copy link
Owner

@csulit Thanks! 😄

The release of the new version is getting closer. I am planning a release for mid-November and... maybe tomorrow for a beta version!

@csulit
Copy link
Author

csulit commented Oct 31, 2020

@csulit Thanks! 😄

The release of the new version is getting closer. I am planning a release for mid-November and... maybe tomorrow for a beta version!

You're Welcome :) thank you for sharing!

@ValentinBELYN
Copy link
Owner

Hi 👋

icmplib 2.0 can now be tested in an experimental version! Don't hesitate to tell me about potential bugs 😄
The multiping function is currently not available.

To install the new version, follow these instructions:

# Uninstall icmplib
pip3 uninstall icmplib

# Download and extract this repository
wget -qO- https://github.com/ValentinBELYN/icmplib/archive/master.tar.gz | tar -xzf -
cd icmplib-master

# Install the version under development:
python3 setup.py install

Ping

def ping(address, count=4, interval=1, timeout=2, id=PID, source=None,
    privileged=True, **kwargs):

Since the documentation is not yet up to date on GitHub, here are the new parameters and exceptions for the ping function:

    Send ICMP Echo Request packets to a network host.

    :type address: str
    :param address: The IP address, hostname or FQDN of the host to
        which messages should be sent. For a deterministic behavior,
        prefer to use an IP address.

    :type count: int, optional
    :param count: The number of ping to perform. Default to 4.

    :type interval: int or float, optional
    :param interval: The interval in seconds between sending each
        packet. Default to 4.

    :type timeout: int or float, optional
    :param timeout: The maximum waiting time for receiving a reply in
        seconds. Default to 2.

    :type id: int, optional
    :param id: The identifier of ICMP requests. Used to match the
        responses with requests. In practice, a unique identifier
        should be used for every ping process. On Linux, this
        identifier is ignored when the `privileged` parameter is
        disabled.

    :type source: str, optional
    :param source: The IP address from which you want to send packets.
        By default, the interface is automatically chosen according to
        the specified destination.

    :type privileged: bool, optional
    :param privileged: When this option is enabled, this library fully
        manages the exchanges and the structure of the ICMP packets.
        Disable this option if you want to use this function without
        root privileges and let the kernel handle ICMP headers.
        Default to True.
        Only available on Unix systems. Ignored on Windows.

    Advanced (**kwags):

    :type payload: bytes, optional
    :param payload: The payload content in bytes. A random payload is
        used by default.

    :type payload_size: int, optional
    :param payload_size: The payload size. Ignored when the `payload`
        parameter is set. Default to 56.

    :type traffic_class: int, optional
    :param traffic_class: The traffic class of ICMP packets.
        Provides a defined level of service to packets by setting the
        DS Field (formerly TOS) or the Traffic Class field of IP
        headers. Packets are delivered with the minimum priority by
        default (Best-effort delivery).
        Intermediate routers must be able to support this feature.
        Only available on Unix systems. Ignored on Windows.

    :rtype: Host
    :returns: A `Host` object containing statistics about the desired
        destination.

    :raises NameLookupError: If you pass a hostname or FQDN in
        parameters and it does not exist or cannot be resolved.
    :raises SocketPermissionError: If the privileges are insufficient
        to create the socket.
    :raises SocketAddressError: If the source address cannot be
        assigned to the socket.
    :raises ICMPSocketError: If another error occurs. See the
        `ICMPv4Socket` or `ICMPv6Socket` class for details.

Traceroute

def traceroute(address, count=2, interval=0.05, timeout=2, id=PID, max_hops=30,
    source=None, fast=False, **kwargs):

Parameters and exceptions for the traceroute function:

    Determine the route to a destination host.

    The Internet is a large and complex aggregation of network hardware,
    connected together by gateways. Tracking the route one's packet
    follow can be difficult. This function uses the IP protocol time to
    live field and attempts to elicit an ICMP Time Exceeded response
    from each gateway along the path to some host.

    This function requires root privileges to run.

    :type address: str
    :param address: The IP address, hostname or FQDN of the host to
        reach. For a deterministic behavior, prefer to use an IP
        address.

    :type count: int, optional
    :param count: The number of ping to perform per hop. Default to 2.

    :type interval: int or float, optional
    :param interval: The interval in seconds between sending each
        packet. Default to 0.05.

    :type timeout: int or float, optional
    :param timeout: The maximum waiting time for receiving a reply in
        seconds. Default to 2.

    :type id: int, optional
    :param id: The identifier of ICMP requests. Used to match the
        responses with requests. In practice, a unique identifier
        should be used for every traceroute process. By default, the
        identifier corresponds to the PID.

    :type max_hops: int, optional
    :param max_hops: The maximum time to live used in outgoing probe
        packets. Default to 30.

    :type source: str, optional
    :param source: The IP address from which you want to send packets.
        By default, the interface is automatically chosen according to
        the specified destination.

    :type fast: bool, optional
    :param fast: When this option is enabled and an intermediate router
        has been reached, skip to the next hop rather than perform
        additional requests. The `count` parameter then becomes the
        maximum number of requests in the event of no response.
        Default to False.

    Advanced (**kwags):

    :type payload: bytes, optional
    :param payload: The payload content in bytes. A random payload is
        used by default.

    :type payload_size: int, optional
    :param payload_size: The payload size. Ignored when the `payload`
        parameter is set. Default to 56.

    :type traffic_class: int, optional
    :param traffic_class: The traffic class of ICMP packets.
        Provides a defined level of service to packets by setting the
        DS Field (formerly TOS) or the Traffic Class field of IP
        headers. Packets are delivered with the minimum priority by
        default (Best-effort delivery).
        Intermediate routers must be able to support this feature.
        Only available on Unix systems. Ignored on Windows.

    :rtype: list of Hop
    :returns: A list of `Hop` objects representing the route to the
        desired destination. The list is sorted in ascending order
        according to the distance, in terms of hops, that separates the
        remote host from the current machine. Gateways that do not
        respond to requests are not added to this list.

    :raises NameLookupError: If you pass a hostname or FQDN in
        parameters and it does not exist or cannot be resolved.
    :raises SocketPermissionError: If the privileges are insufficient
        to create the socket.
    :raises SocketAddressError: If the source address cannot be
        assigned to the socket.
    :raises ICMPSocketError: If another error occurs. See the
        `ICMPv4Socket` or `ICMPv6Socket` class for details.

Thank you for your feedbacks! 👍

@ValentinBELYN
Copy link
Owner

icmplib 2.0 will be available on November 15th!

You can now download the pre-release version by following these instructions:

# Uninstall icmplib
pip3 uninstall icmplib

# Download and extract this repository
wget -qO- https://github.com/ValentinBELYN/icmplib/archive/master.tar.gz | tar -xzf -
cd icmplib-master

# Install the version under development
python3 setup.py install

The multiping function is back and many fixes have been made since the last beta version. Some small details can still be changed before the final version.

@ValentinBELYN
Copy link
Owner

Hi 👋

icmplib 2.0 is now available! All the foundations of the library have been completely reworked to make it even faster. You can now use the library without root privileges. 🎉
Hope you will like this new version!

Click here to see the full changelog

@max-block
Copy link

It looks like root privs are still required:
res = traceroute("8.8.8.8") throws
icmplib.exceptions.SocketPermissionError: Root privileges are required to create the socket

macOS 12.2
icmplib 2.0.2

@ValentinBELYN
Copy link
Owner

ValentinBELYN commented Feb 16, 2021

Hi @max-block,

The traceroute function is the only function of the library that requires root privileges. It is also written in the README: https://github.com/ValentinBELYN/icmplib#traceroute 😄

Traceroute
Determine the route to a destination host.
[...]
This function requires root privileges to run.

This is a technical constraint. To capture responses from intermediate gateways, I have to use raw sockets which require root privileges.

When you have any questions, please feel free to open a new issue. Your question is interesting and might interest other people. Opening a dedicated issue (unless another is already open on this subject) allows it to be more visible.

@tuser-code
Copy link

Hello!
icmplib-2.1.1
On Raspberry PI 4, i got:
Python 3.7.3 (default, Jan 22 2021, 20:04:44)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.

from icmplib import ping
host = ping('192.168.2.1', count=10, interval=0.5, timeout=1)
Traceback (most recent call last):
File "/home/pi/.local/lib/python3.7/site-packages/icmplib/sockets.py", line 90, in init
socket.SOCK_DGRAM)
File "/home/pi/.local/lib/python3.7/site-packages/icmplib/sockets.py", line 455, in _create_socket
proto=socket.IPPROTO_ICMP)
File "/usr/lib/python3.7/socket.py", line 151, in init
_socket.socket.init(self, family, type, proto, fileno)
PermissionError: [Errno 1] Operation not permitted

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "", line 1, in
File "/home/pi/.local/lib/python3.7/site-packages/icmplib/ping.py", line 133, in ping
privileged=privileged)
File "/home/pi/.local/lib/python3.7/site-packages/icmplib/sockets.py", line 97, in init
raise SocketPermissionError
icmplib.exceptions.SocketPermissionError: Root privileges are required to create the socket

Does anyone know how to fix

@ValentinBELYN
Copy link
Owner

Hi @tuser-code,
Did you follow the instructions described in the README?

Use instead:

host = ping('192.168.2.1', count=10, interval=0.5, timeout=1, privileged=False)

If you are using Raspberry Pi OS, you need to configure your system before:
https://github.com/ValentinBELYN/icmplib#how-to-use-the-library-without-root-privileges

Finally, feel free to open a new issue when you have any questions or encounter any bugs 😉

@tuser-code
Copy link

Thank you Valentine. My mistake is that I did not read the readme file. Everything works now!

Repository owner locked as resolved and limited conversation to collaborators May 30, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants