суббота, 2 февраля 2008 г.

Дальше про статическую маршрутизацию (или настройка Linux-маршрутизатора)

Я хочу показать, как настраиваются маршрутизаторы и под Linux, и под FreeBSD, и под OpenBSD, и под Windows, и, собственно Cisco.

Для этого пришлось сварганить нижепоказанную топологию с аж 6-ю маршрутизаторами, разнообразно связанными между собой и с "тупиковыми" сетями, которые имеют выход в остальные сети через эти самые маршрутизаторы.
Кроме всего нижепоказанного, каждый роутер подсоединен к сети 10.0.0.0/8, через которую я ими управляю вне зависимости от того, какие интерфейсы у них настроены и какие маршруты есть.




Для начала настроим интерфейсы маршрутизатора, прописав IP-адреса и маски.

В Debian и похожих это делается через файл /etc/network/interfaces. Полученный файл у меня выглядит примерно так:

# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

# The loopback network interface
auto lo eth0 eth1 eth2 eth3
iface lo inet loopback

iface eth0 inet static
address 192.168.250.1
netmask 255.255.255.0

iface eth1 inet static
address 192.168.249.2
netmask 255.255.255.0

iface eth2 inet static
address 192.168.6.1
netmask 255.255.255.0

iface eth3 inet static
address 10.0.0.3
netmask 255.0.0.0

В результате получается аж 4 строки в таблице маршрутизации:
linux-router:/home/stasikos# route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
192.168.6.0 * 255.255.255.0 U 0 0 0 eth2
192.168.249.0 * 255.255.255.0 U 0 0 0 eth1
192.168.250.0 * 255.255.255.0 U 0 0 0 eth0
10.0.0.0 * 255.0.0.0 U 0 0 0 eth3

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

Итак, анализируя топологию, можно сделать вывод, что "there is a more than one way to reach any network". Действительно, практически любая "тупиковая" сеть доступна нам как через eth0, так и через eth1. Очевидно, что для лучшей отказоустойчивости, имеет смысл прописать помимо одного короткого и оптимального - один длинный маршрут через другой интерфейс.
Всего на рисунке показано 6 "тупиковых" сетей и 7 "транзитных", с помощью которых маршрутизаторы связаны между собой. Очевидно, что при наличии трех интерфейсов, из которых один - тупик, у нас осталось 5 сетей-тупиков и еще 4 транзитных сети. Так как эти 5+4 сетей доступны через два интерфейса, нам нужно будет прописать аж 18 маршрутов. Нет, вы конечно, уже подумали про простое решение (какой-нибудь протокол маршрутизации), но я сегодня мазохист и буду заниматься прописыванием маршрутов руками. Ибо мы статической маршрутизацией занимаемся. Вспомним еще, что у нас много маршрутизаторов. Целых 6, и на каждом примерно то же нужно будет выполнить, чтобы вся сеть работала.

Итак, смотрим еще раз на топологию и видим...
Stub1 доступна как через опенбсд, так и через циску, но через опенбсд - ближе
Stub2 доступна так же, но через бсд - ближе
Ближайший маршрут во все другие сети лежит через циску.

как это записать? например, командой route
После чтения route(8) нам становится ясен синтаксис этой команды. Поэтому, забиваем сразу 10 маршрутов

linux-router# route add -net 192.168.1.0 netmask 255.255.255.0 gw 192.168.249.1 metric 10
linux-router# route add -net 192.168.2.0 netmask 255.255.255.0 gw 192.168.249.1 metric 10
linux-router# route add -net 192.168.1.0 netmask 255.255.255.0 gw 192.168.250.2 metric 20
linux-router# route add -net 192.168.2.0 netmask 255.255.255.0 gw 192.168.250.2 metric 20
linux-router# route add -net 192.168.3.0 netmask 255.255.255.0 gw 192.168.250.2 metric 10
linux-router# route add -net 192.168.3.0 netmask 255.255.255.0 gw 192.168.249.1 metric 20
linux-router# route add -net 192.168.4.0 netmask 255.255.255.0 gw 192.168.249.1 metric 20
linux-router# route add -net 192.168.5.0 netmask 255.255.255.0 gw 192.168.249.1 metric 20
linux-router# route add -net 192.168.5.0 netmask 255.255.255.0 gw 192.168.250.2 metric 10
linux-router# route add -net 192.168.4.0 netmask 255.255.255.0 gw 192.168.250.2 metric 10

