Примеры использования ipaddress для администрирования сетей
Работа с IP-адресами и сетями в Python: модуль ipaddress
Модуль ipaddress стандартной библиотеки Python предоставляет удобные инструменты для создания, проверки и манипуляции IP-адресами и подсетями. Он поддерживает обе версии протокола - IPv4 и IPv6. В статье рассматриваются основные классы, типовые задачи и примеры кода.
Основные классы и создание объектов
Модуль включает классы IPv4Address, IPv6Address, IPv4Network, IPv6Network, IPv4Interface, IPv6Interface. Для создания объекта достаточно передать строку с адресом или сетью:
import ipaddress
addr = ipaddress.IPv4Address('192.168.1.10')
net = ipaddress.IPv4Network('192.168.1.0/24', strict=False)
print(addr, net)
# 192.168.1.10 192.168.1.0/24Python client py (клиент на python)
Если указать strict=True (по умолчанию), то сеть должна быть задана точным сетевым адресом (биты хоста равны нулю). При strict=False допускается любой адрес, ipaddress автоматически отбросит хостовую часть.
Как проверить, принадлежит ли IP-адрес сети?
Оператор in работает с объектами IPv4Network/IPv6Network:
net = ipaddress.IPv4Network('10.0.0.0/8')
addr = ipaddress.IPv4Address('10.1.2.3')
print(addr in net) # TruePython socket (сокеты в python (socket))
Также доступны методы subnet_of и supernet_of для сравнения сетей:
net1 = ipaddress.IPv4Network('192.168.1.0/24')
net2 = ipaddress.IPv4Network('192.168.1.0/26')
print(net2.subnet_of(net1)) # True
print(net1.supernet_of(net2)) # True
Python ipaddress ip network (модуль ipaddress в python)
Типичная ошибка:
При использовании in с IPv6 и IPv4 может возникнуть TypeError из-за несовместимости протоколов. Всегда проверяйте версию адреса.
Как получить все IP-адреса из сети?
Метод hosts() возвращает генератор всех используемых адресов (исключая сетевой и широковещательный):
net = ipaddress.IPv4Network('192.168.0.0/29', strict=False)
for host in net.hosts():
print(host)
# 192.168.0.1
# 192.168.0.2
# ...
# 192.168.0.6Python сети (сетевые возможности python)
Чтобы включить все адреса, используйте iter(net) или list(net).
Как разбить сеть на подсети заданного префикса?
Метод subnets() возвращает генератор подсетей:
net = ipaddress.IPv4Network('10.0.0.0/24')
for subnet in net.subnets(new_prefix=26):
print(subnet)
# 10.0.0.0/26
# 10.0.0.64/26
# 10.0.0.128/26
# 10.0.0.192/26Python network programming (сетевое программирование на python)
Ошибка:
Если новый префикс меньше текущего (например, /30 на /24), возникнет ValueError. Допустимо только увеличение префикса (разбиение на более мелкие подсети).
Как получить сетевой и широковещательный адреса, маску?
У объекта сети есть атрибуты:
net = ipaddress.IPv4Network('192.168.1.128/25')
print(f"Network: {net.network_address}") # 192.168.1.128
print(f"Broadcast: {net.broadcast_address}") # 192.168.1.255
print(f"Netmask: {net.netmask}") # 255.255.255.128
print(f"Prefixlen: {net.prefixlen}") # 25Ip network python (работа с ip-сетями в python)
Как работать с IPv6 адресами?
Классы для IPv6 работают аналогично:
v6net = ipaddress.IPv6Network('2001:db8::/32')
v6addr = ipaddress.IPv6Address('2001:db8::1')
print(v6addr in v6net) # True
print(v6net.exploded) # '2001:0db8:0000:0000:0000:0000:0000:0000'
print(v6net.compressed) # '2001:db8::'
Как преобразовать объект обратно в строку или число?
Для адреса доступны атрибуты packed (бинарное представление) и exploded/compressed для IPv6:
addr = ipaddress.IPv4Address('10.0.0.1')
print(int(addr)) # 167772161
print(bytes(addr)) # b'\n\x00\x00\x01'
net = ipaddress.IPv4Network('10.0.0.0/24')
print(str(net)) # '10.0.0.0/24'
Частая проблема: при ручном вводе адресов может возникнуть ValueError: 'xxx' does not appear to be an IPv4 or IPv6 network. Решение - проверять формат. Также при использовании strict=False некоторые адреса с ненулевой хостовой частью будут приняты, но может потеряться информация.
Расширенные примеры использования модуля ipaddress
1. Вычисление общей сети (supernet) для списка подсетей
Функция collapse_addresses находит минимальный набор подсетей, покрывающий все заданные:
import ipaddress
def find_supernet(subnets_str):
networks = [ipaddress.IPv4Network(s, strict=False) for s in subnets_str]
collapsed = list(ipaddress.collapse_addresses(networks))
return collapsed
subs = ['10.0.0.0/25', '10.0.0.128/25']
result = find_supernet(subs)
print([str(n) for n in result])
# ['10.0.0.0/24']
['10.0.0.0/24']
2. Проверка пересечения (overlap) двух сетей
Метод overlaps возвращает True, если сети имеют общие адреса:
net1 = ipaddress.IPv4Network('192.168.1.0/24')
net2 = ipaddress.IPv4Network('192.168.1.128/25')
print(net1.overlaps(net2)) # True
net3 = ipaddress.IPv4Network('10.0.0.0/8')
print(net1.overlaps(net3)) # False
True False
3. Использование интерфейсов (IPv4Interface)
Класс IPv4Interface объединяет адрес и сеть. Позволяет получить маску, broadcast и т.д.:
iface = ipaddress.IPv4Interface('192.168.1.10/24')
print(f"IP: {iface.ip}") # 192.168.1.10
print(f"Net: {iface.network}") # 192.168.1.0/24
print(f"Broadcast: {iface.network.broadcast_address}")
# 192.168.1.255
# Извлечение адреса и сети отдельно
addr = iface.ip
net = iface.network
print(addr in net) # True
IP: 192.168.1.10 Net: 192.168.1.0/24 Broadcast: 192.168.1.255 True
4. Работа с частными (private) и публичными адресами
Методы is_private, is_global, is_loopback и др.:
addr_priv = ipaddress.IPv4Address('10.0.0.5')
addr_pub = ipaddress.IPv4Address('8.8.8.8')
print(f"Private: {addr_priv.is_private}, Global: {addr_priv.is_global}")
print(f"Private: {addr_pub.is_private}, Global: {addr_pub.is_global}")
# Для сетей
net_priv = ipaddress.IPv4Network('172.16.0.0/12')
print(net_priv.is_private) # True
Private: True, Global: False Private: False, Global: True True
5. Создание диапазона адресов и связка с другими модулями
Использование summarize_address_range для получения списка подсетей, покрывающих диапазон:
start = ipaddress.IPv4Address('192.168.0.0')
end = ipaddress.IPv4Address('192.168.0.255')
networks = list(ipaddress.summarize_address_range(start, end))
print([str(n) for n in networks])
# ['192.168.0.0/24']
['192.168.0.0/24']
Модуль часто применяется с socket для разрешения имён хостов:
import socket
import ipaddress
def resolve_to_network(hostname):
try:
ip_str = socket.gethostbyname(hostname)
ip = ipaddress.IPv4Address(ip_str)
return ip
except (socket.gaierror, ValueError):
return None
print(resolve_to_network('google.com'))
# Примерный вывод: 142.250.185.78
142.250.185.78
6. Проверка корректности маски и префикса
Маска может быть задана как в десятичном виде, так и через длину префикса:
# Автоматическое определение по адресу и маске
net = ipaddress.IPv4Network('192.168.1.0/255.255.255.0')
print(net) # 192.168.1.0/24
# Проверка маски - только степени двойки
mask_str = '255.255.255.0'
try:
ipaddress.IPv4Network(f'0.0.0.0/{mask_str}')
print('Valida mask')
except ValueError as e:
print(f'Invalid mask: {e}')
192.168.1.0/24 Valida mask
7. Преобразование между IPv4 и IPv6 (если применимо)
IPv4-совместимые IPv6 адреса:
v4 = ipaddress.IPv4Address('192.0.2.1')
v6_mapped = v4.ipv4_mapped # IPv4-mapped IPv6
print(v6_mapped) # ::ffff:192.0.2.1
v6 = ipaddress.IPv6Address('::ffff:192.0.2.1')
print(v6.ipv4_mapped) # 192.0.2.1
::ffff:192.0.2.1 192.0.2.1