Routing Loop Causing TTL Exceeded Errors
Embed This Widget
Add the script tag and a data attribute to embed this widget.
Embed via iframe for maximum compatibility.
<iframe src="https://ipfyi.com/iframe/entity//" width="420" height="400" frameborder="0" style="border:0;border-radius:10px;max-width:100%" loading="lazy"></iframe>
Paste this URL in WordPress, Medium, or any oEmbed-compatible platform.
https://ipfyi.com/entity//
Add a dynamic SVG badge to your README or docs.
[](https://ipfyi.com/entity//)
Use the native HTML custom element.
Packets destined for a specific prefix are caught in a routing loop between two or more routers, each forwarding to the other indefinitely. The IP TTL field decrements at each hop until it reaches zero, at which point the router discards the packet and sends an ICMP Time Exceeded message back to the source. Users experience complete unreachability and traceroute reveals the same router IPs repeating.
Symptoms
- ⚠ traceroute to the affected destination shows the same two or three hops repeating
- ⚠ Ping returns 'Time to live exceeded' (ICMP type 11) instead of a normal reply
- ⚠ Affected destinations become completely unreachable while unrelated routes work fine
- ⚠ Network monitoring shows abnormally high traffic between two routers
- ⚠ Log shows repeated TTL exceeded messages sourced from the same router IPs
- ⚠ Issue appeared after a routing protocol reconfiguration, static route addition, or link failure
Possible Root Causes
- • Misconfigured static route pointing to a next-hop that in turn has a route pointing back, creating a two-hop loop
- • Routing protocol (OSPF, BGP) advertising a more specific prefix back to its own upstream neighbor during network convergence
- • Two routers each using the other as the default gateway when neither has a route to the destination
- • Temporary loop during OSPF or BGP convergence after a link failure before routes are withdrawn
- • Incorrect redistribute statement causing a static default route to be injected into the dynamic routing protocol and learned back
Diagnosis Steps
Step 1: Run traceroute to Identify the Loop
# Linux / macOS
traceroute -m 30 203.0.113.1
# Windows
tracert -h 30 203.0.113.1
# Expected loop output:
# 8 10.1.0.1 2.341 ms
# 9 10.1.0.2 3.112 ms
# 10 10.1.0.1 2.890 ms <-- same as hop 8, loop confirmed
# 11 10.1.0.2 3.067 ms
# ...
# 30 * * * <-- TTL exhausted
Step 2: Check Routing Tables on Suspected Routers
# On router-A (Cisco IOS style)
show ip route 203.0.113.0
# Expected loop: "via 10.1.0.2, GigabitEthernet0/1"
# On router-B
show ip route 203.0.113.0
# "via 10.1.0.1, GigabitEthernet0/0" <- sends back to router-A
# Linux router
ip route show 203.0.113.0/24
# If both point to each other, the loop is confirmed
Step 3: Look for Conflicting Static and Dynamic Routes
# Linux: check all routes including policy tables
ip route show table all | grep 203.0.113
# Cisco: compare static routes against OSPF/BGP learned routes
show ip route static
show ip route ospf
show ip route bgp
# A static route with lower administrative distance can override the correct dynamic route,
# pointing traffic back to a peer that in turn has no route (and uses its own default)
Step 4: Check for Null Route / Black Hole vs Loop Distinction
# A black hole drops silently; a loop cycles with TTL exceeded messages
# If traceroute shows repeating hops = loop; if it shows * * * = black hole
# Check for explicit null routes
ip route show type blackhole
ip route show type unreachable
Step 5: Examine Recent Configuration Changes
# Linux: check recently modified files
ls -lt /etc/network/ /etc/netplan/ /etc/iproute2/rt_tables
# Identify any new static route entries
# Router: check running config change log
show archive log config # Cisco IOS-XE
Solution
Fix 1: Remove the Offending Static Route
# Linux: remove the conflicting static route
sudo ip route del 203.0.113.0/24 via 10.1.0.2
# Verify the loop is broken
traceroute 203.0.113.1
# Make permanent by removing the route from /etc/network/interfaces, /etc/netplan/*.yaml,
# or /etc/iproute2/rt_tables as appropriate
Fix 2: Correct the Next-Hop
If the route is needed but points to the wrong next-hop:
# Replace the incorrect route
sudo ip route replace 203.0.113.0/24 via 198.51.100.1 dev eth0
# For Cisco IOS:
no ip route 203.0.113.0 255.255.255.0 10.1.0.2
ip route 203.0.113.0 255.255.255.0 198.51.100.1
Fix 3: Add a Null Route as Loop Prevention
Install a less-specific null route so that if the dynamic route disappears, traffic falls to the null route rather than the default gateway loop:
# Linux
sudo ip route add blackhole 203.0.113.0/16
# Cisco
ip route 203.0.113.0 255.255.0.0 Null0 254 # AD 254 = only used as last resort
Fix 4: Fix OSPF Redistribute Issue
# Cisco: avoid redistributing connected/static into OSPF if it creates feedback
router ospf 1
no redistribute static subnets
# Or use a route-map to filter:
redistribute static subnets route-map FILTER_STATIC
route-map FILTER_STATIC permit 10
match ip address prefix-list ALLOWED_STATICS
Prevention
- Use a route policy that requires explicit next-hop verification before adding static routes affecting the default path
- Enable OSPF loop prevention features (stub areas, route filtering) and validate with
show ip ospf databaseafter changes - Add null routes (administrative distance 254) for all major summary prefixes as a loop-of-last-resort safeguard
- Implement change management that requires traceroute validation of affected prefixes before and after routing changes
- Monitor ICMP TTL Exceeded rates via SNMP or syslog; a spike indicates a routing loop in progress