Запись команды route малость неудобна и громоздка. Поэтому если установлен iproute, проще пользоваться им:
(здесь я буду писать маршруты уже не для "тупиковых" сетей)
linux-router# ip ro add 192.168.255.0/24 via 192.168.249.1 m 10
linux-router# ip ro add 192.168.255.0/24 via 192.168.250.2 m 20
linux-router# ip ro add 192.168.254.0/24 via 192.168.250.2 m 10
linux-router# ip ro add 192.168.254.0/24 via 192.168.249.1 m 20
linux-router# ip ro add 192.168.253.0/24 via 192.168.250.2 m 10
linux-router# ip ro add 192.168.252.0/24 via 192.168.250.2 m 10
linux-router# ip ro add 192.168.251.0/24 via 192.168.250.2 m 10
linux-router# ip ro add 192.168.253.0/24 via 192.168.249.1 m 20
linux-router# ip ro add 192.168.252.0/24 via 192.168.249.1 m 20
linux-router# ip ro add 192.168.251.0/24 via 192.168.249.1 m 20

Посмотрим получившуюся таблицу маршрутизации командой "route"

linux-router:/home/stasikos# route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
192.168.252.0 192.168.250.2 255.255.255.0 UG 10 0 0 eth0
192.168.252.0 192.168.249.1 255.255.255.0 UG 20 0 0 eth1
192.168.254.0 192.168.250.2 255.255.255.0 UG 10 0 0 eth0
192.168.254.0 192.168.249.1 255.255.255.0 UG 20 0 0 eth1
192.168.251.0 192.168.250.2 255.255.255.0 UG 10 0 0 eth0
192.168.251.0 192.168.249.1 255.255.255.0 UG 20 0 0 eth1
192.168.253.0 192.168.250.2 255.255.255.0 UG 10 0 0 eth0
192.168.253.0 192.168.249.1 255.255.255.0 UG 20 0 0 eth1
192.168.255.0 192.168.249.1 255.255.255.0 UG 10 0 0 eth1
192.168.255.0 192.168.250.2 255.255.255.0 UG 20 0 0 eth0
192.168.6.0 * 255.255.255.0 U 0 0 0 eth2
192.168.5.0 192.168.250.2 255.255.255.0 UG 10 0 0 eth0
192.168.5.0 192.168.249.1 255.255.255.0 UG 20 0 0 eth1
192.168.4.0 192.168.250.2 255.255.255.0 UG 10 0 0 eth0
192.168.4.0 192.168.249.1 255.255.255.0 UG 20 0 0 eth1
192.168.3.0 192.168.250.2 255.255.255.0 UG 10 0 0 eth0
192.168.3.0 192.168.249.1 255.255.255.0 UG 20 0 0 eth1
192.168.2.0 192.168.249.1 255.255.255.0 UG 10 0 0 eth1
192.168.2.0 192.168.250.2 255.255.255.0 UG 20 0 0 eth0
192.168.1.0 192.168.249.1 255.255.255.0 UG 10 0 0 eth1
192.168.1.0 192.168.250.2 255.255.255.0 UG 20 0 0 eth0
192.168.249.0 * 255.255.255.0 U 0 0 0 eth1
192.168.250.0 * 255.255.255.0 U 0 0 0 eth0
10.0.0.0 * 255.0.0.0 U 0 0 0 eth3

Можно ласты склеить. "Нифига себе".

Или командой ip route show
linux-router:/home/stasikos# ip ro sh
192.168.6.0/24 dev eth2 proto kernel scope link src 192.168.6.1
192.168.5.0/24 via 192.168.250.2 dev eth0 metric 10
192.168.5.0/24 via 192.168.249.1 dev eth1 metric 20
192.168.4.0/24 via 192.168.250.2 dev eth0 metric 10
192.168.4.0/24 via 192.168.249.1 dev eth1 metric 20
192.168.3.0/24 via 192.168.250.2 dev eth0 metric 10
192.168.3.0/24 via 192.168.249.1 dev eth1 metric 20
192.168.2.0/24 via 192.168.249.1 dev eth1 metric 10
192.168.2.0/24 via 192.168.250.2 dev eth0 metric 20
192.168.1.0/24 via 192.168.249.1 dev eth1 metric 10
192.168.1.0/24 via 192.168.250.2 dev eth0 metric 20
192.168.249.0/24 dev eth1 proto kernel scope link src 192.168.249.2
192.168.250.0/24 dev eth0 proto kernel scope link src 192.168.250.1
192.168.251.0/24 via 192.168.250.2 dev eth0 metric 10
192.168.251.0/24 via 192.168.249.1 dev eth1 metric 20
192.168.252.0/24 via 192.168.250.2 dev eth0 metric 10
192.168.252.0/24 via 192.168.249.1 dev eth1 metric 20
192.168.253.0/24 via 192.168.250.2 dev eth0 metric 10
192.168.253.0/24 via 192.168.249.1 dev eth1 metric 20
192.168.254.0/24 via 192.168.250.2 dev eth0 metric 10
192.168.254.0/24 via 192.168.249.1 dev eth1 metric 20
192.168.255.0/24 via 192.168.249.1 dev eth1 metric 10
192.168.255.0/24 via 192.168.250.2 dev eth0 metric 20
10.0.0.0/8 dev eth3 proto kernel scope link src 10.0.0.3

Чтобы не забивать этой ерундой мозг каждый раз, когда включается маршрутизатор, запишем все команды в шелл-скрипт и положим его в /etc/network/if-up.d.
Честно говоря, он будет не очень простым, так как надо все-таки разбираться, поднятие какого интерфейса вызывает наш скрипт. Для этого ifupdown передает скрипту переменную $IFACE.

Чтобы опять же не заниматься дурной работой (мы ведь уже забили маршруты в таблицу), можно сформировать готовые команды для одного и второго интерфейса с помощью iproute и мозга. То есть, я хотел сказать, sed. )
# ip ro sh dev eth0 | grep -v link | sed -e 's/^/ $ADDCMD /'
# ip ro sh dev eth1 | grep -v link | sed -e 's/^/ $ADDCMD /'

поэтому в результате у нас получится примерно такой скрипт:

#!/bin/sh

ADDCMD='/sbin/ip route add '
case "$IFACE" in
eth0)
# команды для маршрутов через eth0
$ADDCMD 192.168.5.0/24 via 192.168.250.2 metric 10
$ADDCMD 192.168.4.0/24 via 192.168.250.2 metric 10
$ADDCMD 192.168.3.0/24 via 192.168.250.2 metric 10
$ADDCMD 192.168.2.0/24 via 192.168.250.2 metric 20
$ADDCMD 192.168.1.0/24 via 192.168.250.2 metric 20
$ADDCMD 192.168.251.0/24 via 192.168.250.2 metric 10
$ADDCMD 192.168.252.0/24 via 192.168.250.2 metric 10
$ADDCMD 192.168.253.0/24 via 192.168.250.2 metric 10
$ADDCMD 192.168.254.0/24 via 192.168.250.2 metric 10
$ADDCMD 192.168.255.0/24 via 192.168.250.2 metric 20
;;
eth1)
# команды для маршрутов через eth1
$ADDCMD 192.168.5.0/24 via 192.168.249.1 metric 20
$ADDCMD 192.168.4.0/24 via 192.168.249.1 metric 20
$ADDCMD 192.168.3.0/24 via 192.168.249.1 metric 20
$ADDCMD 192.168.2.0/24 via 192.168.249.1 metric 10
$ADDCMD 192.168.1.0/24 via 192.168.249.1 metric 10
$ADDCMD 192.168.251.0/24 via 192.168.249.1 metric 20
$ADDCMD 192.168.252.0/24 via 192.168.249.1 metric 20
$ADDCMD 192.168.253.0/24 via 192.168.249.1 metric 20
$ADDCMD 192.168.254.0/24 via 192.168.249.1 metric 20
$ADDCMD 192.168.255.0/24 via 192.168.249.1 metric 10
;;
*)
# для всех остальных случаев ничего не делаем
exit 0
;;
esac

Я сохранил его в /etc/network/if-up.d/routing и установил на нем бит "исполняемый".

После этого несмотря на перезагрузку, таблица маршрутизатора останется такой же как и была. Т.е. можно считать что таблица на нем настроена.
Остается только включить пересылку пакетов между интерфейсами. Это делается в /etc/sysctl.conf. Туда нужно дописать строку (или раскомментировать, если она там уже есть):
net.ipv4.all.forwarding=1

далее выполняем

linux-router:/# sysctl -p
net.ipv4.conf.all.forwarding = 1

Команда применяет изменения в /etc/sysctl.conf и показывает их на экран.
Вот и все готово. Неверующие набирают еще "reboot" и проверяют, все ли осталось на своих местах. Можно переходить к настройке соседней циски.

Комментариев нет:

Отправить комментарий