Статическая маршрутизация в вопросах и ответах

Этот краткий FAQ я составил, руководствуясь идеей необходимости вычленить из огромной области знаний, называемой “статическая IP-маршрутизация”, только те вопросы, которые действительно необходимо знать читателю рубрики, в которой помещена эта статья, то бишь, системному администратору.

В повседневной работе рядовой администратор систем, завязанных на LAN, сталкивается с вопросами маршрутизации лишь эпизодически. И, естественно, не имея достаточного времени, чтобы ясно увидеть задачу, он не может эффективно ее решить. Но маршрутизация – это инструмент чрезвычайно гибкий, и достаточно иметь десяток приемов, чтобы вчерашние проблемы превратить в приятную работу. Именно с такими приемами читатель сможет познакомиться, дочитав статью до конца.
Что касается динамической маршрутизации, могу лишь сказать, что это несколько другая тема, которая здесь не рассматривается, но которую невозможно понять, не зная основ в статике.
Ниже рассматриваются примеры, реализованные на ОС Linux. Если вы работаете на другой ОС, то необходимо лишь уточнить синтаксис команд и незначительные детали. Также для понимания поднимаемых вопросов необходимо хорошее понимание IP-адресации и начальные навыки в конфигурировании сетевых устройств.

вопрос 1

Почему хосты, интерфейсы которых имеют IP-адреса, принадлежащие разным логическим сетям, в некоторых случаях могут нормально взаимодействовать без дополнительной маршрутизации? Вот примеры подобных пар IP-адресов: 10.10.1.1/8 – 10.10.2.2/16, 192.168.5.1/16 – 192.168.5.2/24. Ведь в первом случае адреса сетей будут 10.0.0.0 и 10.10.0.0, во втором 192.168.0.0 и 192.168.5.0.

Посмотрим, когда такое “взаимодействие” (назовем так обмен пакетами между интерфейсами хостов) может не получиться. Если на хосте образуется пакет с IP-адресом назначения, не попадающим ни под один из маршрутов внутренней таблицы маршрутизации этого хоста, то он отправляется на маршрут по умолчанию (default gateway, см. также вопрос 6). И решение о том, куда направлять пакет, предоставляется следующему маршрутизатору, и так далее. Таким образом, если верный маршрут до получателя не существует ни на одном из маршрутизаторов по пути следования пакета, он может “потеряться” и не дойти до получателя.

В вопросе же указаны пары адресов, обмен пакетами между которыми вполне осуществим с помощью записей во внутренних таблицах маршрутизаций хостов, добавляемых операционной системой автоматически при активации сконфигурированных интерфейсов. Например, у хоста с активированным и настроенным на IP-адрес 10.10.1.1/8 интерфейсом, во внутренней таблице маршрутизации, помимо других, будет приблизительно такая запись:

Destination Gateway Genmask Flags Metric Ref Use Iface
10.0.0.0 * 255.0.0.0 U 0 0 0 eth0

Теперь посмотрим, подходит ли такая запись для пакета с адресом 10.10.2.2. Применим к этому адресу маску 255.0.0.0 из вышеприведенной записи. Получаем логическую сеть 10.0.0.0. Таким образом, пакет отправится на интерфейс eth0. А для получателя, IP-адрес отправителя пакета совершенно безразличен, и учитывается только при генерации ответа.

То же можно сказать и о хосте с интерфейсом, у которого IP-адрес 10.10.2.2/16. Применение маски 255.255.0.0 к IP адресу 10.10.1.1 даст логическую сеть 10.10.0.0. Маршрут на этом хосте для такой логической сети существует, и пакет с адресом назначения 10.10.1.1 будет отправлен именно по этому маршруту. Замечу, что это может быть ответ на пакет, пришедший с с хоста, рассмотренного первым. В результате получаем полноценный обмен пакетами.

Таким образом, если есть пара интерфейсов в пределах одного физического сегмента, то можно сформулировать следующее простое правило: если применение маски первого интерфейса к обоим IP-адресам дает равный результат, а также применение маски второго интерфейса к обоим IP адресам дает также равный результат, то хосты будут нормально обмениваться пакетами в обоих направлениях.

То, что мы обсудили, имеет название. Supernetting – высвобождение адресов хостов за счет уменьшения количества сетей — метод, обратный выделению подсетей за счет уменьшения количества хостов (subnetting).

вопрос 2

У меня в LAN появился хост с “неподходящей” подсетью в IP-адресе, например, другого класса. Изменять этот IP-адрес нельзя. Что делать? Не менять же адреса у всех хостов, которые с ним работают?

Есть несколько методов решения этой проблемы.

Метод 1.
Самый простой инеэффективный– добавить дополнительный IP-адрес с подходящей подсетью хосту, который инициирует коннекты. Здесь есть варианты. Можно установить дополнительный интерфейс и сконфигурировать его соответствующим образом. Проще добавить к интерфейсу так называемый alias. Это дополнительный IP-адрес, привязанный к интерфейсу и действующий наравне с основным. Следующая команда присваивает интерфейсу eth0 дополнительный IP адрес 172.16.1.1.

#ifconfig eth0:1 inet 172.16.1.1 netmask 255.255.0.0 broadcast 172.16.255.255

где eth0:x – название виртуальных интерфейсов, которые обслуживаются той же сетевой картой, что и интерфейс eth0. Указание broadcast в данном случае не обязательно, но если вы практикуете использование нестандартных масок, рекомендую взять в привычку указание этого параметра, т.к. по умолчанию принимается значение, соответствующее классу IP-адреса и часто не соответствует указанной маске.

Замечу, что при добавлении интерфейса с IP-адресом либо IP alias, всегда автоматически добавляется соответствующий маршрут в таблицу маршрутизации. Именно это обстоятельство позволяет решить нашу проблему.
Недостаток данного метода в необходимости конфигурирования большого количества клиентов.

Метод 2.
Можно добавить в хосты, инициирующие коннекты, соответствующий маршрут. Например. Клиентский хост имеет знакомый из предыдущего вопроса IP-адрес 10.10.2.2/16. Сервер имеет IP-адрес 172.16.1.200/16. Добавляем на клиентском хосте маршрут.

#route add –net 172.16.0.0 netmask 255.255.0.0 eth0

Тем самым мы указываем, что все пакеты, предназначенные для логической сети 172.16.0.0, нужно отправлять на интерфейс eth0. Этого достаточно, чтобы клиентский хост с IP-адресом 10.10.2.2/16 мог устанавливать сессии с сервером 172.16.1.200/16. Этот метод на самом деле мало отличается от первого :-)
/* Можно также использовать маршрут на отдельный хост (подробнее рассмотрен в вопросе 6). Если в приведенном выше примере не существенно, какую форму записи маршрута (на хост или на сеть) выбрать, есть ситуации, когда маршрут на хост является единственно возможным вариантом. Сразу пример: внутри нашей сети, использующей «нереальные» (fake) адреса, находится хост с реальным адресом, причем все остальные его собратья по IP-сети (подсети) находятся в другом месте (за шлюзом, например). В этом случае можно использовать только маршрут на хост. — прим. ред. */

Метод 3.Может оказаться очень эффективным метод указания маршрута на шлюзе (благо он есть практически в любой организации), если клиентские рабочие станции уже настроены на него. На Рис. 1 показана такая ситуация. Многочисленные клиентские хосты (Cx) настроены на шлюз по умолчанию 10.10.99.99/16. Тогда на G1 добавляем маршрут, как это сделано в предыдущем пункте.

G1#route add –net 172.16.0.0 netmask 255.255.0.0 eth0

Тогда все пакеты хостов Сx к адресу 172.16.1.200/16 будут вначале перенаправляться на G1, потому что на Cx маршрута на сеть 172.16.0.0 нет и, следовательно, применяется маршрут по умолчанию (default) на 10.10.99.99, а затем с G1 согласно указанного нами маршрута на интерфейс, подключенный к внутренней LAN. Это может быть интерфейс eth0. А может быть и дополнительный eth1. И, наконец, с этого интерфейса пакеты попадают на S1 .

/* Кстати, если уж вводить на G1 дополнительный интерфейс, можно изменить и схему подключения G1 и S1, а именно: S1 включить напрямую в eth1 на G1, оставив последнему только одну точку подключения к LAN. С точки зрения network design’a это несколько корректней, особенно применительно к некоммутируемому Ethernet, хотя в каждом конкретном случае могут быть свои нюансы. — прим. ред. */

