17 лет назад 13 ноября 2006 в 10:58 3125

 

Конечно, все аспекты работы протоколов невозможно разобрать в одной статье, но если вам интересно более детально изучить тему, то почитайте документы RFC (Request For Comments). Публикуются они на английском языке, интересующимся — сюда: www.ietf.org.Но для того, чтобы в общих чертах понимать, как работает эта замечательная технология, необходимо разобраться, как функционируют протоколы IP, TCP и UDP. Поэтому сегодня мы поговорим о сетевом и транспортном уровнях модели OSI.

Протокол IP
Как я и говорил, протокол IP занимается межсетевой доставкой пакетов данных по каналам связи, причем его не волнует, какая среда между двумя маршрутизаторами. Это важно потому, что на своем пути пакет может преодолеть несколько разных сред. Например: от клиентского компьютера до маршрутизатора провайдера — ADSL, от маршрутизатора провайдера до вышестоящего провайдера — FDDI (оптика), далее — опять оптика, а от провайдера хостера до самого сервера — Ethernet. Причем ни данные, ни заголовок не должны изменяться. Ни на одном этапе. Исключения есть, но о них чуть позже. ОС сама заполняет все необходимые поля, исходя из полученных от приложения данных. (См. таблицу 1. Обращаю ваше внимание на то, что второе поле — это длина заголовка, а не пакета, и на то, что в этом заголовке указана контрольная сумма заголовка IP, а не всего пакета.)

Допустим, наш пакетик, укомплектованный заголовком, готов к отправке. Операционке необходимо решить, что с ним делать, как и куда его отправить. Ответ на эти вопросы дает таблица маршрутизации, которая присутствует в каждой системе, работающей с протоколом IP. Эта таблица как раз и содержит данные о том, куда какие данные переправлять. Чтобы посмотреть ее, отдайте команду route print в консоли Windows либо netstat -rn в Linux или FreeBSD. Помимо прочих, нас пока не интересующих, таблица обязательно содержит следующие поля: адрес сети, маска сети, адрес шлюза, интерфейс. Разберем подробнее каждое.

Адрес подсети, маска подсети
Для того чтобы маршрутизация проходила правильно, весь интернет поделен на так называемые подсети. У подсети есть маска. Чтобы понять, что это такое и для чего оно служит, необходимо вспомнить, что IP-адрес состоит из четырех байтов. Маска подсети тоже состоит из четырех байтов, однако имеет две части: сначала идущие подряд единицы (n), затем идущие подряд нули (32 — n). Единицы — биты, адресующие сеть, а нули — биты, адресующие хост сети. Вообще, подсеть — это некое адресное пространство, выделенное нескольким хостам, которые представляют собой организованную структуру, например районную или корпоративную сеть. Каждая подсеть имеет два специфических адреса. Это адрес сети и адрес Broadcast. Если с адресом сети все более или менее понятно (идентификатор), то адрес Broadcast намного интереснее. По идее, пакет, посланный на него, будет принят и обработан всеми хостами сети, однако на практике маршрутизаторы давно блокируют такие пакеты. Еще подсеть характеризуется тем, что пакеты внутри нее доставляются напрямую, без маршрутизаторов. И даже если районная сеть сегментирована при помощи внутренних маршрутизаторов, то это уже не одна подсеть, а несколько подсетей, объединенных в одну (например, районную).

Основной шлюз
Он же маршрутизатор. Это специальный узел сети, который занимается передачей пакетов между разными сетями.

Интерфейс
Для каждого конкретного маршрута прописывается, с какой именно сетевой карты посылать пакеты, идущие по нему. Уважаемые читатели, открою вам два секрета, которые совсем не секреты. Во-первых, далеко не все интерфейсы являются физическими. То есть каждой сетевой карте соответствует один логический интерфейс, но не обязательно каждому логическому интерфейсу соответствует сетевая карта. Знакомый абонентам локальных сетей пример — VPN-соединение. Логический интерфейс есть, а отдельной сетевой карточки нет и быть не может. Еще бы: это же Virtual Private Network. А во-вторых, даже если компьютер не имеет ни одной сетевой карты, но на нем установлена поддерживающая работу в сети операционка — Windows, Linux, FreeBSD и т. д., — то у него есть как минимум один интерфейс, так называемый LoopBack, или «петля». В этом интерфейсе всегда прописан адрес 127.0.0.1 (самая середина адресного пространства).

