簡體   English   中英

在 Python 中,您如何確定 IP 地址是否是私有的?

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

在 Python 中,確定 IP 地址(例如'127.0.0.1''10.98.76.6' )是否在專用網絡上的最佳方法是什么? 代碼聽起來並不難寫。 但是可能存在比立即顯而易見的更多邊緣情況,並且需要考慮 IPv6 支持等。是否有現有的庫可以做到這一點?

從 Python 3.3 開始,您可以使用 stdlib 中的ipaddress 模塊

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

如果使用 Python 2.6 或更高版本,我強烈建議使用此模塊的反向移植

查看IPy模塊。 如果有一個函數iptype()似乎可以執行您想要的操作:

>>> from IPy import IP
>>> ip = IP('127.0.0.0/30')
>>> ip.iptype()
'PRIVATE'

您可以使用http://tools.ietf.org/html/rfc1918http://tools.ietf.org/html/rfc3330 自行檢查。 如果你有 127.0.0.1 你只需要&它與掩碼(假設255.0.0.0 )並查看該值是否與任何專用網絡的網絡地址匹配。 所以使用inet_pton你可以做到: 127.0.0.1 & 255.0.0.0 = 127.0.0.0

這是說明這一點的代碼:

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

另一種實現是計算所有私有塊的 int 值:

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"

這是@Kurt 建議的正則表達式方法的固定版本,包括@RobEvans 建議的修復

  • ^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}.\\d{1,3}$

  • ^172.(1[6-9]|2[0-9]|3[0-1]).[0-9]{1,3}.[0-9]{1,3}$

     def is_ip_private(ip): # https://en.wikipedia.org/wiki/Private_network priv_lo = re.compile("^127\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$") priv_24 = re.compile("^10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$") priv_20 = re.compile("^192\\.168\\.\\d{1,3}.\\d{1,3}$") priv_16 = re.compile("^172.(1[6-9]|2[0-9]|3[0-1]).[0-9]{1,3}.[0-9]{1,3}$") res = priv_lo.match(ip) or priv_24.match(ip) or priv_20.match(ip) or priv_16.match(ip) return res is not None

這不會是 kubernetes 內部使用的 100.xxx 范圍

我在cuckoo 中找到了這個。不需要安裝新模塊。只需導入兩個內置模塊:socket 和 struct。 並使用下面的功能。

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

問這個問題幾天后,我發現了這個谷歌項目ipaddr-py ,它似乎具有一些相同的功能,用於確定地址是否是私有的( is_rfc1918 )。 顯然,這將是 Python 3.1 的標准。

如果你想避免導入一個模塊,你可以應用一個簡單的正則表達式:

  • ^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}$

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM