add a function to get local interfaces or external interface only

Issue #51 closed
stephaneYaal
created an issue

Hello,

are you interested by something like:

>>> netifaces.local_interfaces()
['lo0', 'en0']
>>> netifaces.public_interfaces()
['gif0', 'stf0', 'en1', 'fw0']

My usecase is that I need to find local interfaces on several OSes to display them to the user. So I get all of them with netifaces.interfaces(), then making a loop for selecting local adresses with this function:

def _is_local_address(addr):
    return addr.startswith("192.168") or \
            (addr.startswith("172.") and 16 <= int(addr.split(".")[1]) <= 31) or \
            addr.startswith("10.")

I think a generic interface in netifaces could help other people. I can make a pull-request of the feature if you are interested.

Comments (6)

  1. opalmer

    Seems useful but would be more involved than the above to implement (netifaces is written in C) and I'm not sure it belongs here either because it's hard to determine what's an external interface just on the IP address alone. By the way, you should really use CIDR blocks instead of checking what it starts with to determine if an interface is in a private address range and is also not a special use case:

    https://github.com/pyfarm/pyfarm-agent/blob/master/pyfarm/agent/sysinfo/network.py#L171

    https://github.com/pyfarm/pyfarm-agent/blob/master/pyfarm/agent/sysinfo/network.py#L44

    The other problem is "local interfaces" and "external interfaces" is a bit misleading in my opinion. In order to determine if an interface is actually external or not you have to use it to make a request to a non-local address. If it works, it's an "external interface" because it can communicate externally. The other kind of "external interface" is one that can receive traffic from the outside world. In most cases traffic will be routed to the interface by the network so you could easily have something in the 192.168.0.0/16 range receiving traffic from the WAN. You could also have special cases where what appears to be a private interface is actually getting traffic from another private interface which in turn is getting traffic from the public WAN.

    So basically, "external" can mean a lot of things so you're often better off trying to class an IP as local host only, private address or special use if you're trying to implement a public API.

  2. stephaneYaal reporter

    You're right, public_interfaces() is not clear and can be forgotten. local_interfaces() should be named private_interfaces().

    Pyfarm example uses netaddr library and adding local_interfaces() could be easily done by depending from netaddr. However, I'm not sure it is interesting to add it as dependancy for netifaces.

    It could be implemented more simply than pyfarm does with:

    ip = netaddr.IPAddress(addr)
    ip.is_private()
    

    ... so CIDR is hidden in netaddr library.

    Still not sure if private_interfaces() should be added to netifaces. Do you think it's useful to continue or we can close this request?

  3. opalmer

    I'd close this request. I think netaddr already solves this problem and using netaddr directly prevents the need to write an equivalent function in C and/or having to add the packages as dependency of netifaces.

  4. Log in to comment