Содержание статьи
- Валидация адресов
- Проверки по форме
- Проверки по существу
- Библиотеки
- netaddr
- libcidr
- Заключение
Любое приложение, которое хоть как‑то работает с сетью, должно валидировать правильность IP-адресов. Это сложнее, чем может показаться. Здесь легко впасть в крайности: при излишне строгой валидации пользователь не сможет ввести верные данные, при недостаточной — окажется наедине с низкоуровневыми сообщениями об ошибках (если они вообще передаются). В этой статье мы разберем ряд сложностей, возникающих при валидации адресов, а потом посмотрим на готовые библиотеки, которые с этим помогают.
Валидация адресов
Ошибки в адресах могут появиться тремя способами:
- опечатки;
- недопонимание;
- намеренные попытки сломать приложение.
От попыток сломать приложение одна валидация адресов не поможет. Она может затруднить такие попытки, но не заменит полноценную проверку авторизации и обработку ошибок на всех этапах работы программы, так что улучшение безопасности нужно рассматривать скорее как полезный побочный эффект. Основная цель — упростить жизнь пользователям, которые случайно ввели неверный адрес или неправильно поняли, что от них требуется.
Проверки можно условно разделить на проверки по форме и по существу. Цель формальной проверки — убедиться, что введенная пользователем строка вообще может быть допустимым адресом. Многие программы ограничиваются именно этим. Мы же пойдем дальше и посмотрим, как можно проверять, что адрес не только правильный, но и подходящий для конкретной цели, но об этом позже.
Проверки по форме
Проверка правильности формата только на вид может показаться задачей для несложного регулярного выражения — на деле все не так просто.
В IPv4 сложности начинаются со стандарта на этот формат — такого стандарта не существует. Формат dot-decimal (0.0.0.0–255.255.255.255) — общепринятый, но не стандартный. Стандарт IPv4 не содержит никаких упоминаний о формате записи адресов вообще. Никакой другой RFC тоже ничего не говорит о формате адресов IPv4, так что общепринятый формат — это не более чем соглашение.
И это даже не единственное соглашение. Функция inet_aton() позволяет не писать нулевые разряды в конце адреса, например 192.0.2 = 192.0.2.0. Кроме того, она позволяет вводить адрес одним целым числом, 511 = 0.0.1.255.
info
Может ли адрес хоста заканчиваться на ноль? Конечно, может — в любой сети размером больше /23 найдется хотя бы один такой. Например, 192.168.0.0/23 содержит адреса хостов 192.168.0.1–192.168.1.254, включая 192.168.1.0.
Если ограничиться поддержкой только полного dot-decimal из четырех групп, без возможности опускать нулевые разряды, то выражение (d+).(d+).(d+).(d+) может поймать значительную часть опечаток. Если задаться целью, можно составить выражение для любого допустимого адреса, хотя оно и будет довольно громоздким. Лучше воспользоваться тем, что его легко разделить на группы, и явно проверить, что каждая из них попадает в диапазон 0–255:
def check_ipv4(s): groups = s.split('.') if len(groups) != 4: for g in groups: num = int(g) if (num > 255) or (num < 0): raise ValueError("Invalid octet value")
С IPv6 все одновременно проще и сложнее. Проще потому, что авторы IPv6 учли опыт IPv4 и добавили формат записи адресов в RFC 4291. О любых альтернативных форматах можно смело говорить, что они против стандарта, и игнорировать. С другой стороны, сами форматы сложнее. Основную сложность представляет сокращенная запись: группы нулевых разрядов можно заменять на символ ::, например 2001:db8::1 вместо 2001:db8:0:0:0:0:0:1. Для пользователя это, безусловно, удобно, но для разработчика все ровно наоборот: разделить адрес на группы по двоеточию невозможно, нужна заметно более сложная логика. К тому же стандарт запрещает использовать :: больше одного раза в одном адресе, что еще сильнее усложняет задачу.
Так что, если приложение поддерживает IPv6, для валидации адресов нужен полноценный парсер. Писать его самим нет смысла, поскольку существуют готовые библиотеки, которые предоставляют и другие полезные функции.
Проверки по существу
Если уж мы взялись подключать библиотеку и парсить адреса, давай посмотрим, какие дополнительные проверки мы можем провести, чтобы отсеять ошибочные значения и сделать сообщения об ошибках более информативными.
Продолжение доступно только участникам
Материалы из последних выпусков становятся доступны по отдельности только через два месяца после публикации. Чтобы продолжить чтение, необходимо стать участником сообщества «Xakep.ru».
Присоединяйся к сообществу «Xakep.ru»!
Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее
1 год8460 р. |
1 месяц790 р. |
Я уже участник «Xakep.ru»