/contrib/famzah

Enthusiasm never stops

Get default outgoing IP address and interface on Linux

5 Comments

Suppose you have one or more network interfaces, and they have one or more assigned IP addresses, also called aliases. If you need to find out which IP address and interface will be used as a default “source” by your Linux box, you need to execute the following:

ip route get 8.8.8.8

This, of course, assumes that 8.8.8.8 is not directly connected on your networks somehow. Since this is one of the Public Name Servers of Google, I think it is safe to assume so.

A sample output of the ip command follows:

8.8.8.8 via 10.0.2.2 dev eth0  src 10.0.2.15
    cache 

The output is pretty much self-explanatory — the route to “8.8.8.8” will originate from device “eth0”, the used source IP address will be “10.0.2.15”, and the next hop, the (default) gateway, will be “10.0.2.2”.

This method is 100% reliable. The man page of “ip” says that “this command gets a single route to a destination and prints its contents exactly as the kernel sees it”.


References:

Author: Ivan Zahariev

An experienced Linux & IT enthusiast, Engineer by heart, Systems architect & developer.

5 thoughts on “Get default outgoing IP address and interface on Linux

  1. Hello!

    Thanks for the tip. ๐Ÿ™‚

    Nevertheless it does not work within an OpenVZ container.

    Is there a reliable way to get the second hop? (“traceroute -n -m 2 8.8.8.8” seems useless)

    Thanks.

    • Hi. I’ve tested it in one of my OpenVZ containers and it works properly:

      root@us:~# uname -a
      Linux vz1.localdomain.tld 2.6.32-5-openvz-686 #1 SMP Tue Mar 8 23:30:33 UTC 2011 i686 GNU/Linux
      
      root@us:~# ifconfig
      venet0    Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  
                inet addr:127.0.0.1  P-t-P:127.0.0.1  Bcast:0.0.0.0  Mask:255.255.255.255
                UP BROADCAST POINTOPOINT RUNNING NOARP  MTU:1500  Metric:1
                RX packets:2062404822 errors:0 dropped:0 overruns:0 frame:0
                TX packets:3481908787 errors:0 dropped:0 overruns:0 carrier:0
                collisions:0 txqueuelen:0 
                RX bytes:4137966362 (3.8 GiB)  TX bytes:2102324686 (1.9 GiB)
      
      venet0:0  Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  
                inet addr:30.40.50.60  P-t-P:30.40.50.60  Bcast:0.0.0.0  Mask:255.255.255.255
                UP BROADCAST POINTOPOINT RUNNING NOARP  MTU:1500  Metric:1
      
      venet0:1  Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  
                inet addr:30.40.50.61  P-t-P:30.40.50.61  Bcast:0.0.0.0  Mask:255.255.255.255
                UP BROADCAST POINTOPOINT RUNNING NOARP  MTU:1500  Metric:1
      
      root@us:~# route -n
      Kernel IP routing table
      Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
      192.0.2.1       0.0.0.0         255.255.255.255 UH    0      0        0 venet0
      0.0.0.0         192.0.2.1       0.0.0.0         UG    0      0        0 venet0
      
      root@us:~# ip route get 8.8.8.8
      8.8.8.8 via 192.0.2.1 dev venet0  src 30.40.50.60 
          cache  mtu 1500 advmss 1460 hoplimit 64
      

      The default source IP is properly detected as “30.40.50.60” which belongs to “venet0:0”.
      Note that I run the default OpenVZ guest configuration where containers have public IP addresses. If you are running your VZ guests behind a NAT, that’s a different story. The article here demonstrates how to get the default outgoing IP address of the machine (which may be a private one), not its real IP address if it’s behind a NAT.

      Regarding the “traceroute” parsing — I don’t recommend it, since “traceroute” is making real network tests which could take a while. Here is an example on how to parse it though:

      taurus:~# traceroute -n 8.8.8.8
      traceroute to 8.8.8.8 (8.8.8.8), 30 hops max, 60 byte packets
       1  192.168.100.1  1.091 ms  1.381 ms  1.708 ms
       2  85.1.2.129     6.825 ms  6.941 ms  7.030 ms
       3  85.1.2.193     7.211 ms  7.324 ms  7.408 ms
      ...and so on...
      
      taurus:~# traceroute -n 8.8.8.8|head -n3|tail -n1|egrep '^[[:space:]]*2'|awk '{print $2}'
      85.1.2.129
      

      The “egrep” is there just as a sanity check that the “head|tail” commands really returned the second hop.

  2. Hello!

    > “not its real IP address if itโ€™s behind a NAT”

    That is the case: all VMs use venet and are “hidden” in a private network.

    And sadly, traceroute always returns the node primary IP adress, not the IP failover used by some containers.

    Anyway, thank you for your help! ๐Ÿ™‚

    • ๐Ÿ™‚ You are welcome. It’s even theoretically impossible to find out the real IP address from the NAT’ed machine, since IP headers rewriting is done outside of the machine, at the router.

      The only solution if you want to figure this out from the local machine, is to query a remote server connected in Internet and ask it to echo your remote IP address. For example, I put the following PHP script at “http://www.famzah.net/temp/ip.php”:

      <?php
      echo $_SERVER['REMOTE_ADDR']."\n";
      

      Then queried for my real IP address in the following way:

      $ curl http://www.famzah.net/temp/ip.php
      85.1.2.145
      
  3. ip route get 8.8.8.8 | awk ‘ NR == 1 {print $NF}’

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s