2009-03-27 21 views

Respuesta

30

Eche un vistazo al módulo IPy. Si tiene una función iptype() que parece hacer lo que quiere:

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

Como se esperaba para una IP pública, la cadena es 'PUBLIC'. Hay algunos resultados inesperados: 'print (IP ('127.0.0.1'). Iptype())' produce 'PRIVATE'. 'print (IP (':: 1'). iptype())' produce 'LOOPBACK'. 'print (IP ('2001: 0658: 022a: café: 0200 :: 1'). iptype())' produce 'RLOQUEO ASIGNADO NCC' –

+0

¡Esto es perfecto! – Ryan

+0

De hecho, hay algunos resultados inesperados: 'print (IP ('0.0.0.0/0'). Iptype()) produce 'PRIVATE', mientras que yo esperaría que" todo el Internet IPv4 "sea PÚBLICO ... – Niobos

2

Si desea evitar la importación de un módulo sólo se puede aplicar una expresión regular simple:.

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

No deberían esos. los caracteres escapan vía \. ? Supongo que el patrón seguirá funcionando de cualquier manera. –

+1

Esa expresión regular no funcionó para mí, pero si sustituyes {123} por {1,3} funciona bien. – Tk421

2

Unos días después de hacer esta pregunta, me enteré de este proyecto de Google, ipaddr-py, que parece tener algunas de las mismas funcionalidades con respecto a determinar si una dirección es privada (is_rfc1918). Aparentemente esto será estándar en Python 3.1.

+0

Ahora es provisional en 3.3, vea el módulo [ipaddress] [1]. [1]: http://docs.python.org/3.3/library/ipaddress.html –

+0

Consulte la propiedad "is_private". –

20

Puede verificarlo usted mismo usando http://tools.ietf.org/html/rfc1918 y http://tools.ietf.org/html/rfc3330. Si tiene 127.0.0.1 solo necesita & con la máscara (digamos 255.0.0.0) y vea si el valor coincide con cualquiera de los network address de la red privada. Así, utilizando inet_pton que puede hacer: 127.0.0.1 & 255.0.0.0 = 127.0.0.0

Aquí está el código que ilustra que:

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 

otra implementación consiste en calcular los valores int de todos los bloques privados:

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" 
4

Este es el versión fija del enfoque de expresiones regulares sugerida por @Kurt, incluida la solución recomendada por @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 
    
+0

+1, sugiero que se devuelva un "contenedor" booleano, para reflejar mejor el nombre de la función: return (priv_lo.match (ip) o priv_24.match (ip) o priv_20.match (ip) o priv_16.match (ip)) no es Ninguno – mork

21

Como Python 3.3 hay un ipaddress module en el stdlib que puedes usar

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

Si usando Python 2.6 o superior no te recomiendo utilizar a backport of this module.

1

Encuentro esto en cuckoo. No es necesario instalar nuevos módulos. Solo importe dos módulos incorporados: socket y struct. Y usa la función a continuación.

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 
Cuestiones relacionadas