Вот результат применения команды tracert на Windows-машине C1 в описанном случае.

С1>tracert 172.16.1.200

Tracing route to 172.16.1.200 over a maximum of 30 hops

1 1 ms <1 ms <1 ms 10.10.99.99
2 1 ms <1 ms <1 ms 172.16.1.200

Trace complete.

Недостаток этого метода очевиден. Весь трафик будет проходить через G1, поэтому необходимо предусмотреть достаточную пропускную способность оборудования по всему маршруту следования трафика.

вопрос 3

Третий метод замечательно работает, но теперь S1 не видит клиентов Cx!

Все верно. Теперь посмотрим на S1 как клиента для Cx. Чего не хватает? Маршрута для сети 10.10.0.0 на S1. Добавляем.

S1#route add –net 10.10.0.0 netmask 255.255.0.0 eth0

На этот раз нет смысла заворачивать маршрут на G1, потому что есть возможность прописать маршрут сразу на S1, и только один раз.

вопрос 4

А если в обсуждаемой выше схеме хосту G1 присвоить дополнительный IP 172.16.x.x? Тогда нет необходимости прописывать маршрут?

Совершенно верно. Можно было на G1 не добавлять маршрут, а присвоить IP-адрес интерфейсу eth1, либо IP alias на eth0, как описано в методе 1 вопроса 2. Тогда остается добавить маршрут по умолчанию на наш законный шлюз (как это сделано на всех клиентах Cx) на сервере S1, чтобы он мог инициировать коннекты к Cx.

S1#route add default gw 10.10.99.99

Получаем еще одну полностью работающую схему. Думаю, здесь вопросов больше нет.

вопрос 5

Какие существуют способы диагностики, помогающие устранить ошибки в конфигурации маршрутов?

Выявление ошибок, на мой взгляд, удобно проводить, двигаясь от конечного интерфейса к начальному. Последовательный ping в таком направлении обычно сразу позволяет выявить этап, на котором застревают пакеты. Следует отметить опцию –R в команде ping. Она показывает маршрут движения пакета, подобно тому, как это делает команда traceroute. Для того, чтобы увидеть пришедший ICMP-пакет на интерфейс назначения может пригодится сетевой монитор, скажем, tcpdump. Например, команда

#tcpdump proto ICMP

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

Для проверки правильности прохождения пакетами маршрутов незаменимой остается traceroute. Напомню, что каждая строка (hop) означает изменение маршрута согласно таблиц маршрутизации. Первая строка обычно порождается таблицей маршрутизации хоста, с которого идет трассировка. Каждая последующая – прохождение маршрутизатора.

Очень важно, на мой взгляд, понимание следующего тезиса. IP-маршрутизация работает на сетевом (3-м) уровне модели OSI и опирается на канальный (2-й). В этом смысле маршрутизатор можно условно назвать коммутатором 3-го уровня. Для того чтобы отделить ошибки, не связанные с маршрутизацией, нужно провести диагностику на канальном уровне. Тогда, убедившись, что на этом уровне все хорошо, можно искать проблемы на сетевом уровне.

Отличной проверкой правильной работы канального уровня /* точнее, сопряжения канального уровня с сетевым — прим. ред. */ может служить наличие корректного MAC-адреса нужного интерфейса в ARP-кэше. Например.

source_host>ping –с 1 [target_hostname | IP]
source_host>arp –a [target_hostname | IP]

Сверив полученный из кэша адрес с истинным адресом интерфейса (команда ifconfig),

target_host>ifconfig [interface]

можно сказать что, скорее всего, на канальном уровне все в порядке.

/* Когда ситуация в вашей сети еще не совсем «устаканилась», то бишь вы часто меняете адреса на некоторых хостах/интерфейсах, изучение ARP-кэша поможет вам отыскать самый что ни на есть классический глюк: если некий адрес только что принадлежал одному хосту и его переназначили другому, то MAC-адрес прежнего хозяина того IP-адреса, который вы столь усердно и безрезультатно пингуете, мог просто застрять в ARP-кэше. Пакеты уходят «вникуда», их там никто не ждет — старый владелец адреса может быть отключен или ему назначен другой адрес и он пытается смаршрутизировать пакеты... ерунда в общем полная :)

Очистить ARP-кэш (полностью или частично) можно с помощью команды arp –d. — прим. ред. */
В принципе, пяти команд – ifconfig, route, ping, arp, и traceroute хватает для решения любой задачи статической маршрутизации. Ну и сетевой анализатор, как было сказано выше, не помешает.

