Saturday, November 14, 2015

Why loopback is 127.0.0.0/8

If you've played with networking at all, you should be familiar with 127.0.0.1 being localhost.  If you look closely at the network settings, you'll see that this is on a loopback device, and it's configured as a /8 network, not just that one IP address.  That means any IP address in the range of 127.0.0.0 through 127.255.255.255 goes to the loopback device.  Typically your hosts file only uses one of those addresses, namely the aforementioned localhost.

So what's the point of having 24-bits of local IP addressing?  Isn't that just a waste?  Not entirely.  It turns out there is at least one very clever trick you can use this for.

Suppose you have a service running that uses a given port, say port 2159.  Now suppose you have that service running on several systems, and you want to use that service locally.  Now suppose there's a firewall on those boxes that blocks remote access to port 2159.  The obvious solution is to use ssh to forward that port back to the local system.  But if you have the same service in use locally, you have to use a different port number.  Or if you want to work with more than one remote system at a time, you have to use a different port.  This may break your client software that also insists on using port 2159.  You can fix this by inserting iptables rules that direct anything going to port 2159 at the remote IP address to instead go to whatever port number you picked locally.  That works great, except you have to have root access to set iptables rules, and you need to have your kernel configured with the right iptables options, and you have to clean up all the entries when you close your ssh tunnel (which gets tricky someone just kills the process).  This is not a solution that you can deploy as a script for lots of people to use.

Fortunately, you can use port 2159 locally.  The trick is to bind it to a different local IP address.  Since we have millions to choose from, not just one, this is easy.  Say we wanted to use 10.4.5.6:2159.  We set up a ssh tunnel to make that port appear locally on 127.4.5.6:2159.  We can do the same for lots of other systems at the same time.  No need for root access or any other magic hacks (unless the port number is below 1024).

So to implement the above example:
   ssh -L 127.4.5.6:2159:127.0.0.1:2159 -o ExitOnForwardFailure=yes \
       -f -N user@10.4.5.6

Now we just tell our program to connect to 127.4.5.6, and it works just like 10.4.5.6 would, only without being blocked by the firewall.

Interestingly, the designers of IPv6 apparently thought using a /8 for loopback was a waste, so you only get the one IP address there.  I haven't worked much with IPv6, though, so there be similar tricks available.  In any case, you can still use the local IPv4 space even if the real network is IPv6-only.

Oh, and in case you're curious, 2159 is the remote GDB debugging port, so I figured it was a good example.  I've been using this trick at work with a bunch of similar ports for debugging, much of it using internally developed software that doesn't provide an option for using an alternative port number.  While you can make a good argument that all software should allow alternative port numbers (and I would tend to agree), reality is that this is not the case, and this one way of dealing with that.

1 comment:

  1. Prston, as you suspected, your mother doesn't understand a word of this, but I am proud of you!

    ReplyDelete