Имеется локальная сеть офиса или удалённой технологической площадки, подключённая к двум поставщикам услуг. Требуется, чтобы при обращении к маршрутизатору из Интернет через того или другого поставщика ответ всегда уходил через этого же поставщика, с соответствующего порта и с IP-адресом источника, назначенным этому порту.
Задача не так проста, как кажется, и обычными средствами IP-маршрутизации не решается. Для этой цели приходится задействовать сразу несколько механизмов обработки IP-пакетов:
Схема стенда показана на рисунке. Одно из устройств изображает интернет и пользователя в нём. Другое — маршрутизатор офисной сети. При пинге с первого устройства с source-ip=172.16.0.1 на второе по адресам 192.168.1.2 и 10.0.23.2 ответ отправляется всегда с того же интерфейса, на который послан запрос.
Устройство "интернет":
port : eth0 : : adm-state = "up" : : ifAddress : : : prefix = "192.168.1.1/24" : eth1 : : ifAddress : : : prefix = "10.0.23.1/24" pseudo-interface : dummy0 : : ifAddress : : : prefix = "172.16.0.1/32"
Устройство "офис":
ip : route : : 1 : : : gateway = "192.168.1.1" : route-tables : : 1 : : : name = "ktab0" : : 2 : : : name = "ktab1" : dynamic-routing : : enable = true : : kernel : : : 1 : : : : device-routes = true : : : : export = "all" : : : : import = "none" : : : : kernel-table = 1 : : : : table = "btab0" : : : 2 : : : : device-routes = true : : : : export = "all" : : : : import = "none" : : : : kernel-table = 2 : : : : table = "btab1" : : static : : : 1 : : : : route : : : : : 172.16.0.1/32 : : : : : : action = "via-gateway" : : : : : : gateway = "192.168.1.1" : : : : table = "btab0" : : : 2 : : : : route : : : : : 172.16.0.1/32 : : : : : : action = "via-gateway" : : : : : : gateway = "10.0.23.1" : : : : table = "btab1" : : table : : : btab0 : : : : _keep = true : : : btab1 : : : : _keep = true : mangle : : INPUT : : : 1 : : : : in-interface = "eth0" : : : : target = "CONNMARK" : : : : connmark-params = "--set-mark 1" : : : 2 : : : : in-interface = "eth1" : : : : target = "CONNMARK" : : : : connmark-params = "--set-mark 2" : : OUTPUT : : : 1 : : : : target = "CONNMARK" : : : : connmark-params = "--restore-mark" : : : 2 : : : : explicit-matches : : : : : 1 : : : : : : match-type = "mark" : : : : : : mark = "! 0x0" : : : : target = "ACCEPT" : rule : : 1 : : : fwmark = 1 : : : table = "ktab0" : : 2 : : : fwmark = 2 : : : table = "ktab1" port : eth0 : : adm-state = "up" : : ifAddress : : : prefix = "192.168.1.2/24" : eth1 : : ifAddress : : : prefix = "10.0.23.2/24"
Дополнительные замечания:
Механизм динамической маршрутизации используется в данном случае для того, чтобы создать две дополнительные таблицы маршрутизации, помимо основной.
Шлюзом по умолчанию в основной таблице маршрутизации может быть любой из поставщиков услуг — как 192.168.1.1, так и 10.0.23.1. Этот маршрут необходим только для формальной маршрутизации исходящих на первом этапе, т.е. непосредственно после их попадания из приложения в сетевой стек. На этом этапе они ещё не имеют метки и, соответственно, не подпадают ни под одно из двух правил маршрутизации. Важен сам факт, что пакеты прошли на следующий левел этого гейма, выбранный маршрут не имеет значения. После него пакеты попадают в таблицу ip.mangle.OUTPUT и только там получают нужную метку. После этого выполняется второй этап маршрутизации, уже с учётом этой метки.