Благодаря LoopBack машина доставляет данные сама себе. Вся информация, переданная через него, возвращается на отославший ее компьютер. Кроме того, любая ОС имеет в таблице маршрутизации записи о том, что на ее собственные адреса (прописанные на других интерфейсах вне зависимости от степени их виртуальности) данные необходимо доставлять именно через LoopBack. Это сделано в целях устранения ненужной нагрузки на сетевое оборудование. В таблице маршрутизации содержатся записи с маршрутами до всех подсетей, для которых их надо явно указывать, а для остальных действует так называемый дефолтный маршрут (default). Обычно он обозначается нулевым адресом сети и нулевой маской. Для него указывается адрес основного шлюза и интерфейс, и все пакеты, для которых не указан маршрут, направляются согласно этим правилам.

Чем же маршрутизатор отличается от обычного хоста сети? Во-первых, наличием двух и более сетевых интерфейсов, во-вторых, правом перераспределять пакеты между этими интерфейсами, а в-третьих, наличием соответствующих записей в таблице маршрутизации. То есть любое устройство, имеющее более одного сетевого интерфейса, способно стать маршрутизатором. Маршрутизатор, получив предназначенный не ему пакет, прогоняет его через свой файрволл и, если этот пакет разрешен к передаче, смотрит в свою таблицу маршрутизации, чтобы найти маршрут для него. Если маршрут прописан, отправляет пакет по нему, если нет, пересылает по дефолтному. Но до того производит еще одно важное действие.

Помните, я упоминал про исключения, касающиеся изменения заголовка IP на пути от одного узла к другому? Вот и настало время рассказать про одно из них. Взгляните еще раз на заголовок IP-пакета. Обратите внимание на поле «Время жизни». Оно занимает один байт и, как следствие, может принимать значения от 0 до 255. По-английски оно именуется Time To Live, или, сокращенно, TTL. Так вот, каждый маршрутизатор, через который проходит пакет, уменьшает значение этого параметра на единицу. Если маршрутизатор получит пакет, у которого TTL равно нулю, то пакет будет уничтожен, а его отправителю будет послано специальное сообщение. Так сделано для того, чтобы при неверной настройке маршрутизации и образовании петель (кольцевых цепей) пакеты рано или поздно были уничтожены. На этом основана работа программы Traceroute, о ней написано во врезке. Вот мы и рассмотрели протокол IP. Однако конкретную пользу приносят протоколы, функционирующие на его основе.

Протокол ICMP
Самый простой из протоколов на основе IP. Наиболее востребованная его функция — определять, жив ли конкретный хост сети и доходят ли до него IP-пакеты. Для этого используется популярная команда ping, отсылающая специальные ICMP-запросы, на которые удаленный хост должен дать ответ. Также замеряется время, за которое данные прошли весь путь туда и обратно.

Протоколы TCP и UDP
Как я писал в предыдущей части статьи, протокол IP отвечает только за доставку данных от одного хоста к другому, но не идентифицирует приложения, отправившие и принявшие их. А вот доставкой данных от одного приложения к другому, помимо прочих, занимаются именно TCP и UDP. При их изучении необходимо запомнить одно из основных понятий, которыми мы будем пользоваться, — порт. Это сугубо логический элемент, через который передаются данные. Пара портов на концах соединения однозначно идентифицирует это соединение.

В рамках пакета данных (от уровня MAC до прикладного) идентификатор порта (его номер) обычно фигурирует только в заголовке TCP или UDP. У каждой системы 65 535 портов для работы по TCP и столько же для работы по UDP. Порты делятся на привилегированные (от 1-го до 1023-го) и непривилегированные (от 1024-го до 65 535-го). Изначально считалось, что привилегированные предназначены для установки входящего соединения, непривилегированные — для установки исходящего, а для инициализации привилегированного необходимы административные права. Однако на практике соблюдаются только второе и третье правила. Ну, с портами разобрались, а те, кому непонятно, поймут по ходу чтения. Перейдем к рассмотрению самих протоколов.

Протокол UDP
Его заголовок приведен в таблице 2. (Краткость — сестра таланта. Однако контроль соединения отсутствует, что затрудняет диагностику и выявление проблем средствами транспортного уровня. Но контрольная сумма есть — и то хорошо.) UDP не предоставляет никаких возможностей, кроме фактической идентификации потока данных и проверки целостности доставки при помощи контрольной суммы. Но вместе с тем он не порождает лишнего трафика пакетами подтверждения, в отличие от TCP. В основном этот протокол используется для передачи данных некритичных либо тех, целостность которых контролируется протоколами более высокого уровня. Хорошие примеры сфер применения UDP — это запросы системы DNS, протокол TFTP (не путать с FTP!), а также всевозможные сетевые компьютерные игры. Однако поток важных данных или поток, для которого задержки некритичны, этому протоколу доверять не следует.