вопрос 6

Какие еще существуют записи для таблицы маршрутизации?

Пока мы применяли один тип маршрута – трафик логической подсети направлялся на интерфейс. Другой тип маршрута для выделения нужного трафика — это маршрут для указанного хоста. Т.е. есть возможность указать маршрут персонально для одного хоста (опция add -host), хотя применяется такая запись редко.

Это были виды маршрутов с точки зрения критериев принятия решения о выборе записи.
С точки зрения направления движения трафика помимо рассмотренного нами указания интерфейса есть возможность перенаправить пакеты на указанный IP-адрес шлюза (gateway). Тогда не учитывается конкретный IP-адрес, указанный в пакетах и, следовательно, принятие решения о цели пакетов откладывается до следующего маршрутизатора. Таких перенаправлений может быть сколь угодно много, и ограничено лишь значением TTL (Time To Live).

Частным случаем перенаправления на шлюз является запись default. Это запись для сети, имеющей значение 0.0.0.0, т.е. “вся сеть“. Правило для такого маршрута срабатывает, когда IP-адрес цели пакета не подходит ни под один из критериев, указанных в таблице маршрутизации. На практике маршрут по умолчанию следует настраивать на шлюз в Интернет. В этом есть практический смысл. Если хосты, которые запрашивает клиент, отсутствуют в LAN, то они могут быть в остальной сети, т.е. в Интернет.
В добавлении маршрута на конкретный IP-адрес есть одна особенность. Для IP-адреса шлюза уже должен существовать маршрут. Иначе неизвестно куда отправлять пакет. Поясню сказанное на примере. Сначала добавляем запись для сети 192.168.5.0, а затем уже запись для сети 172.16.0.0 на шлюз 192.168.5.1.

#route add –net 192.168.5.0 netmask 255.255.255.0 eth0
#route add –net 172.16.0.0 netmask 255.255.0.0 gw 192.168.5.1 eth0

вопрос 7

Моя LAN разделена на две большие части, которые соединены достаточно медленной (1Мбт/c) линией. Широковещательный трафик занимает значительную долю этой линии. Как мне разделить две эти сети на подсети, чтобы проходил трафик только с конкретными IP-адресами?

Собственно, это главная задача маршрутизации – уменьшать трафик за счет разделения сетей, либо другими словами, направлять трафик по назначению и никуда более.
Разберем пример, когда LAN состоит из двух частей, соединенных относительно низкоскоростным каналом (Рис. 2). Подключение к Интернет имеет только первая часть. Это приемлемо, когда канал в Интернет еще более узок, чем канал между частями LAN.

Рассмотрим конфигурацию приведенной схемы.
Верхняя часть.

С1#route add default gw 10.10.99.99
G1#echo "1" > /proc/sys/net/ipv4/ip_forward
G1#route add –net 10.20.0.0 netmask 255.255.0.0 gw 10.10.99.98 eth1
R1#echo "1" > /proc/sys/net/ipv4/ip_forward
R1#route add –net 10.20.0.0 netmask 255.255.0.0 gw 172.17.1.2 eth1
R1#route add default gw 10.10.99.99


Нижняя часть.

СR1#route add default gw 10.20.99.98
R2#echo "1" > /proc/sys/net/ipv4/ip_forward
R2# route add default gw 172.17.1.1

На хостах G1, R1, R2 должен быть включен форвард пакетов между сетевыми адаптерами. Вписываем “1” в файл /proc/sys/net/ipv4/ip_forward, если это не сделано.

Множество клиентов Cx имеют настройку на шлюз G1 для всех неизвестных сетей (по умолчанию). Любой обращение к сетям, отличным от 10.10.0.0, обрабатывает G1. В случае, если идет обращение к сети 10.20.0.0, шлюз G1 перенаправляет это обращение к маршрутизатору R1. А маршрутизатор R1 перенаправляет на маршрутизатор R2. В свою очередь R2 непосредственно находится в сети 10.20.0.0. и направляет обращение к нужному клиенту.

