/ networking

There's more to localhost than 127.0.0.1

The loopback interface is most familiarly encountered as 127.0.0.1 and is referred to as the local loopback address. This address is present on every IPv4 host and is given the hostname localhost.

What people either don't know or seem to forget is that on the lo interface, there's ~16 million other addresses that applications can also listen on. This means that you can have multiple local services on the same port; as long as they are listening on a dfiferent address.

The local loopback address is not a single address,
it's the range 127.0.0.1 - 127.255.255.254.

There's a lot of addresses to pick from, but not so many ports. It is for this reason, using 127.0.0.1 for everything "local" is dumb. If it's a single instance of a local service, e.g. cockpit, that's okay. Things like local or remote ssh forwards... that's not so okay.

I as a rule, would recommend against ever using 127.0.0.1 for remote/local ssh forwards.

Only use it for things that are truly local.

What to do instead
Create named and organized structures for your localhost addresses, and as needed, putting IPs in /etc/host (or even dns). Have consistent numbering rules. You are far less likely to get clashes, and it makes it easier to infer what the purpose and nature of the service is.

Using meaningful loopback ips is useful for:

  • Virtual hosts
  • Proxys
  • Testing different configurations of a service

Simple Use case

Suppose I have nginx listening on 127.0.0.1:80 and I want to test out an apache2 server. While 127.0.0.1 is occupied, as mentioned earlier, there are 16 million or so addresses we can use instead.

We should try to be consistent and predictable in how we choose to use the address space.

A simple guideline for the listening addresses.
127.80.0.0 is for web servers
127.80.0.x is for nginx and its vhosts
127.80.1.x is for apache and its vhosts.

SSH Forwarding

When I proxy SSH ports, I generally use this convention where I bind to 127.x.y.z where x,y,z are the last three octets of the ssh server IP.

$ ssh -L 127.51.100.69:9090:127.0.0.1:9090 user@198.51.100.69 -N

How local forwarding works*
Port 9090 is the port for cockpit. Going to //127.51.100.69:9090 takes you to the cockpit server on 198.51.100.69.

Since I have cockpit listening on my pc. I can't do the simple ssh local forward of

$ ssh -L 9090:localhost:9090 user@server -N . 

The noob version of me would have done something messy like

$ ssh -L 15256:localhost:9090 user@server -N

which translates to

$ ssh -L localhost:15256:localhost:9090

Proper numbering means it's never going to clash (even if I have hundreds of forwarded connections) and its always unambiguous I'm connecting to is a remote proxy... and you don't need to be arbitrary with picking port numbers.

the cockpit example won't work if cockpit is bound on all interfaces, you can change this in /etc/systemd/system/cockpit.socket).

In some cases, you might want to put these addresses in /etc/hosts

$ vi /etc/hosts
127.0.0.1      localhost localhost.localdomain
198.51.100.69  deusnullus.etherarp.net
127.51.100.69  deusnullus.etherarp.net.localhost

You can batch add with this script

$ read domain;
$ printf "127.%s %s.localhost\n" \
          $(cut -d. -f2,3,4 <<< `dig +short $domain`) \
          $domain  
  >> /etc/hosts

This type of scheme would be useful for SSH reverse forwarding too: