Python: Módulo: Netaddr

pip install netaddr
In [1]: from netaddr import *

In [2]: ip = IPNetwork('192.168.2.123/24')

In [3]: ip.network
Out[3]: IPAddress('192.168.2.0')

In [4]: ip.broadcast
Out[4]: IPAddress('192.168.2.255')

In [5]: ip.netmask
Out[5]: IPAddress('255.255.255.0')

In [6]: ip.hostmask
Out[6]: IPAddress('0.0.0.255')

In [7]: ip.ip
Out[7]: IPAddress('192.168.2.123')

In [8]: ip.version
Out[8]: 4

In [9]: ip.info
Out[9]:
{'IPv4': [{'date': '1993-05',
 'designation': 'Administered by ARIN',
 'prefix': '192/8',
 'status': 'Legacy',
 'whois': 'whois.arin.net'}]}

In [10]: ip.prefixlen
Out[10]: 24

In [11]: ip.size
Out[11]: 256

netaddr nos permite convertir las direcciones MAC a diferentes formatos y obtener información del fabricante de la MAC.

In [1]: from netaddr import *

In [2]: mac = EUI('e8:ea:6a:00:03:15')

In [3]: mac
Out[3]: EUI('E8-EA-6A-00-03-15')

In [4]: str(mac)
Out[4]: 'E8-EA-6A-00-03-15'

In [5]: str(mac.oui)
Out[5]: 'E8-EA-6A'

In [6]: str(mac.ei)
Out[6]: '00-03-15'

In [7]: str(mac.version)
Out[7]: '48'

In [8]: mac.dialect = mac_unix

In [9]: mac
Out[9]: EUI('e8:ea:6a:0:3:15')

In [10]: mac.dialect = mac_unix_expanded

In [11]: mac
Out[11]: EUI('e8:ea:6a:00:03:15')

In [12]: mac.dialect = mac_cisco

In [13]: mac
Out[13]: EUI('e8ea.6a00.0315')

In [14]: mac.dialect = mac_bare

In [15]: mac
Out[15]: EUI('E8EA6A000315')

In [16]: mac.oui.registration().org
Out[16]: 'StarTech.com'

Generar una lista con las IPs de un prefijo:

In [1]: from netaddr import *

In [2]: ip = IPNetwork('192.168.2.32/29')

In [3]: ips = list(ip)

In [4]: ips
Out[4]:
[IPAddress('192.168.2.32'),
 IPAddress('192.168.2.33'),
 IPAddress('192.168.2.34'),
 IPAddress('192.168.2.35'),
 IPAddress('192.168.2.36'),
 IPAddress('192.168.2.37'),
 IPAddress('192.168.2.38'),
 IPAddress('192.168.2.39')]

Acceso a las IPs mediante un indice

n [1]: from netaddr import *

In [2]: ip = IPNetwork('192.168.2.32/29')

In [3]: ip[3]
Out[3]: IPAddress('192.168.2.35')

In [4]: ip[7]
Out[4]: IPAddress('192.168.2.39')

Acceso a sub rango de IPs, como por ejemplo las IPs usables (omitiendo la primera = network y la última = broadcast)

In [1]: from netaddr import *

In [2]: ip = IPNetwork('192.168.2.32/29')

In [3]: list(ip[1:6])
Out[3]:
[IPAddress('192.168.2.33'),
 IPAddress('192.168.2.34'),
 IPAddress('192.168.2.35'),
 IPAddress('192.168.2.36'),
 IPAddress('192.168.2.37')]

Acceso a las IPs pares o listado inverso

In [1]: from netaddr import *

In [2]: ip = IPNetwork('192.168.2.32/29')

In [3]: list(ip[0::2])
Out[3]:
[IPAddress('192.168.2.32'),
 IPAddress('192.168.2.34'),
 IPAddress('192.168.2.36'),
 IPAddress('192.168.2.38')]

In [4]: list(ip[-1::-1])
Out[4]:
[IPAddress('192.168.2.39'),
 IPAddress('192.168.2.38'),
 IPAddress('192.168.2.37'),
 IPAddress('192.168.2.36'),
 IPAddress('192.168.2.35'),
 IPAddress('192.168.2.34'),
 IPAddress('192.168.2.33'),
 IPAddress('192.168.2.32')]

Ordenando IPs y redes

In [1]: from netaddr import *

In [2]: ip_list = [
   ...: IPAddress('192.0.2.130'),
   ...: IPAddress('10.0.0.1'),
   ...: IPNetwork('192.0.2.128/28'),
   ...: IPNetwork('192.0.3.0/24'),
   ...: IPNetwork('192.0.2.0/24'),
   ...: IPNetwork('fe80::/64'),
   ...: IPAddress('::'),
   ...: IPNetwork('172.24/12')]

In [3]: ip_list
Out[3]:
[IPAddress('192.0.2.130'),
 IPAddress('10.0.0.1'),
 IPNetwork('192.0.2.128/28'),
 IPNetwork('192.0.3.0/24'),
 IPNetwork('192.0.2.0/24'),
 IPNetwork('fe80::/64'),
 IPAddress('::'),
 IPNetwork('172.24.0.0/12')]

In [4]: ip_list.sort()

In [5]: ip_list
Out[5]:
[IPAddress('10.0.0.1'),
 IPNetwork('172.24.0.0/12'),
 IPNetwork('192.0.2.0/24'),
 IPNetwork('192.0.2.128/28'),
 IPAddress('192.0.2.130'),
 IPNetwork('192.0.3.0/24'),
 IPAddress('::'),
 IPNetwork('fe80::/64')]

Sumarizar IPs y Rangos

In [1]: from netaddr import *

In [2]: ip_list = [ip for ip in IPNetwork('fe30::/120')]

In [3]: ip_list.append(IPNetwork('192.168.2.0/24'))

In [4]: ip_list.append(IPNetwork('192.168.3.0/24'))

In [6]: ip_list.append(IPNetwork('10.1.1.0/25'))

In [7]: ip_list.append(IPNetwork('10.1.1.128/25'))

In [8]: len(ip_list)
Out[8]: 260

In [9]: ip_list
Out[9]:
[IPAddress('fe30::'),
 IPAddress('fe30::1'),
 IPAddress('fe30::2'),
 - - - OMITIDO - - -
 IPAddress('fe30::fe'),
 IPAddress('fe30::ff'),
 IPNetwork('192.168.2.0/24'),
 IPNetwork('192.168.3.0/24'),
 IPNetwork('10.1.1.0/25'),
 IPNetwork('10.1.1.128/25')]

In [10]: cidr_merge(ip_list)
Out[10]:
[IPNetwork('10.1.1.0/24'),
 IPNetwork('192.168.2.0/23'),
 IPNetwork('fe30::/120')]

Cálculos de supernet y subnets

In [1]: from netaddr import *

In [2]: ip = IPNetwork('192.168.0.0/16')

In [3]: subnets = list(ip.subnet(23))

In [4]: len(subnets)
Out[4]: 128

In [5]: subnets
Out[5]:
[IPNetwork('192.168.0.0/23'),
 IPNetwork('192.168.2.0/23'),
 - - - OMITIDO - - -
 IPNetwork('192.168.252.0/23')]
 IPNetwork('192.168.254.0/23')]

In [6]: subnets = list(ip.subnet(24))

In [7]: subnets
Out[7]:
[IPNetwork('192.168.0.0/24'),
 - - - OMITIDO - - -
 IPNetwork('192.168.255.0/24')]

In [8]: len(subnets)
Out[8]: 256

In [9]: subnets = list(ip.subnet(22))

In [10]: len(subnets)
Out[10]: 64
In [1]: from netaddr import *

In [2]: ip = IPNetwork('10.1.1.114')

In [3]: supernets = ip.supernet(22)

In [4]: supernets
Out[4]:
[IPNetwork('10.1.0.0/22'),
 IPNetwork('10.1.0.0/23'),
 IPNetwork('10.1.1.0/24'),
 IPNetwork('10.1.1.0/25'),
 IPNetwork('10.1.1.64/26'),
 IPNetwork('10.1.1.96/27'),
 IPNetwork('10.1.1.112/28'),
 IPNetwork('10.1.1.112/29'),
 IPNetwork('10.1.1.112/30'),
 IPNetwork('10.1.1.114/31')]

Comprobar tipo de IP

In [1]: from netaddr import *

In [2]: IPAddress('192.168.2.1').is_unicast()
Out[2]: True

In [3]: IPAddress('fe80::1').is_unicast()
Out[3]: True

In [4]: IPAddress('239.192.0.1').is_multicast()
Out[4]: True

In [5]: IPAddress('ff00::1').is_multicast()
Out[5]: True

In [6]: IPAddress('172.24.0.1').is_private()
Out[6]: True

In [7]: IPAddress('10.0.0.1').is_private()
Out[7]: True

In [8]: IPAddress('fc00::1').is_private()
Out[8]: True

In [9]: IPAddress('253.0.0.1').is_reserved()
Out[9]: True

In [10]: IPAddress('255.255.254.0').is_netmask()
Out[10]: True

In [11]: IPAddress('0.0.1.255').is_hostmask()
Out[11]: True

In [12]:  IPAddress('127.0.0.1').is_loopback()
Out[12]: True

In [13]:  IPAddress('::1').is_loopback()
Out[13]: True

Comparaciones entre IPs

In [1]: from netaddr import *

In [2]: IPAddress('192.168.2.1') == IPAddress('192.168.2.1')
Out[2]: True

In [3]: IPAddress('192.168.2.1') < IPAddress('192.168.2.2')
Out[3]: True

In [4]: IPAddress('192.168.2.1') > IPAddress('192.168.2.2')
Out[4]: False

In [5]: IPAddress('192.168.2.1') != IPAddress('192.168.2.1')
Out[5]: False

In [6]: IPAddress('192.168.2.1') >= IPAddress('192.168.2.1')
Out[6]: True

In [7]: IPAddress('192.168.2.1') <= IPAddress('192.168.2.1')
Out[7]: True

In [8]: IPAddress('192.168.2.1') >= IPAddress('192.168.2.2')
Out[8]: False

In [9]: IPAddress('192.168.2.1') <= IPAddress('192.168.2.2')
Out[9]: True

In [10]: IPNetwork('192.168.2.0/24').cidr == IPNetwork('192.168.2.134/24').cidr
Out[10]: True

In [11]: IPNetwork('192.168.2.0/24') == IPNetwork('192.168.2.134/24')
Out[11]: True

In [12]: IPNetwork('192.168.2.0/24').ip == IPNetwork('192.168.2.134/24').ip
Out[12]: False

Comprobar si una red/ip está contenido dentro de una red.

from netaddr import *

ip1 = IPNetwork('192.168.2.64/27')

ip2 = IPNetwork('192.168.2.0/24')

ip3 = IPNetwork('192.168.0.0/22')

ip1 in ip2
True

ip1 in ip3
True

ip2 in ip1
False

ip2 in ip3
True
In [1]: from netaddr import *

In [2]: IPAddress('8.8.8.8').reverse_dns
Out[2]: '8.8.8.8.in-addr.arpa.'

In [3]: IPAddress('fe80::feeb:daed').reverse_dns
Out[3]: 'd.e.a.d.b.e.e.f.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.e.f.ip6.arpa.'

In [4]: IPAddress('192.168.3.65').reverse_dns
Out[4]: '65.3.168.192.in-addr.arpa.'

Más información netaddr

Retro

Lugares

Redes

Sistemas

Varios