Лю­бое при­ложе­ние, которое хоть как‑то работа­ет с сетью, дол­жно валиди­ровать пра­виль­ность 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, для валида­ции адре­сов нужен пол­ноцен­ный пар­сер. Писать его самим нет смыс­ла, пос­коль­ку сущес­тву­ют готовые биб­лиоте­ки, которые пре­дос­тавля­ют и дру­гие полез­ные фун­кции.

 

Проверки по существу

Ес­ли уж мы взя­лись под­клю­чать биб­лиоте­ку и пар­сить адре­са, давай пос­мотрим, какие допол­нитель­ные про­вер­ки мы можем про­вес­ти, что­бы отсе­ять оши­боч­ные зна­чения и сде­лать сооб­щения об ошиб­ках более информа­тив­ными.

Продолжение доступно только участникам

Вариант 1. Присоединись к сообществу «Xakep.ru», чтобы читать все материалы на сайте

Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее

Вариант 2. Открой один материал

Заинтересовала статья, но нет возможности стать членом клуба «Xakep.ru»? Тогда этот вариант для тебя! Обрати внимание: этот способ подходит только для статей, опубликованных более двух месяцев назад.


3 комментария

  1. Аватар

    Laglag

    18.02.2021 в 16:00

    великолепно спасибо за информацию, скоро наверное ip4 уйдет на нет так как у ip6 над ним приоритет….

  2. Аватар

    vinitto

    22.02.2021 в 16:08

    Я помню раньше была возможность материал добавить в избранное. Например чтобы почитать потом. Сейчас как это можно сделать?

    • Андрей Письменный

      Андрей Письменный

      26.02.2021 в 11:16

      Сердечко и «Добавить в закладки» в шапке под заголовком (нужно залогиниться).

Оставить мнение