Linux – How come one can successfully ping 127.0.0.2 on Linux

icmpiplinuxloopback

On a FreeBSD system with a loopback network interface …

% ifconfig lo0      
lo0
    link up loopback drv_running running multicast
    nd6 performnud auto_linklocal no_radr
    link rxcsum txcsum hwcsum rxcsum_ipv6 txcsum_ipv6
    link address  metric 0 mtu 16384 
        type 24 linkstate 0 physical 0 baudrate 0 
    inet4 address 127.0.0.1 prefixlen 8 bdaddr 127.0.0.1 
    inet6 address ::1 scope 0 prefixlen 128 bdaddr ::1 scope 0 
    inet6 address fe80::1 scope 3 prefixlen 64 
    inet6 address ::2 scope 0 prefixlen 128 
    inet4 address 127.53.0.1 prefixlen 8 bdaddr 127.53.0.1 
    inet4 address 127.53.1.1 prefixlen 8 bdaddr 127.53.1.1 
%

… pinging the IP address 127.0.0.2, which is not assigned to that (or to any other) network interface results in failure:

% ping -c 1 127.0.0.2  
PING 127.0.0.2 (127.0.0.2): 56 data bytes
ping: sendto: Network is unreachable

--- 127.0.0.2 ping statistics ---
1 packets transmitted, 0 packets received, 100.0% packet loss
% 

The same is true for OpenBSD:

% ping -c 1 127.0.0.2      
PING 127.0.0.2 (127.0.0.2): 56 data bytes
ping: sendto: Network is unreachable
ping: wrote 127.0.0.2 64 chars, ret=-1
--- 127.0.0.2 ping statistics ---
1 packets transmitted, 0 packets received, 100.0% packet loss
% 

But on Linux where there is similarly no 127.0.0.2 configured …

% ifconfig lo
lo
    link up loopback running
    link address 00:00:00:00:00:00 bdaddr 00:00:00:00:00:00 
    inet4 address 127.0.0.1 prefixlen 8 bdaddr 127.0.0.1 
    inet4 address 127.53.0.1 prefixlen 8 bdaddr 127.255.255.255 
    inet6 address ::2 scope 0 prefixlen 128 
    inet6 address fe80:: scope 1 prefixlen 10 
    inet6 address ::1 scope 0 prefixlen 128 
% 

… the ping is surprisingly successful:

% ping -c 1 127.0.0.2
PING 127.0.0.2 (127.0.0.2) 56(84) bytes of data.
64 bytes from 127.0.0.2: icmp_seq=1 ttl=64 time=0.044 ms

--- 127.0.0.2 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.044/0.044/0.044/0.000 ms
% 

How come?

Related questions

Other references

  • Jonathan de Boyne Pollard (2019). ifconfig. nosh Guide. Softwares.

Best Answer

ip-route is used to manipulate entries in the kernel routing tables.

Route types:

unicast - the route entry describes real paths to the destinations covered by the route prefix.

...

local - the destinations are assigned to this host. The packets are looped back and delivered locally.

$ ip -4 route show table all type local
local 127.0.0.0/8 dev lo table local proto kernel scope host src 127.0.0.1 
local 127.0.0.1 dev lo table local proto kernel scope host src 127.0.0.1 
local 172.16.8.139 dev wlp2s0 table local proto kernel scope host src 172.16.8.139 
local 192.168.122.1 dev virbr0 table local proto kernel scope host src 192.168.122.1

$ ip -4 address show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
4: wlp2s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    inet 172.16.8.139/24 brd 172.16.8.255 scope global dynamic noprefixroute wlp2s0
       valid_lft 36391sec preferred_lft 36391sec
5: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
       valid_lft forever preferred_lft forever

When an address is added to an interface, a local route is automatically added for the address. Additionally, when an address is added to a loopback interface (IFF_LOOPBACK), a local route is added for the network prefix of the address. In Linux 5.0, you can find this implemented in fib_add_ifaddr().


In contrast, when an address is added to a non-loopback interface, a unicast route is added for the network prefix.

$ ip -4 route show table all type unicast
default via 172.16.8.1 dev wlp2s0 proto dhcp metric 600 
172.16.8.0/24 dev wlp2s0 proto kernel scope link src 172.16.8.139 metric 600 
192.168.122.0/24 dev virbr0 proto kernel scope link src 192.168.122.1 linkdown

The local routes are added to a specific table called "local". The most obvious significance of this is that a quick ip -4 route will not show the local table. This is because it is equivalent to ip -4 route show table main.


linux-ip.net has some broader information. It mentions two other uses of the local table.

The above will likely apply to any version of Linux that you encounter. I am not sure exactly how far back it goes. However the ip route command is already ancient; it goes back to at least the days of Linux 2.2.

Related Question