What's My IP Address

One of the most frustrating questions we get in #bash is "Help me extract my IP address from the output of ifconfig." This is a classic XyProblem of the worst kind. People often don't even realize it's a bad question, and then when we try to lead them in a more productive direction, they can't understand why we won't answer the question that they think is so straightforward.

This page, although still incomplete, attempts to give some insight into the multiple layers of complexity that lie behind this deceptively simple question.

Why Do You Care?

Sure, we could tell you one of the hundreds of ways to parse the output of ifconfig using sed or awk or cut or parameter expansions or a plethora of similar tools. But that only helps you insofar as parsing ifconfig output actually makes any sense for achieving your real goal. Without knowing what that goal is, we can't go straight to the heart of the problem, as we would like.

Here is just a small sample of the reasons we've been able to get people to confess, when they asked us this question. There were doubtless many other goals that went undiscovered.

Let's look at some of these issues....

My Laptop, It Moves

Most Linux distributions these days have some sort of mechanism for configuring your network interface, routing table, resolv.conf file, etc. from one of multiple sets of information depending on where you boot the laptop. You should use your OS-provided hooks for setting this stuff up. Why are you reinventing the wheel?

My Address, It Changes

DHCP is a pain in the ass for Unix clients. Unix systems were designed to run services and make them available on the network. If your address keeps changing, how are you supposed to serve anyone?

If you control the DHCP server, it becomes an order of magnitude easier. You can assign an IP address to a specific MAC address, so that your Unix system always comes up with the same IP address. (If you don't control the DHCP servers at work, you might be able to request such a designation from the people who do.) If you control the DHCP server and the DNS server, you can have the DHCP server tell the DNS server what public address it just assigned to your host.

If you need to submit your IP address to a dynamic DNS server directly from the client host, then yes, you will need to have the address available. Usually there will be some hook provided by your DHCP client program that provides the address it just received to a program of your choice, so you don't have to try to reverse engineer the assignment that just took place.

If you choose to reinvent the wheel and grab the first IP address you stumble across from ifconfig in an rc.local script, you still run into another problem: it's permissible for a DHCP server to assign you a different address when your lease on the first one expires. Your DHCP client could (in theory, anyway) change your IP address while you're still using the old one. Now, in practice, if this happens it's going to hurt. You can ameliorate the pain slightly, at least, by not just running a hack script one time in rc.local. Instead, use the hooks provided by your DHCP client. Whenever it changes the IP address, it should have some way of running a program to clean things up. Put your code there.

My Box, It's Old

Shut up, greycat. Nobody cares about your HP-UX systems.

My Firewall, It's A Template

If you want to set up netfilter (iptables) in such a way that the configuration works on a whole bunch of systems, just use the interface name (eth0) instead of the IP address in the rules.

My Company, It's Evil

I wasn't making up the guy who wanted to log information from 4000 "STBs" (set-top boxes -- that was his word for them) in people's homes. That motherfucker went directly onto the /ignore list.

But... But... But...

There is still a fundamental problem at the conceptual level here. Your computer is not likely to have "an IP address". If your computer only has one IP address, then you know a priori that it's 127.0.0.1, so you don't need to parse anything. You also won't care, because you're only talking to yourself.

If you have some sort of hardware interface to a network that speaks the Internet Protocol (ethernet, token ring, wireless alphabet soup, whatever), then you can have one or more IP addresses of two different kinds on each interface. It is perfectly plausible to have a system with a loopback interface, two hardware ethernet interfaces, two IPv4 addresses on the first hardware interface, and an IPv6 address on each hardware interface.

Moreover, there is no standard way to find out what those addresses are. None. Nada. Zip. Any tool you come up with to spit out this information is OS-specific -- even ifconfig.

Let's look at some of those, shall we?

In addition to the OS-specific tool issue, there is Network Address Translation. The address you can see may not be the address by which other computers can reach you. If you have a non-routable LAN IP address, but you can surf, then your packets are probably going through a NAT firewall. The web server sees your data coming from the public interface of the NAT gateway; it doesn't see your LAN IP address at all. Likewise, if your router is set up to redirect packets to you, then people who connect to you do so through the NAT's public interface. They won't even know there's a NAT involved in the picture.

So, when you ask "What's my IP address", do you really mean "What's my LAN IP address", or do you mean "What's my publically visible IP address"? If you mean the latter, there is no conceivable way you can get that information from your local computer. Your local computer doesn't have that information. It only knows the private (LAN) interface of the NAT gateway, not the public interface. If you want to know the public IP, you have to ask some other system that you trust, which is outside of your LAN, to tell you what address it sees when you connect to it.

There are a slew of crappy web sites that provide that information as a service. Most of them bury it in several kilobytes of useless HTML. Try http://wooledge.org/myip.cgi or http://ifconfig.me/ip instead, or set up your own CGI that does the same thing. It's incredibly trivial. Here it is, in its entirety:

cyclops:~$ cat /var/www/htdocs/wooledge.org/myip.cgi 
#!/bin/sh

echo "Content-type: text/plain"
echo
echo "$REMOTE_ADDR"

It could be made even shorter using printf.