Работа с IP сетями средствами Python: от основ до продвинутых техник
Основы работы с IP сетями в Python
Работа с IP сетями в Python часто выполняется с помощью встроенного модуля ipaddress. Он предоставляет классы для представления IP адресов, сетей и интерфейсов, поддерживает IPv4 и IPv6, а также операции проверки вхождения, разбиения на подсети, объединения сетей и другие. Ниже рассмотрены различные подходы, от стандартного до альтернативных.
Использование модуля ipaddress (основной способ)
Модуль ipaddress входит в стандартную библиотеку Python (начиная с версии 3.3) и считается наиболее эффективным и безопасным решением.
import ipaddress
# создание сети
net = ipaddress.ip_network('192.168.1.0/24', strict=False)
print(net) # 192.168.1.0/24
# проверка принадлежности адреса
ip = ipaddress.ip_address('192.168.1.10')
print(ip in net) # True
# список всех адресов
for addr in net.hosts():
print(addr)
break # первый адресPython client py (клиент на python)
192.168.1.0/24 True 192.168.1.1
Python socket (сокеты в python (socket))
Типичная ошибка: при strict=True модуль проверяет, что адрес сети является сетевым адресом (нулевой хост). Для произвольных сетей следует указывать strict=False, иначе возникнет ValueError.
ipaddress.ip_network('192.168.1.10/24', strict=True) # ValueError
Python ipaddress ip network (модуль ipaddress в python)
Как проверить вхождение IP в подсеть без сторонних библиотек?
Вариант с использованием модуля socket и битовых масок. Полезно для понимания низкоуровневых операций.
import socket, struct
def ip_in_network(ip_str, net_str):
ip = struct.unpack('!I', socket.inet_aton(ip_str))[0]
net_addr, bits = net_str.split('/')
net = struct.unpack('!I', socket.inet_aton(net_addr))[0]
mask = (0xFFFFFFFF << (32 - int(bits))) & 0xFFFFFFFF
return (ip & mask) == (net & mask)
print(ip_in_network('192.168.1.10', '192.168.1.0/24')) # TruePython сети (сетевые возможности python)
True
Python network programming (сетевое программирование на python)
Проблемы: работает только с IPv4; требуется ручное преобразование; ошибка при неверном формате маски (ValueError в inet_aton). Не рекомендуется для сложных сетей.
Как работать с диапазонами и сортировкой IP адресов?
Использование библиотеки netaddr (устанавливается отдельно). Она предоставляет расширенные функции для работы с IP адресами, например, получение диапазона, сортировка, объединение смежных сетей.
from netaddr import IPNetwork, IPAddress
net = IPNetwork('10.0.0.0/24')
print(net.size) # 256
# конвертация в диапазон
print(net.first, net.last) # 167772160 167772415
# сортировка списка адресов
iplist = ['10.0.0.5', '10.0.0.2', '10.0.0.100']
sorted_ips = sorted(iplist, key=lambda x: IPAddress(x))
print(sorted_ips)Ip network python (работа с ip-сетями в python)
256 167772160 167772415 ['10.0.0.2', '10.0.0.5', '10.0.0.100']
Библиотека не входит в стандартную поставку, требует pip install netaddr. При работе с большими подсетями (IPv6) может потреблять много памяти.
Расширенные примеры работы с IP сетями
Приведены нестандартные сценарии, которые могут потребоваться при разработке средств мониторинга, VLAN конфигурации или анализа трафика.
1. Разбиение сети на подсети с заданным размером
import ipaddress
net = ipaddress.ip_network('10.0.0.0/24')
# разбить на 4 подсети по 64 адреса
subnets = list(net.subnets(new_prefix=26))
for sub in subnets:
print(sub)
10.0.0.0/26 10.0.0.64/26 10.0.0.128/26 10.0.0.192/26
2. Поиск общих вышестоящих подсетей (supernet)
net1 = ipaddress.ip_network('192.168.1.0/25')
net2 = ipaddress.ip_network('192.168.1.128/25')
# объединение смежных сетей
if net1.overlaps(net2):
supernet = net1.supernet(new_prefix=24)
print(supernet) # 192.168.1.0/24
192.168.1.0/24
3. Генерация случайного IP адреса внутри сети
import ipaddress, random
net = ipaddress.ip_network('10.0.0.0/28')
addr_list = list(net.hosts()) # исключаем broadcast и network
random_ip = random.choice(addr_list)
print(random_ip) # например 10.0.0.5
10.0.0.5
4. Проверка пересечения двух IPv6 сетей
net1 = ipaddress.ip_network('2001:db8::/32')
net2 = ipaddress.ip_network('2001:db8:1000::/36')
print(net1.overlaps(net2)) # True, т.к. 2001:db8:1000:: входит в 2001:db8::/32
True
5. Конвертация IP адреса в двоичный вид и обратно
import ipaddress
def ip_to_bin(ip_str):
ip = ipaddress.ip_address(ip_str)
return bin(int(ip))
bin_form = ip_to_bin('192.168.1.1')
print(bin_form)
# восстановление
dec_form = int(bin_form, 2)
print(ipaddress.ip_address(dec_form))
0b11000000101010000000000100000001 192.168.1.1