How do you determine if an IP address is private, in Python?

前端 未结 7 1206
Happy的楠姐
Happy的楠姐 2020-12-02 18:48

In Python, what is the best way to determine if an IP address (e.g., \'127.0.0.1\' or \'10.98.76.6\') is on a private network? The code does not s

相关标签:
7条回答
  • 2020-12-02 19:16

    You can check that yourself using http://tools.ietf.org/html/rfc1918 and http://tools.ietf.org/html/rfc3330. If you have 127.0.0.1 you just need to & it with the mask (lets say 255.0.0.0) and see if the value matches any of the private network's network address. So using inet_pton you can do: 127.0.0.1 & 255.0.0.0 = 127.0.0.0

    Here is the code that illustrates that:

    from struct import unpack
    from socket import AF_INET, inet_pton
    
    def lookup(ip):
        f = unpack('!I',inet_pton(AF_INET,ip))[0]
        private = (
            [ 2130706432, 4278190080 ], # 127.0.0.0,   255.0.0.0   http://tools.ietf.org/html/rfc3330
            [ 3232235520, 4294901760 ], # 192.168.0.0, 255.255.0.0 http://tools.ietf.org/html/rfc1918
            [ 2886729728, 4293918720 ], # 172.16.0.0,  255.240.0.0 http://tools.ietf.org/html/rfc1918
            [ 167772160,  4278190080 ], # 10.0.0.0,    255.0.0.0   http://tools.ietf.org/html/rfc1918
        ) 
        for net in private:
            if (f & net[1]) == net[0]:
                return True
        return False
    
    # example
    print(lookup("127.0.0.1"))
    print(lookup("192.168.10.1"))
    print(lookup("10.10.10.10"))
    print(lookup("172.17.255.255"))
    # outputs True True True True
    

    another implementation is to compute the int values of all private blocks:

    from struct import unpack
    from socket import AF_INET, inet_pton
    
    lookup = "127.0.0.1"
    f = unpack('!I',inet_pton(AF_INET,lookup))[0]
    private = (["127.0.0.0","255.0.0.0"],["192.168.0.0","255.255.0.0"],["172.16.0.0","255.240.0.0"],["10.0.0.0","255.0.0.0"])
    for net in private:
        mask = unpack('!I',inet_aton(net[1]))[0]
        p = unpack('!I',inet_aton(net[0]))[0]
        if (f & mask) == p:
            print lookup + " is private"
    
    0 讨论(0)
  • 2020-12-02 19:16

    If you want to avoid importing a module you can just apply a simple regex:

    • ^127.\d{1,3}.\d{1,3}.\d{1,3}$
    • ^10.\d{1,3}.\d{1,3}.\d{1,3}$
    • ^192.168.\d{1,3}$
    • ^172.(1[6-9]|2[0-9]|3[0-1]).[0-9]{1,3}.[0-9]{1,3}$
    0 讨论(0)
  • 2020-12-02 19:17

    Check out the IPy module. If has a function iptype() that seems to do what you want:

    >>> from IPy import IP
    >>> ip = IP('127.0.0.0/30')
    >>> ip.iptype()
    'PRIVATE'
    
    0 讨论(0)
  • 2020-12-02 19:18

    I find this in cuckoo.There is no need to install new modules.Just import two built-in modules: socket and struct. And use function below.

    def _is_private_ip(self, ip):
        """Check if the IP belongs to private network blocks.
        @param ip: IP address to verify.
        @return: boolean representing whether the IP belongs or not to
                 a private network block.
        """
        networks = [
            "0.0.0.0/8",
            "10.0.0.0/8",
            "100.64.0.0/10",
            "127.0.0.0/8",
            "169.254.0.0/16",
            "172.16.0.0/12",
            "192.0.0.0/24",
            "192.0.2.0/24",
            "192.88.99.0/24",
            "192.168.0.0/16",
            "198.18.0.0/15",
            "198.51.100.0/24",
            "203.0.113.0/24",
            "240.0.0.0/4",
            "255.255.255.255/32",
            "224.0.0.0/4",
        ]
    
        for network in networks:
            try:
                ipaddr = struct.unpack(">I", socket.inet_aton(ip))[0]
    
                netaddr, bits = network.split("/")
    
                network_low = struct.unpack(">I", socket.inet_aton(netaddr))[0]
                network_high = network_low | 1 << (32 - int(bits)) - 1
    
                if ipaddr <= network_high and ipaddr >= network_low:
                    return True
            except Exception,err:
                continue
    
        return False
    
    0 讨论(0)
  • 2020-12-02 19:21

    Since Python 3.3 there is an ipaddress module in the stdlib that you can use.

    >>> import ipaddress
    >>> ipaddress.ip_address('192.168.0.1').is_private
    True
    

    If using Python 2.6 or higher I would strongly recommend to use a backport of this module.

    0 讨论(0)
  • 2020-12-02 19:39

    A few days after asking this question, I found out about this Google project, ipaddr-py, which appears to have some of the same functionality with respect to determining if an address is private (is_rfc1918). Apparently this will be standard in Python 3.1.

    0 讨论(0)
提交回复
热议问题