30

Python で、IP アドレス ('127.0.0.1'または など'10.98.76.6') がプライベート ネットワーク上にあるかどうかを判断する最良の方法は何ですか? コードを書くのは難しくないようです。しかし、すぐにわかるよりも多くのエッジケースが存在する可能性があり、考慮すべき IPv6 サポートなどがあります。それを行う既存のライブラリはありますか?

4

7 に答える 7

78

Python 3.3 以降、使用できる stdlib にipaddress モジュールがあります。

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

Python 2.6 以降を使用している場合は、このモジュールのバックポートを使用することを強くお勧めします。

于 2015-06-24T20:30:24.950 に答える
41

IPyモジュールを調べてください。iptype()あなたが望むことをするように見える機能がある場合:

>>> from IPy import IP
>>> ip = IP('127.0.0.0/30')
>>> ip.iptype()
'PRIVATE'
于 2009-03-27T18:55:23.263 に答える
25

https://www.rfc-editor.org/rfc/rfc1918およびhttps://www.rfc-editor.org/rfc/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   https://www.rfc-editor.org/rfc/rfc3330
        [ 3232235520, 4294901760 ], # 192.168.0.0, 255.255.0.0 https://www.rfc-editor.org/rfc/rfc1918
        [ 2886729728, 4293918720 ], # 172.16.0.0,  255.240.0.0 https://www.rfc-editor.org/rfc/rfc1918
        [ 167772160,  4278190080 ], # 10.0.0.0,    255.0.0.0   https://www.rfc-editor.org/rfc/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"
于 2011-12-01T10:36:41.797 に答える
2

この質問をしてから数日後、この Google プロジェクトipaddr-pyについて知りました。これは、アドレスが非公開かどうかの判断に関して、同じ機能をいくつか持っているようです ( is_rfc1918)。どうやらこれは Python 3.1 で標準になるようです。

于 2009-04-03T07:23:27.437 に答える
2

cuckooでこれを見つけました。新しいモジュールをインストールする必要はありません。2 つの組み込みモジュール、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
于 2016-09-23T08:53:01.410 に答える
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}$
于 2009-03-28T08:33:51.800 に答える