cloudflared decrements the TTL/HopLimit of ICMP packets received from the edge before forwarding them to the origin, which makes cloudflared behave like one hop on the request path.
However, ICMP Echo Reply packets received from the origin are returned to the eyeball with the default TTL instead of preserving the TTL/HopLimit from the origin reply. This makes the reply path inconsistent with the request path and hides the remaining hop limit observed from the origin side.
Expected behavior:
cloudflared should treat the reply path as one hop as well:
- use the received TTL/HopLimit from the origin Echo Reply when available
- decrement it by 1 before returning the packet to the eyeball
- drop the reply if the received TTL/HopLimit is 1 or lower, rather than emitting a packet with TTL=0
- keep the current default TTL fallback only when the received TTL/HopLimit is unavailable
Platform notes:
- Linux can read IPv4 TTL / IPv6 HopLimit via packet control messages.
- Darwin can preserve TTL when the socket returns a full IP packet that can be decoded.
- Windows IPv4 can use the parsed reply Options.TTL.
- Windows IPv6 appears to lack HopLimit in the current parsed Icmp6SendEcho2 reply path, so the default TTL fallback may need to remain there.
cloudflared decrements the TTL/HopLimit of ICMP packets received from the edge before forwarding them to the origin, which makes cloudflared behave like one hop on the request path.
However, ICMP Echo Reply packets received from the origin are returned to the eyeball with the default TTL instead of preserving the TTL/HopLimit from the origin reply. This makes the reply path inconsistent with the request path and hides the remaining hop limit observed from the origin side.
Expected behavior:
cloudflared should treat the reply path as one hop as well:
Platform notes: