Fix/IStartup Capabilites/IPv6, ip version flag, operational metrics#2
Merged
Bierchermuesli merged 5 commits intomainfrom Apr 2, 2026
Merged
Conversation
…for raw ICMP sockets
The privileged variable was derived from conn == nil, which was only true
for the dontFragment/v4RawConn path. When udp4 failed and fell back to
ip4:icmp (or ip6:ipv6-icmp succeeded), the flag was incorrectly false,
causing two bugs:
1. dst was wrapped as *net.UDPAddr ("8.8.8.8:0") but ReadFrom on a raw
ICMP socket returns *net.IPAddr ("8.8.8.8"), so the peer comparison
always failed and every reply was silently dropped, causing timeout.
2. The ICMP echo ID check was skipped for raw sockets, allowing stray
packets to match.
Replace with useUDP bool set only when udp4/udp6 socket is actually used.
Fixes ping in Docker containers with NET_RAW where udp4 is unavailable
and the ip4:icmp fallback is used. IPv6 fallback from ip6:ipv6-icmp to
udp6 is also correctly tracked.
Move per-packet and socket-selection logs to DEBUG level. Add a single INFO summary line per probe (sent/received/loss/avg_rtt). Improve error messages to surface both udp4 and raw socket failures when neither works. Update README permissions section to document the two socket modes (unprivileged udp4/udp6 vs raw ip4:icmp/ip6:ipv6-icmp), clarify that NET_RAW is not required in Docker when the host ping_group_range sysctl is permissive, and remove the duplicate/incorrect "NET_RAW is required" note from the Docker usage example.
Default ip_protocol changes from ip4 to auto. In auto mode, literal IPv4/IPv6 addresses are detected by family so e.g. 2600:: no longer fails with "no suitable address found". For hostnames, AAAA is tried first (IPv6-first, RFC 8305 / Happy Eyeballs intent) but only if the system can actually open an IPv6 ICMP socket — detected once at startup via DetectCapabilities(). This prevents dual-stack hostname probes from failing on IPv4-only systems. Add --ping.default-ip-protocol flag (ip4/ip6/auto) to set the system-wide default, overridable per probe via the ip_protocol URL parameter. Update README with IP protocol auto-detection behaviour, updated parameter defaults, and new --ping.default-ip-protocol flag documentation.
… fail fast if none Extend Capabilities with IPv4UDP/IPv6UDP flags so performPing goes straight to the correct socket type instead of try-and-fail on every probe. Detection order: raw (ip4:icmp / ip6:ipv6-icmp) is tried first — if CAP_NET_RAW or root is present it wins. UDP (udp4/udp6) is the fallback for truly unprivileged environments where ping_group_range allows it. This ensures the startup log accurately reflects the socket type in use (e.g. sudo shows raw/CAP_NET_RAW, not udp/unprivileged). Logging moved from DetectCapabilities into main so capabilities and the failure path are reported in one place with clear socket type labels (raw/CAP_NET_RAW, udp/unprivileged, unavailable) instead of ambiguous boolean flags. Fail at startup with a descriptive error if neither IPv4 nor IPv6 ICMP is available, rather than letting every probe fail silently.
Add exporter-level metrics to /metrics:
- ping_exporter_capability_info{ipv4, ipv6} — socket type in use at startup
- ping_exporter_probes_total{result, ip_version} — probe success/failure counts
- ping_exporter_packets_sent_total{ip_version} — aggregate packets sent
- ping_exporter_packets_received_total{ip_version} — aggregate packets received
- ping_exporter_probe_duration_seconds{ip_version} — probe duration histogram
All metrics are split by ip_version (4/6) derived from probe_ping_ip_version.
Fix IPv6 capability detection: opening ip6:ipv6-icmp on :: succeeds even
when no IPv6 address is configured (the socket opens but cannot route).
Add hasRoutableAddress() which checks for a non-loopback, non-link-local
address on an up interface before attempting to open the ICMP socket.
Containers without IPv6 now correctly report ipv6=unavailable.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problems
ip_protocoldefaulted to hardcodedip4— literal IPv6 addresses like2600::always failed withaddress 2600::: no suitable address found- or if FQDN only resolves to AAAAChanges
Auto IP family detection (
--ping.default-ip-protocol, defaultauto)ip_protocolparam needed--ping.default-ip-protocolflag (ip4/ip6/auto) sets the system-wide default; overridable per probe viaip_protocolURL parameterStartup capability detection (
DetectCapabilities)ip4:icmp/ip6:ipv6-icmp) is tried first, UDP (udp4/udp6) as fallback. however - again: udp should be preffered and NET_RAW is not neededperformPinguses the detected type directly — no per-probe try-and-failraw/CAP_NET_RAW,udp/unprivileged,or
unavailable— not ambiguous booleansStartup says now either:
level=ERROR source=main.go:120 msg="No ICMP socket available — cannot ping anything" ipv4=unavailable ipv6=unavailable hint="add CAP_NET_RAW or set net.ipv4.ping_group_range"(exit)level=INFO source=main.go:124 msg="ICMP sockets ready" ipv4=udp/unprivileged ipv6=udp/unprivilegedINFO source=main.go:124 msg="ICMP sockets ready" ipv4=udp/unprivileged ipv6=udp/unprivilegedINFO source=main.go:153 msg="ICMP sockets ready" ipv4=raw/CAP_NET_RAW ipv6=unavailable(IPv4 only probes)new in
/metricsNote
This branch includes commits from #1
fix/icmp-socket-privileged-detection— that PR should be merged first.