Closed csulit closed 3 years ago
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.
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.
sudo setcap 'CAP_NET_RAW+eip CAP_NET_ADMIN+eip' .venv/bin/python3
@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.
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
@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.
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 😄
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
andtraceroute
.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!!
@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 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!
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
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.
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! 👍
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.
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!
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
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.
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 "
Does anyone know how to fix
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 :wink:
Thank you Valentine. My mistake is that I did not read the readme file. Everything works now!
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.