Порой при настройке и проектировании сетевой архитектуры системному администратору может понадобиться небольшая автоматизации расчета адресов и масок, в том числе для выделения подсетей из основной. В этом случае он может написать небольшую программу на языке Python. Сделать это несложно и даже не потребуется глубоких знаний в программировании. Для старта хватит знаний из бесплатной части курса по Python на Stepik.
Вам даже не придется лишнего устанавливать, хватит чистого Python. Он “из коробки“ содержит мощную встроенную библиотеку, которая включает много полезных модулей, в том числе и для работы с сетями. Нам в этой статье потребуется ipaddress.
Рассмотрим несколько практических приёмов работы с IP-адресами и сетями.
Проектируем офисную сеть
Представим, что заказчику требуется организовывать небольшую сеть на 254 адреса в офисе. Офис находится в двухэтажном здании и поэтому будем делать две подсети — каждая на 128 адресов.
Первым делом необходимо определить адрес основной сети и пусть это будет 192.168.13.0.
Так как мы запланировали 254 адреса, то необходимо выбрать маску 255.255.255.0 (или /24 в сокращённом виде). Соответственно саму сеть можно создать в Python-программе двумя способами:
# Импортируем библиотеку для работы с сетями
import ipaddress
# Создаем офисную сеть (выберите один из двух вариантов ниже)
office_net = ipaddress.ip_network('192.168.13.0/24')
office_net = ipaddress.ip_network('192.168.13.0/255.255.255.0')
Объект office_net для работы с офисной сетью создан. Давайте посмотрим, какую информацию можно из него вытянуть. Для этого обратимся к атрибутам объекта:
# Добавьте этот код сразу после того как создали office_net
print("Адрес сети (network): ", office_net.network_address)
print("Адрес сети с маской: ", office_net.with_hostmask)
print("Адрес сети с префиксом: ", office_net.with_prefixlen)
print("Префикс (Bitmask): ", office_net.prefixlen)
print("Широковещательный адрес (broadcast):", office_net.broadcast_address)
print("Маска сети (netmask): ", office_net.netmask)
print("Маска хоста (wildcard): ", office_net.hostmask)
print("Адресов (1): ", len(list(office_net.hosts())))
print("Адресов (2): ", office_net.num_addresses - 2)
# Пример вывода данных в двоичном виде
print("Адрес сети (network): ", f"{office_net.network_address:#b}")
print("Маска сети (netmask): ", f"{office_net.netmask:#b}")
После выполнения кода вы увидите следующую информацию:
Адрес сети (network): 192.168.13.0
Адрес сети с маской: 192.168.13.0/0.0.0.255
Адрес сети с префиксом: 192.168.13.0/24
Префикс (Bitmask): 24
Широковещательный адрес (broadcast): 192.168.13.255
Маска сети (netmask): 255.255.255.0
Маска хоста (wildcard): 0.0.0.255
Адресов (1): 254
Адресов (2): 254
Адрес сети (network): 0b11000000101010000000110100000000
Маска сети (netmask): 0b11111111111111111111111100000000
Теперь нам нужно разделить офисную сеть на две равные подсети и для этого можно воспользоваться методом subnets(), который принимает параметр prefixlen_diff. Если передать в него единицу, то метод выделит подсети, у которых битовая маска сети будет на один бит больше, чем у основной сети.
# Выделяем 2 подсети (/25):
# IPv4Network('192.168.13.0/25')
# IPv4Network('192.168.13.128/25')]
print("Подсети", list(office_net.subnets(prefixlen_diff=1)))
# Выделяем 4 подсети (/26):
# IPv4Network('192.168.13.0/26')
# IPv4Network('192.168.13.64/26')
# IPv4Network('192.168.13.128/26')
# IPv4Network('192.168.13.192/26')
print("Подсети", list(office_net.subnets(prefixlen_diff=2)))
Так как по тех. заданию нам требуется две подсети, то остановимся на первом варианте:
# Выделяем все подсети
subnests = list(office_net.subnets(prefixlen_diff=1))
# Получаем каждую подсеть по отдельности:
floor1_net = subnests[0]
floor2_net = subnests[1]
# Выводим общую информацию по подсетям:
print(floor1_net) # 192.168.13.0/25
print(floor2_net) # 192.168.13.128/25
Готово. Подсети для каждого из этажей получили. Теперь можно перепроверить какая сеть является основной, а какие “дочерними”. Для этого используются два зеркальных метода: supernet_of, subset_of.
Первый применяется к основной сети и принимает дочерную сеть, которую нужно проверить:
print("Офисная главная:", office_net.supernet_of(floor1_net))
Второй метод применятся к подсети и проверяет, является ли эта подсеть дочерней для какой-либо общей сети:
print("Подсеть офисной?:", floor1_net.subnet_of(office_net))
Оба варианта выведут True, так как floor1_net является подсетью для office_net.
Кстати, представим, что наша офисная сеть сама являются подсетью для сети 192.168.12.0/22, которая объединяет несколько зданий. Давайте проверим является ли сеть зданий общей для наших подсетей:
# Создаем сеть зданий
buildings_net = ipaddress.ip_network('192.168.12.0/22')
# Проверяем принадлежность всех офисных сетей
print("Офисная сеть:", buildings_net.supernet_of(office_net)) # True
print("Сеть этажа 1:", buildings_net.supernet_of(floor1_net)) # True
print("Сеть этажа 2:", buildings_net.supernet_of(floor2_net)) # True
Все три метода вернут True. А вот если у нас сеть зданий имеет такой адрес 192.168.4.0/23 то все три метода вернут False.
# Создаем сеть зданий
buildings_net = ipaddress.ip_network('192.168.4.0/23')
# Проверяем принадлежит ли офисная сеть и сеть этажей к общей сети зданий
print("Офисная сеть:", buildings_net.supernet_of(office_net)) # False
print("Сеть этажа 1:", buildings_net.supernet_of(floor1_net)) # False
print("Сеть этажа 2:", buildings_net.supernet_of(floor2_net)) # False
Теперь давайте получим список доступных конечных IP-адресов в сети второго этажа.
Для этого воспользуемся Python-циклами:
# Перебираем все хосты внутри сети floor2_net
for host in floor2_net.hosts():
print(host)
И если его запустить, то он выведет по порядку все адреса начиная с 192.168.13.129 и 192.168.13.254. Эти адреса мы спокойно можем назначать нашим компьютерам, серверам, принтерам и другой технике.
Далее разберемся, как можно получить максимальный и минимальный адрес подсети. И тут нам поможет следующей Python-код:
# Получаем список всех хостов в сети
floor2_hosts = list(floor2_net.hosts())
# Получаем минимиальный и максимальный хост (вариант 1)
min_host, max_host = min(floor2_hosts), max(floor2_hosts)
# Получаем начальный и конечный хост (вариант 2)
min_host, max_host = floor2_hosts[0], floor2_hosts[-1]
# Выводим минимальный и максимальный IP адрес в сети
print(min_host, max_host)
И наконец, давайте проверим к какой сети принадлежит случайный IP-адрес: пусть будет 192.168.13.187
Для этого сперва создадим объект IP-адреса, а потом с помощью оператора in проверим его принадлежность сети:
# Создаём IP адрес пользователя
user_ip = ipaddress.ip_address("192.168.13.187")
# Проверяем к какой сети он относится
print("Первый этаж:", user_ip in floor1_net) # False
print("Второй этаж:", user_ip in floor2_net) # True
print("Офис:", user_ip in office_net) # True
print("Сеть зданий:", user_ip in buildings_net) # True
Что ж, с основной задачей мы справились. Разумеется, библиотека ipaddress содержит и другие методы для работы с сетями, с помощью которых вы можете гибко объединять сети, вычитать, сравнивать и так далее. Но тут уже каждый системный администратор или программист найдет для себя то, что ему нужно в реальной работе. Задачи у всех разные.
Также, если чуть глубже научиться программировать на Питоне, вы можете автоматизировать и другие рутинные операции: изменение конфигурации маршрутизаторов, мониторинг состояния сети, управление политиками безопасности и т.д.. Тут, правда, потребуется уже более серьезный курс по Python, а также изучение сторонних библиотек, например, Netmiko или NAPALM.