Rootless Pings in Rust

https://news.ycombinator.com/rss Hits: 11
Summary

Rootless pings in Rust Sending a ping by creating an ICMP socket normally requires root: you can鈥檛 create a raw socket to send ICMP packets without it. The ping command line tool works without root however, how is that possible? It turns out you can create a UDP socket with a protocol flag, which allows you to send the ping rootless. I couldn鈥檛 find any simple examples of this online and LLMs are surprisingly bad at this (probably because of the lack of examples). Therefore I posted an example on GitHub in Rust. The gist of it is this: 1. Create a UDP socket with ICMP protocol Using the socket2 crate. use socket2::{Domain, Protocol, Socket, Type}; use std::net::UdpSocket; let socket = Socket::new(Domain::IPV4, Type::DGRAM, Some(Protocol::ICMPV4))?; let socket: UdpSocket = socket.into(); 2. Create and send the ping packet Note that you don鈥檛 need to provide an IP header and that Linux and macOS behave differently here: the Linux kernel overrides the identifier and checksum fields, while macOS does use them and the checksum needs to be correct. let sequence: u16 = 1; let mut packet: Vec<u8> = vec![ 8, // type: echo request 0, // code: always 0 for echo request 0, 0, // checksum: calculated by kernel on Linux, required on macOS 0, 1, // identifier: overwritten by kernel on Linux, not on macOS (sequence >> 8) as u8, (sequence & 0xff) as u8, b'h', b'e', b'l', b'l', b'o', // payload (can be anything) ]; // Checksum is determined by the kernel on Linux, but it's needed on macOS let checksum = calculate_checksum(&packet); packet[2] = (checksum >> 8) as u8; packet[3] = (checksum & 0xff) as u8; // Port can be anything, doesn't matter socket.send_to(&packet, "1.1.1.1:0")?; 3. Receive and interpret the response Here macOS and Linux are different again: macOS includes the IP header in the response, Linux does not. let mut buffer = vec![0u8; 64]; let (size, from_addr) = socket.recv_from(&mut buffer)?; // On macOS, the IP header is included in the received packet, strip it #[cfg(t...

First seen: 2025-12-02 07:53

Last seen: 2025-12-02 17:54