Так как UDP не поддерживает сессии, существуют только два начальных состояния порта: закрыт и открыт. Если порт закрыт, то все данные, приходящие на него (в качестве номера порта получателя указан номер закрытого порта), отвергаются, если открыт, то данные передаются приложению, открывшему порт. Если приложение отвечает (посылает данные в ответ), ОС отправляет UDP-пакет, в котором меняет местами номер порта отправителя и номер порта получателя. Благодаря этому приложение, инициировавшее соединение, понимает, в рамках какого соединения (на один хост может приходиться несколько соединений одновременно, да что там — даже на один порт, но порт отправителя для каждого соединения свой) были переданы данные.

Протокол TCP
Он работает значительно медленнее UDP, но зато обеспечивает контроль целостности данных и гарантирует их доставку до порта получателя (но не доставку до самого получателя). Почему-то TCP используется гораздо интенсивнее, чем UDP. (См. таблицу 3. Протокол поддерживает множество опций, однако некоторые из них не используются вообще.) Так уж исторически сложилось. Возможно, отчасти потому, что, несмотря на сложность самого протокола, реализовать приложения на его основе намного проще, чем на основе UDP. Нелегкая функция контроля целостности данных в этом случае ложится на ОС, а пользовательские приложения гоняют данные в обе стороны, как по трубе.

Возможна передача данных по протоколу TCP одновременно в двух направлениях, а для того, чтобы не запутаться, где какие данные, существует механизм контроля, представленный полями Sequence Number (SeqNum) и Acknowledgement Number (AckNum). SeqNum содержит номер первого передаваемого байта, AckNum — номер первого ожидаемого байта. Ориентируясь на эти номера, ни одна система не запутается, что делать с только что пришедшими данными — передать приложению или подождать пропавший кусок. Дело в том, что у глобальных сетей есть особенность, обусловленная динамической маршрутизацией: первый отправленный пакет может прийти позже второго. Для того и был введен вышеописанный механизм контроля.

Рассмотрим сам протокол и особенности его работы. Согласно спецификации, у порта есть несколько состояний. Для того чтобы соединение было установлено, порт должен находиться в состоянии Listen (ждать запроса на соединение), иначе любые данные, приходящие на него, будут отброшены. Соединение устанавливается, когда на открытый порт приходит пакет с флагом SYN и SeqNum = 100. На это система отвечает либо пакетом с флагами SYN и ACK, SeqNum = 300, AckNum = 101, если соединение можно установить, либо пакетом с флагом RST в ином случае. Если соединение возможно, то инициирующая его система отсылает пакет с битом ACK, SeqNum = 101, AckNum = 301, после чего разрешается передача, соединение  установлено, порты переводятся в состояние Established (готовы к приему).

Завершение соединения чуть сложнее его установки. Сторона, решившая завершить соединение, отправляет пакет с битами FIN и ACK, SeqNum = 100, AckNum = 300 и переводит свой порт в состояние FIN-WAIT-1. Другая сторона должна ответить битом ACK, SeqNum = 300, AckNum = 101, что переведет порт первой в состояние FIN-WAIT-2, а порт второй — в состояние LAST-ACK. Для того чтобы перевести порт в изначальное состояние, требуется еще один пакет с битами FIN и ACK, SeqNum = 300, AckNum = 101. После получения пакета с битом ACK, SeqNum = 101, AckNum = 301 и небольшого тайм-аута оба порта переводятся в свои исходные состояния. Я бы с радостью привел схему состояний сокета TCP, да боюсь, что многоуважаемый Барсик мне этого не даст сделать. (Вам волю дай — ничего, кроме таблиц и графиков, не оставите! — Прим. ред.) Чтобы более подробно узнать про работу протокола TCP, а также увидеть много схем и рисунков по теме, прочтите RFC 793:
www.ibiblio.org/pub/docs/rfc/rfc793.txt.

Технология NAT
С IP, TCP, UDP и портами разобрались, пора поговорить о том, как экономится адресное пространство в Сети. Когда американцы, интернет изобретшие, поняли, что они не одни на свете (а они что, все-таки поняли?! — Прим. ред.), а адресов на всех не хватит, выяснилось, что далеко не каждая машина должна иметь возможность принимать входящие соединения, но каждая должна иметь возможность установить соединение с необходимым ей сервером. И была придумана технология, позволяющая локальной сети выглядеть для остального мира единым хостом. Специально для этого были выделены три адресные зоны: 10 / 8, 172.16 / 12 и 192.168 / 16. (Вы у меня умные, короткую запись понимаете, могу позволить себе такую вольность.) Вообще, зоны должны подбираться в зависимости от размера сети, а на деле все решают предпочтения системного администратора. Я вот, например, сетку 10 / 8 люблю.

