= 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 [[BadQuestions|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 [[BashFAQ/073|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. * I have a laptop, and I want to configure routing differently when I plug it in at home vs. when I plug it in at work. * I have a legacy Unix system that gets its primary interface's IP address through DHCP, with no hooks for running scripts with the DHCP client-supplied information. I have to manually construct an `/etc/hosts` with the address. * I run a Linux system at home, and I have to send my (DHCP-supplied) IP address to a dynamic DNS service provider to update my A/MX records. * I'm trying to set up iptables, and then I want to copy this configuration to a dozen more systems, without changing it for every one. * I work for someone that wants to run a script on 4000 personal digital video recorder boxes in other people's homes. I want to collect information from these boxes and log it somewhere, with the logs identified by the client box's IP address. 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''. Here's an example, from Debian 8.x: {{{ $ cat /etc/dhcp/dhclient-exit-hooks.d/update-dns #!/bin/sh if [ "$new_ip_address" ] && [ "$new_ip_address" != "$old_ip_address" ]; then /usr/local/sbin/dync "$new_ip_address" fi }}} Notice how you ''do not'' have to get the IP address by parsing some random utility's output. It's provided to you directly in an environment variable. == 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? * OpenBSD 4.7: {{{ $ ifconfig -aA lo0: flags=8049 mtu 33160 priority: 0 groups: lo inet 127.0.0.1 netmask 0xff000000 inet6 ::1 prefixlen 128 inet6 fe80::1%lo0 prefixlen 64 scopeid 0x4 nfe0: flags=8843 mtu 1500 lladdr 00:26:18:56:6d:2f priority: 0 media: Ethernet autoselect (100baseTX full-duplex) status: active inet 192.168.2.1 netmask 0xffffff00 broadcast 192.168.2.255 inet6 fe80::226:18ff:fe56:6d2f%nfe0 prefixlen 64 scopeid 0x1 inet 192.168.3.1 netmask 0xffffff00 broadcast 192.168.3.255 msk0: flags=8843 mtu 1500 lladdr 00:21:91:19:97:63 priority: 0 media: Ethernet autoselect (100baseTX full-duplex) status: active inet6 fe80::221:91ff:fe19:9763%msk0 prefixlen 64 scopeid 0x2 enc0: flags=0<> mtu 1536 priority: 0 pppoe0: flags=8851 mtu 1492 priority: 0 dev: msk0 state: session sid: 0x692 PADI retries: 76 PADR retries: 0 time: 11d 15:51:00 sppp: phase network authproto pap groups: pppoe egress inet6 fe80::226:18ff:fe56:6d2f%pppoe0 -> prefixlen 64 scopeid 0x5 inet 209.142.155.49 --> 69.29.183.11 netmask 0xffffffff pflog0: flags=141 mtu 33160 priority: 0 groups: pflog }}} Notice the routable ("real Internet") IPv4 (`inet`) address on `pppoe0` and the two non-routable (Local Area Network, LAN) IPv4 addresses on `nfe0`. Also note that the names of the interfaces on a BSD system are derived from the name of the driver that controls the interface. They could be `xl` or `nfe` or `vr` or dozens of others. Also notice the three IPv6 (`inet6`) addresses. * Debian 5.0: {{{ $ ip addr show 1: lo: mtu 16436 qdisc noqueue state UNKNOWN link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth0: mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000 link/ether 00:0f:ea:47:15:da brd ff:ff:ff:ff:ff:ff inet 192.168.3.5/24 brd 192.168.3.255 scope global eth0:1 inet 192.168.2.5/24 brd 192.168.2.255 scope global eth0 inet6 fe80::20f:eaff:fe47:15da/64 scope link valid_lft forever preferred_lft forever }}} Linux during this time period began all ethernet interface names with `eth`, unlike BSD systems, where the interface name is the driver name plus a number. Linux uses a different nomenclature for wireless interfaces, though. Here, notice the two IPv4 (`inet`) and the IPv6 (`inet6`) addresses on `eth0`. <
><
> Note here that the `ifconfig` command was not even used. Debian and many other OSes based on Linux are moving to the `ip` command. <
><
> It's also interesting to note that the display of the IP-aliased addresses (the two IPv4s on `eth0`) does not align with the way IP aliasing is ''defined'' on a Debian system, in the `interfaces(5)` file: {{{ # ... some stuff has been omitted ... allow-hotplug eth0 iface eth0 inet static address 192.168.2.5 netmask 255.255.255.0 gateway 192.168.2.1 auto eth0:1 iface eth0:1 inet static address 192.168.3.5 netmask 255.255.255.0 up iptables -A OUTPUT -t mangle -m owner --uid-owner 1007 -j TOS --set-tos 0x02 }}} It's even ''more'' interesting (to me at least) to note that the ''order'' of the IPv4 addresses is not "`eth0` first, then `eth0:0` and so on". The primary address showed up last. (The manual does not specify this, so don't assume anything.) * Debian 7.x: {{{ $ ip -o addr show 1: lo: mtu 16436 qdisc noqueue state UNKNOWN \ link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 1: lo inet 127.0.0.1/8 scope host lo 1: lo inet6 ::1/128 scope host \ valid_lft forever preferred_lft forever 2: eth0: mtu 1500 qdisc pfifo_fast state UP qlen 1000\ link/ether 78:ac:c0:a9:92:64 brd ff:ff:ff:ff:ff:ff 2: eth0 inet 192.168.2.6/24 brd 192.168.2.255 scope global eth0 2: eth0 inet 192.168.3.6/24 brd 192.168.3.255 scope global eth0:1 2: eth0 inet6 fe80::7aac:c0ff:fea9:9264/64 scope link \ valid_lft forever preferred_lft forever }}} Or, if you just want the IPv4 addresses: {{{ $ ip -o -4 addr show 1: lo inet 127.0.0.1/8 scope host lo 2: eth0 inet 192.168.2.6/24 brd 192.168.2.255 scope global eth0 2: eth0 inet 192.168.3.6/24 brd 192.168.3.255 scope global eth0:1 }}} * Debian 9.x: Starting with this version, Debian no longer includes `ifconfig` in the default installation; only `ip`. Also, interface names are created using [[https://www.debian.org/releases/stretch/amd64/release-notes/ch-whats-new.en.html#new-interface-names|systemd predictable names]] by default, although there are ways to return to the old eth0, eth1, etc. * HP-UX 10.20: {{{ $ netstat -in Name Mtu Network Address Ipkts Ierrs Opkts Oerrs Coll ni0* 0 none none 0 0 0 0 0 ni1* 0 none none 0 0 0 0 0 lo0 4608 127 127.0.0.1 73705400 0 73705400 0 0 lan0 1500 10.76.172.0 10.76.173.78 78729542 14 77788491 0 0 $ ifconfig lan0 lan0: flags=863 inet 10.76.173.78 netmask fffffe00 broadcast 10.76.173.255 }}} HP-UX uses `lan` in much the same way Linux uses `eth`, at least for the interfaces that ship with their workstations. I don't have access to any HP-UX systems that are using [[http://forums11.itrc.hp.com/service/forums/questionanswer.do?admit=109447626+1282003051966+28353475&threadId=1225464|IP aliasing]], so unfortunately I can't give any better examples. <
><
> Of note here is the fact that there's no `ifconfig -a` analog to show all the information at once. You must get the interface names somehow (`netstat -i` and variants are handy there), and then pass them to `ifconfig` one by one if you want details. {{{ $ ifconfig -a ifconfig: no such interface }}} 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`.