Академический Документы
Профессиональный Документы
Культура Документы
Наша задача пометить определённой маркой все пакеты, которые приходят от провайдеров и
предназначены для определённого префикса, это необходимо для того, чтобы мы далее могли на любом
этапе обработки пакетов определить, какому провайдеру принадлежит данный пакет.
Если пакет приходит с интерфейса ether1 и адрес назначения лежит в сети 88.88.88.0/29, и такой пакет
создал соединение, то маркируем соединение маркой Next-Hop/88.88.88.1.
Небольшие пояснения:
88.88.88.0/29 - почему сеть, а не IP? Если вы будете делать правила для каждого IP адреса, количество
правил будет расти, а смысл будет тот же самый.
connection-state=new - нет смысла пытаться маркировать соединения, которые уже установлены, как вы
помните new - это пакет, который создал соединение, т.е он только один, а в случае со всеми пакетами
routeros будет каждый раз пытаться маркировать соединение, которое уже и так может иметь
маркировку.
Next-Hop/99.99.99.1 - почему именно так? Как вы помните, наша главная задача отправить трафик через
тот же самый шлюз, через который трафик пришёл, а мы таким названием себе явно напоминаем, какой
1
шлюз будет использоваться для выхода в сторону провайдера. Мы бы могли использовать что-нибудь
вроде ISP1, но так как у нас первый провайдер даёт два префикса в одном и том же интерфейсе, мы
должны трафик, который приходит на разные префиксы каким нибудь образом разделить.
С этого момента весть трафик, который придёт со стороны провайдера, будет промаркирован, а далее
бы будем оперировать данной маркировкой.
Доступ к маршрутизатору
Первая задача, которую нам необходимо решить, это организовать возможность управления
маршрутизатором через разных провайдеров. Мы должны иметь возможность подключится по любому
IP адресу по ssh, winbox, а также если вы будете использовать RouterOS в случае VPN сервера. В общем
организовать правильный выход пакетов, которые будет отправлены с маршрутизатора в ответ на
входящие соединения.
Для начала нам надо организовать правильные таблицы маршрутизации. В одной таблице
маршрутизации не могут быть одновременно два одинаковых активных маршрута, если маршруты
одинаковы, то приоритет выбирается из значения distance. Для того чтобы можно было использовать
несколько одинаковых маршрутов в RouterOS есть возможность создавать альтернативные
(именованные) таблицы маршрутизации.
Разберём:
gateway=88.88.88.1 - шлюз, обратите внимание на то, что нам первый провайдер даёт два префикса с
разными шлюзами, и поэтому мы создаём три маршрута, для нас по факту не два провайдера, а три.
Вы обратили внимание, что я писал про таблицы и маркировки, дело в том, что маркировка маршрута
это не таблица, хотя в большинстве случаев это так. Попробуйте ответить на вопрос, для чего и какая
разница в правилах между двумя фильтрами в фаерволе.
[admin@MikroTik.Me] /ip firewall mangle add routing- tab tab
routing-mark routing-table
Дело в том, что routing-mark это маркировка, когда вы своими руками с помощью mangle назначили на
пакет маркировку, а routing-table это то, через какую таблицу маршрутизации вышел пакет.
2
можно будет отфильтровать например так routing-mark=custommark routing-table=main. Нам же
такое поведение не нужно, если по какой-то причине маршрут не будет найден, пакет должен умереть
на маршрутизаторе, а отправлять через другого провайдера нет никакого смысла.
Т.е марка и таблица по факту это одно и тоже, пакет который имеет определённую routing-mark
пытается найти маршрут в таблице с таким же именем.
Цепочка output, так как мы работаем только с трафиком, который генерирует в ответ на запрос
соединения. Выбрали пакеты принадлежащие только определённым соединениям и отправили в
именованную таблицу.
Вроде бы всё хорошо и всё должно работать, но это не так, в RouterOS есть один маленький нюанс,
который необходимо помнить и учитывать. Дело в том, что маршрутизатор, прежде чем отправить
пакет в цепочку output, смотрит в таблицу маршрутизации и ищет для адреса назначения подходящий
маршрут в таблице main, есть всего три типа сервисов, которые умеют работать вне данного поведения,
это ping, traceroute и ospf - это необходимо для работы в VRF.
На данный момент у нас нет маршрута по умолчанию в таблице маршрутизации main, встаёт вопрос,
какой шлюз указать в качестве маршрута по умолчанию, если мы укажем первого провайдера, то в
случае падения интерфейса мы останемся у разбитого корыта, мы может сразу указать три шлюза и с
помощью distance указать приоритеты, но тогда мы должны помнить про данную настройку и случае
замены провайдера или какого-либо изменения править конфигурацию и в этом моменте, а там то всего
нужно пройти выбор маршрута и далее уже переопределить направление, т.е по факту это логический
кейс.
Все интерфейсы имеют способность падать, есть один интерфейс, который всегда находится в
состоянии UP, но в RouterOS использовать его в конфигурации не представляется возможным - это
Loopback.
3
Я часто расказываю на курсах, почему именно такое название, а не просто Loopback, возможно в
ближайшем будущем в RouterOS будет добавлено поддержка Loopback интерфейса и если разрабочики
заложат такое-же название, то при обновлении версии RouterOS могут возникнуть проблемы.
А теперь создадим маршрут в таблице main, который необходим для преодоления выбора маршрута и
попадания пакета в цепочку output.
[admin@MikroTik.Me] /ip route add dst-address=0.0.0.0/0 gateway=Br-Loopback
distance=254
Максимальная дистанция для того, чтобы в случае если мы создадим нормальный маршрут по
умолчанию, а не фиктивный, нам данный маршрут не мешал.
Напоминаю, что дистанция 255 это административная дистанция, которая явно указывает на то, что
данный маршрут мёртв и не участвует в маршрутизации.
Выход с маршрутизатора
Хоть и по сути мы сделали уже много, но у нас ещё несколько кейсов впереди. Теперь мы должны
сделать таким образом, чтобы пакеты, которые генерирует сам маршрутизатор (не в ответ), уходили
через нужного провайдера и шлюза.
Когда вы пингуете с маршрутизатора, строите PPP* или IP туннели с самого маршрутизатора или dns
запросы отправляете с самого маршрутизатора. Разница с прошлым кейсом в том, что мы отправляли
пакет по уже установленному соединению, а здесь пакет улетает с маршрутизатора и соединение не
имеет маркировки.
Весь трафик, который уходит с маршрутизатора, и имеет IP адрес, который попадает под префикс,
будет отправлен в именованную таблицу маршрутизации.
Всё, теперь вы можете строить туннели и у вас всё будет работать, но только в том случае если явно
указан IP адрес, например в Ipsec или gre, ip туннели и прочее, там где явно можно указать Source адрес.
А что делать с сервисами, где нельзя указать явно IP адрес источника? Ответ на этот вопрос кроется в
таблице маршрутизации. Параметр pref-src отвечает за то, какой IP адрес будет выбран если он явно не
задан.
Ещё раз для понимания, у нас есть два варианта развитая сюжета, если IP адрес источника явно указан и
тогда нам нечего не грозит и всё замечательно работает. Второй вариант, когда IP адрес явно не задан,
например вы подминаете l2tp-client у нас нет возможности указать source адрес, но ведь адрес
назначения есть в любом случае. Тогда маршрутизатор поступает следующим образом, он находит
маршрут в таблице маршрутизации main, смотрит какой указан pref-src и использует данный ip адрес,
как адрес источника.
4
Вы помните что мы создавали фиктивный маршрут.
[admin@MikroTik.Me] /ip route add dst-address=0.0.0.0/0 gateway=Br-Loopback
distance=254
Давайте его немного изменим так, чтобы мы определили IP адрес, с которого будет формироваться
трафик.
[admin@MikroTik.Me] /ip route
Выбор IP адреса зависит только от вас, выбирайте тот адрес, который считаете менее загруженным.
На этом этапе всё, теперь вы можете строить различные туннели и устанавливать соединения не только
указывая явно source адрес.
Доступ за НАТ
172.20.18.2 - это exchange сервер, мы должны обеспечить доступность 25,80,443 портов через каждого
провайдера.
А теперь давайте вспомним то, что мы делали самым первым правилом в mangle мы промаркировали
все соединения, которые приходят через всех провайдеров! Данная маркировка нам опять поможет.
Нам необходимо отфильтровать весь трафик, который идёт из локальной сети и отправить в том
направлении к маркировки которого соединение имеет отношение.
Попробуем логически по шагам описать то, как это будет работать. Опишем для одного провайдера, для
остальных по тоже схеме.
5
add chain=prerouting connection-mark=Next-Hop/44.44.44.1 in-interface=!ether2
action=mark-routing new-routing-mark=Next-Hop/44.44.44.1 passthrough=no
Наверное нет смысла описывать, всё предельно понятно, на входе мы промаркировали трафик от
провайдеров, и когда пакет снова попал на вход маршрутизатора, но уже пакеты идут от серверов мы
отправляем такие пакеты в именованную таблицу маршрутизации.
Наверное многие спросят, а почему указывается не интерфейс ether1, а не взять и указать явно
локальный интерфейс, например ether4.
Мы с вами делаем универсальную конфигурацию, если явно указать какой-либо другой интерфейс,
значит в случае если у нас будет ещё один NAT, который пойдёт в другой порт, нам необходимо будет
добавлять ещё одно аналогичное правило, но уже с другим интерфейсом. А ведь мы можем даже
завернуть трафик с помощью NAT вообще на внешние сервера например 1.1.1.1, и что тогда?
Единственный интерфейс откуда в цепочке prerouting мы не должны ожидать данный трафик, это
трафик с самого провайдера и причём именно с того, с которого он пришёл.
Всё работает, теперь вы можете подключаться в своему серверу по любому IP адресу. Создайте DNS A
запись RR и укажите все три внешних IP адреса и всегда ссылайтесь на данную запись.
Например: mail.mycompany.ru
mail.mycompany.ru A 88.88.88.2
mail.mycompany.ru A 99.99.99.2
mail.mycompany.ru A 44.44.44.2
Ещё каких-то лет 7 назад, DNS RR работал не очень хорошо, в плане того, что приложения зачастую
использовали только первый IP адрес, сейчас все изменилось и многие приложения в случае, если не
смогут подключиться по одному адресу, будут пытаться подключаться по другому и так далее...
Нам делать ничего не нужно, если вспомнить что в правило NAT попадает только самый первый пакет,
тот на основании которого было создано соединение new, именно поэтому обычно вы видите
небольшие значения в счётчиках правила NAT.
6
И так когда пакет попал на маршрутизатор и соединение было "только только" создано, соединение
имело такой вид
0 SAC src-address=5.19.245.3:57839 dst-address=88.88.88.2:80
После того, как произошла процедура dst NAT, маршрутизатор добавил флаги и самое главное на какой
адрес изменяется IP адрес во всех пакетах в данном соединении.
0 SAC d src-address=5.19.245.3:57839 dst-address=88.88.88.2:80 reply-src-
address=172.20.18.2:80
Когда пакет уходил с маршрутизатора в цепочки postrouting работает процедура src NAT, но у нас нет
правил src NAT, оставили значение исходное.
0 SAC d src-address=5.19.245.3:57839 dst-address=88.88.88.2:80 reply-src-
address=172.20.18.2:80 reply-dst-address=5.19.245.3:57839
Обратите внимание, что все данные этапы были сделаны на момент прохождения только первого
пакета.
Тем самым src NAT на данном этапе работает автоматически на основании правил dst-NAT.
Например, VoIP телефония, ваш провайдер телефонии требует, чтобы вы регистрировались только с
определённого IP адреса, или банк клиент на компьютере главного бухгалтера должен подключаться с
определённого адреса.
Сначала настроим адрес листы в которые будем добавлять внутренние адреса хостов, которые
необходимо отправить через нужного провайдера и с определённого IP адреса.
[admin@MikroTik.Me] /ip firewall address-list
Адрес 0.0.0.1 для того чтобы создать лист, но не привязывать к реальному адресу.
Название листа явно говорит о том, на какой IP адрес необходимо изменить адрес источника.
Для реализации данного кейса нам необходимо учитывать особенность работы RouterOS.
Дело в том, что для трафика который проходит через маршрутизатор мы можем изменить таблицу
маршрутизации только в цепочке prerouting, и естественно исходящий интерфейс нам ещё не известен,
он будет известен только в цепочке forward.
Для решении данной задачи нам помогут BOGON сети, это список сетей, которые никогда не должны
использоваться для публикации между public AS в протоколе BGP, другими словами это все те сети,
которые используются исключительно в локальных целях.
А далее создадим правила для того, чтобы выпустить хосты с определённого IP адреса.
[admin@MikroTik.Me] /ip firewall mangle
Если пакет в адресе источника находится адрес, который перечислен в адрес листе и при этом адрес
назначения не попадает под BOGON листы (т.е трафик в интернет), отправить в именованную таблицу.
8
add chain=srcnat routing-mark=Next-Hop/44.44.44.1 src-address-list=via/44.44.44.2
action=src-nat to-addresses=44.44.44.2
Обратите внимание, что не весь трафик, а только тот, который находится в определённом
маркированном маршруте, это необходимо для того, чтобы трафик между локальными сетями не
попадал под NAT правило.
Наверное вы уже догадались, что весь оставшийся трафик от ваших локальных хостов будет попадать в
таблицу main.
Давайте сделаем маршрут ECMP с тем учётом, что шлюз 88.88.88.1 это 10Mbps, а 44.44.44.1 5Mbps.
[admin@MikroTik.Me] /ip route
Пакеты будут отправляться поочередно для каждого шлюза, на каждые 3 пакета, 2 пакету будут
отправлены в 88.88.88.1 и оставшийся один пакет на шлюз 44.44.44.1.
Хотя это немного и не правильно, дело в том, что у процесса ECMP есть отдельная таблица кеша, и
чтобы каждый раз не выбирать маршрут, маршрутизатор для связки src-address:port dst-address:port
создаёт хеш и выберет для данного хеша уже шлюз по схеме Round Robin, тем самым для одного
соединения будет выбираться один и тот же шлюз.
Но не все так однозначно, каждый раз, когда вы изменили маршрут, например добавили шлюз или
шлюз умер то кеш ECMP чистится, а также каждые 10 минут всё также чистится кеш, отсюда
появляется проблема, что каждые 10 минут может выбраться другой шлюз. И снова для каждого
уникального хеша будет выбираться маршрут.
Проблема в том, что ограничение в 10 минут, это ограничение жёсткое и нам его не убрать и не
изменить.
Давайте подумаем вместе, что нам известно о пакете, который попал под ECMP маршрут? Конечно,
данный пакет находится в таблице main.
Идея данного способа заключается в следующем. Дать маршрутизатору выбрать маршрут с помощью
ECMP, промаркировать такие соединения и все последующие пакеты в этом соединение пускать мимо
ECMP, тем самым мы убираем проблему 10 минут.
Делаем.
[admin@MikroTik.Me] /ip firewall mangle
9
add chain=postrouting routing-table=main out-interface=ether1 connection-state=new
action=mark-connection new-connection-mark=ECMP/ether1 passthrough=no
Давайте разберём.
chain=postrouting - Работаем в цепочке по факту того, что уже выбрал ECMP, можно использовать и
цепочку forward, но тогда не попадёт трафик который был сгенерирован самим маршрутизатором.
Ещё раз, мы дали возможность ECMP выбрать направление и мы уже по факту промаркировали
соединения, основываясь на выборе интерфейса.
А теперь все последующие пакеты в соединениях с такой маркировкой должны быть отправлены в тот
же интерфейс, но не в таблицу main, так как там работает ECMP, нам это уже не к чему.
Не забудьте, что трафик смотрится со всех сторон, а нам необходимо только трафик из локальной сети,
а так как интерфейсов может быть много, лучше всего отфильтровывать по принципу весь
трафик КРОМЕ того который пришёл с интерфейса провайдера.
[admin@MikroTik.Me] /ip firewall mangle
Почти всё.
10