What is the difference between ping localhost and ping 127.0.0.1?

The ping command shows the address it resolved the name to. In this case it resolved to the IPv6 localhost address, ::1. On the other hand, 127.0.0.1 is an IPv4 address, so it explicitly makes ping use IPv4.

The sysctl you used only affects IPv4 pings, so you get replies for ::1, but not for 127.0.0.1.

The address you get from resolving localhost depends on how your DNS is resolver is set up. localhost is probably set in /etc/hosts, but in theory you could get it from an actual name server.


As for how to drop IPv6 pings, you may need to look into ip6tables, as there doesn't seem to be a similar sysctl for IPv6. Or just disable IPv6 entirely, if you're not using it in your network. (Though of course that's not a very forward-looking idea, but doable if you're not currently using it anyway.)


127.0.0.1:
127.0.0.1 is the default loopback of most system. A loopback address is an address used by the system to validate the network stack of the OS.
The loopback address for IPv4 could take any value in the subnet 127.0.0.0/8
The loopback address for IPv6 could take any value in the subnet ::1/128
ping any value in those range should work if your network stack is working on your OS.

localhost:
localhost is a hostname, this a sort of domain name but local to your own machine.
This hostname by default point to your IPv4 and IPv6 loopback which is often 127.0.0.1 or ::1.

localhost address could be changed easily by editing the file /etc/hosts.
If your system use the service systemd-resolved, this service will handle the way localhost is resolved.
According to the documentation of systemd-resolved:

The hostnames "localhost" and "localhost.localdomain" (as well as any hostname ending in ".localhost" or ".localhost.localdomain") are resolved to the IP addresses 127.0.0.1 and ::1

ping
When you try to ping a hostname or domain name it will ask the OS to resolve this hostname or domain name. In your case, you disabled icmpv4 but localhost is resolved as your IPv6 loopback and your IPv4 loopback but only your IPv6 loopback answer.
The difference is in one case you're trying to ping an IP and in the other case you ping a hostname that could take several values.

Disable icmpv6
If you don't need IPv6 I advise you to disable it. It will double all the work you would need to do on firewall and configuring services:

sysctl -w net.ipv6.conf.all.disable_ipv6=0

If you still want IPv6 support and want to avoid icmpv6, you could use ip6tables:

ip6tables -A INPUT -p icmpv6 --icmpv6-type echo-request -j DROP

Localhost has two addresses, an IPv6 address ::1 and an IPv4 address 127.0.0.1.

IPv6 is the default protocol, so ::1 is always preferred over 127.0.0.1. This is why you have pinged ::1 when asking to ping localhost.

As for why you could ping ::1 but could not ping 127.0.0.1, your sysctl has only disabled pings for IPv4, but not for IPv6. As far as I can tell, there is no corresponding sysctl to disable pings for IPv6, but you can disable it in the firewall instead if you really need to (of course disabling it is not recommended anyway).

Tags:

Ping

Sysctl