Get all public interface IPs on a system using Python


     I recently came across a requirement in a project where I had to, in Python, programmatically extract all available public IPs on available interfaces on the machine the code would run. I looked around and settled with the following snippet of code that uses the built-in, standard socket Python module:

import socket
ip_list = [ip for ip in socket.gethostbyname_ex(socket.gethostname())[2] if not ip.startswith("127.")]

     While this piece of code does find a public IP listening on any of the available interfaces, its restriction lies in not being able to return all public IPs on interfaces: It gives back just one IP.

     This wasn’t clearly sufficient. I looked around again, and this time, found a third-party Python module called pynetinfo. This module could make possible working with different network device settings.

     I rearranged the code around pynetinfo and produced this:

def get_inet_ips():
  try:
    import netinfo
  except ImportError:
    return None
  else:
    inetIPs = []
    for interface in netinfo.list_active_devs():
      if not interface.startswith('lo'):
        ip = netinfo.get_ip(interface)
        inetIPs.append(ip)
    return inetIPs

     The code above loops through all available and active interfaces on the system, fetching and storing their IP in a simple datastructure. That got me all of the IPs available to a machine, excluding the loopback one, which the code was set to discard.

     But that wasn’t it. There was a slight problem. Not all the active interfaces on the system had public IPs. Some had private, local LAN IPs in the 192.168.0.0/16 and 10.0.0.0/8 subnets. The code above was returning all the IPs it could find, including public and private ones.

     I then found the netaddr third-party Python module which provided a Pythonic means of manipulating network addresses. I modified my code to use the netaddr module and got the following to boot with:

def get_inet_ips():
  try:
    import netinfo
    from netaddr import IPAddress, AddrFormatError
  except ImportError:
    return None
  else:
    inetIPs = []
    for interface in netinfo.list_active_devs():
      if not interface.startswith('lo'):
        ip = netinfo.get_ip(interface)
        try:
          ip_address = IPAddress(ip)
        except AddrFormatError:
          continue
        else:
          # If the IP is not private, use it.
          if not ip_address.is_private():
            inetIPs.append(ip)
    return inetIPs

     The netaddr.IPAddress.is_private() method in the code above determines whether the given IP is part of any of the defined private networks.

     Admittedly, there is much room for improvement in the code above. I can only hope that if it doesn’t help, then at the very least it serves as an interesting read.

One thought on “Get all public interface IPs on a system using Python

  1. Pingback: Get all public interface IPs on a system using Python | Tea Break

Leave a comment