Особенность этих адресов в том, что во «внешнем» интернете они не используются: любой маршрутизатор приняв через интерфейс, не обслуживающий такую сеть (то есть на нем не прописаны адреса этих зон), пакет, в котором адрес отправителя или получателя входит в вышеприведенные диапазоны, уничтожит его.
Продвинутый пользователь поинтересуется: «А вот у меня на машине адрес 10.0.0.200 — и ничего! Интернет работает! Как так?» Дело в том, что такой пользователь находится под юрисдикцией NAT (Network Address Translation), которая и позволяет ему безбоязненно ходить в Сеть. Как же это происходит?

Роутер получает TCP-пакет с флагом SYN и SeqNum = 100 (вспоминаем, что такой пакет инициирует начало нового соединения), отправленный, например, серверу http://www.livejournal.com/ (204.9.177.18) на порт 80 от хоста внутренней сети 10.9.8.7 с порта 3847 (соединение всегда устанавливается со случайно выбранного непривилегированного порта). После того как файрволл, а возможно, еще и антивирус проверил пакет на вшивость, маршрутизатор принимает решение пропустить его. Но он не передает пакет в изначальном виде дальше, а сам случайным образом выбирает непривилегированный порт и меняет в заголовке IP-адрес отправителя на свой внешний (или какой указан в конфигурации), например 87.215.125.14, а в заголовке TCP вместо порта отправителя ставит только что выбранный. Далее маршрутизатор вносит в таблицу преобразований следующую запись: «Внутренний адрес и порт — 10.9.8.7:3847.

Внешний адрес и порт — 87.215.125.14:33203. Адрес и порт соединения — 204.9.177.18:80. Протокол — TCP» — и отправляет пакет согласно своей таблице маршрутизации. Благодаря этой записи в тот момент, когда с 204.9.177.18:80 придет пакет для 87.215.125.14:33203, маршрутизатор заменит IP-адрес получателя (пакет-то входящий!) на 10.9.8.7, а порт получателя — на 3847, хост внутренней сети примет и обработает пакет как ни в чем не бывало. Эта схема замечательна тем, что таких преобразований на пути пакета может быть несколько. К примеру, вы абонент локальной сети с внутренней зоной адресов 10 / 8 и ставите у себя дома маршрутизатор (точку доступа Wi-Fi). На внешнем интерфейсе вы прописываете адрес 10.9.8.7, а на внутреннем — 192.168.0.1 / 24. Тогда пакет от вашего ноутбука с адресом 192.168.0.10 / 24 пройдет два преобразования: одно — в точке доступа, другое — в маршрутизаторе локальной сети.

Еще одна особенность системы NAT в том, что ни один хост из интернета не может установить прямое соединение с внутренним хостом локальной сети. С одной стороны, хорошо, так всяким хакерам сложнее добраться до машин, с другой — это правило распространяется и на сервера, которые, возможно, должны быть видны снаружи (например, почтовые или веб-сервера). Для этого была придумана схема «проброски» портов. Различными средствами создается, например, такая запись в таблице преобразования: «Внутренний адрес сети — 10.9.8.7:80.

Внешний адрес — 87.215.125.14:80. Соединение открыто. Протокол — TCP». В таком случае при получении TCP-пакета с SYN и SeqNum = 100 маршрутизатор отправит хосту 10.9.8.7 на 80-й порт пакет с обратным адресом и портом хоста, установившего соединение (конечно, только в случае, если такое соединение одобрено файрволлом). Далее данные будут преобразовываться по вышеприведенной схеме. Таким образом, и эта проблема решаема. Между прочим, на маршрутизаторе можно прописать даже такую строчку: «Внутренний адрес — 10.9.8.7. Внешний адрес — 87.215.125.16. Соединения открыты. Протоколы — TCP и UDP». Тогда, если маршрутизатор получит на внешний интерфейс пакет для 87.215.125.16, он заменит только IP-адрес и отправит внутреннему хосту. Конечно, в данном случае файрволл тоже работает.

Ну, вот мы и разобрали основные технологии транспортного и сетевого уровней. Если вам захотелось понять, как именно компонуются пакеты, где какие заголовки используются и как все это выглядит вместе, воспользуйтесь любым доступным сниффером. Пользователям ОС Windows рекомендую утилиту Iris Network Traffic Analyzer. Она наглядно показывает заголовки пакета и их поля. Пользователям Linux советую программу tcpdump, которая, несмотря на свое название, показывает не только TCP, но и UDP, а также просто Ethernet-пакеты. Очень полезно для понимания принципов работы сетей. Можно на «живых» пакетах посмотреть, как какие байты располагаются, и соотнести приведенные в статье рисунки с реальными данными. На сегодня все. Cоветую вам почитать и следующую часть статьи, посвященную протоколам прикладного уровня. Продолжение следует…

 

VadZay

Никто не прокомментировал материал. Есть мысли?