Обращаю внимание еще раз, что трафик в направлении сети 10.20.0.0 проходит через шлюз G1, и необходимо предусмотреть достаточную для этого полосу пропускания. В нашем примере предусмотрена дополнительная сетевая карта eth1, хотя можно обойтись и без нее. Я ее включил в конфигурацию только для наглядности.

Теперь посмотрим на движение ответа на рассмотренный запрос. Удаленные клиенты CRx имеют настройку по умолчанию на шлюз R2. IP-адрес хоста назначения будет относиться к сети 10.10.0.0 и, следовательно, ответ на запрос направится на R2. Здесь такой маршрут снова неизвестен, ответ перенаправлятся по маршруту по умолчанию, на R1, на котором есть интерфейс с подходящей сетью 10.10.0.0. Здесь ответ направляется сразу непосредственно на Cx, минуя шлюз G1, что нас вполне устраивает.

Рассмотрим движение запросов в Интернет всех клиентов Cx и CRx. Предполагаем, что запросы обрабатываются посредством Source network address translation (SNAT), и обеспечивается шлюзом G1. В верхней части клиенты Cx имеют простое подключение к Интернету посредством указания маршрута по умолчанию. Думаю, здесь все ясно. В нижней части клиенты имеют маршрут по умолчанию на шлюз R2. Попав на R2, запрос будет перенаправлен дальше опять по маршруту по умолчанию на R1. На R1 ситуация повторится, и запрос уйдет на шлюз в Интернет G1. Далее по назначению. Ответы на запрос пойдут по тому же маршруту в обратном направлении. Для этого на G1 и R1 уже предусмотрены маршруты для сети 10.20.0.0.
Если нужно в нижней части схемы добавить дополнительный шлюз G2 (10.20.99.99/16) с подключением клиентов CRx в Интернет, то просто зеркально отображаем конфигурацию из верхней части.

С1#route add default gw 10.10.99.99
G1#echo "1" > /proc/sys/net/ipv4/ip_forward
G1#route add –net 10.20.0.0 netmask 255.255.0.0 gw 10.10.99.98 eth1
R1#echo "1" > /proc/sys/net/ipv4/ip_forward
R1#route add –net 10.20.0.0 netmask 255.255.0.0 gw 172.17.1.2 eth1
R1#route add default gw 10.10.99.99

G2#echo "1" > /proc/sys/net/ipv4/ip_forward
G2#route add –net 10.10.0.0 netmask 255.255.0.0 gw 10.20.99.98 eth1
СR1#route add default gw 10.20.99.99
R2#echo "1" > /proc/sys/net/ipv4/ip_forward
R2#route add –net 10.10.0.0 netmask 255.255.0.0 gw 172.17.1.1 eth1
R2# route add default gw 10.20.99.99

То же можно сказать о необходимости убрать шлюзы в Интернет совсем. Тогда копируем конфигурацию с нижней части схемы в верхнюю. Конфигурация в этом случае упрощается до безобразия :-).

С1#route add default gw 10.10.99.98
R1#echo "1" > /proc/sys/net/ipv4/ip_forward
R1#route add default gw 172.17.1.2
СR1#route add default gw 10.20.99.98
R2#echo "1" > /proc/sys/net/ipv4/ip_forward
R2# route add default gw 172.17.1.1

вопрос 8

Как сделать так, чтобы конфигурация маршрутов сохранялась после перезагрузки компьютера?

Нужно внести соответствующие изменения в соответствующие файлы :-). Это проще сделать с помощью какой-нибудь комплексной утилиты. Например, с этим прекрасно справляется Linuxconf. Но я предпочитаю делать отдельный скрипт, который включает все настройки, и запускать его автоматически на третьем уровне исполнения. В этом есть значительные преимущества. В скрипте можно одним взглядом охватить всю конфигурацию. Это может оказаться полезным, если она достаточно сложна. Удобно, также, собирать однотипные скрипты со всех хостов для проведения переконфигурирования, либо резервирования конфигурации.

Александр Мисюк, Alexter at tut.by.
Выражаю признательность шеф-редактору за существенное замечание и указание на допущенную мной ошибку в этом вопросе



Сетевые решения. Статья была опубликована в номере 06 за 2003 год в рубрике технологии

©1999-2024 Сетевые решения