У меня есть многосетевые установки с двумя вышестоящими провайдерами. И я хочу ограничить некоторые соединения использованием только одного провайдера - то есть локальных исходящих соединений. Итак, я создал настраиваемую таблицу маршрутизации, которая имеет прямой сетевой маршрут и маршрут по умолчанию:
$ ip route show table 2
default via 5.1.0.1 dev upstream_b
5.1.0.0/16 dev upstream_b scope link src 5.1.0.2
Затем я использую селектор в iptables, чтобы добавить fwmark к некоторым соединениям и ip-rule, чтобы переопределить выбор таблицы маршрутизации:
# for output traffic
# restore packet mark from connection mark
iptables --table mangle --append OUTPUT -j CONNMARK --restore-mark
# for !0 packet marks bail out
iptables --table mangle --append OUTPUT -m mark ! --mark 0 -j ACCEPT
# set packet mark
iptables --table mangle --append OUTPUT -m cgroup --cgroup 0x00010002 -j MARK --set-mark 0x2
# save packet mark to connection mark
iptables --table mangle --append OUTPUT -j CONNMARK --save-mark
# for input traffic restoring mark from connmark
iptables --table mangle --append PREROUTING -j CONNMARK --restore-mark
# adding policy forwarding
ip rule add from all fwmark 2 table 2
Итак, для некоторого процесса [в указанном net_cls
cgroup] его исходящие соединения попадут в правило отметки соединения и затем должны быть маршрутизированы через upstream_b
интерфейс.
Но это не работает (для оболочки bash, которая была помещена в контрольную группу net_cls):
$ curl --resolve ifconfig.co:80:188.113.88.193 -v http://ifconfig.co
* Added ifconfig.co:80:188.113.88.193 to DNS cache
* Rebuilt URL to: http://ifconfig.co/
* Hostname ifconfig.co was found in DNS cache
* Trying 188.113.88.193...
* Immediate connect fail for 188.113.88.193: Network is unreachable
* Closing connection 0
curl: (7) Couldn't connect to server
Предыдущий результат имел место, пока main
таблица маршрутизации не имеет маршрута по умолчанию (т.е. нет маршрута к ifconfig.co).
Но это еще не все. Поскольку у меня есть многосетевые настройки, обычно существует маршрут ECMP для балансировки трафика через обоих провайдеров. И по упомянутому тесту я получил интересный результат. Пакеты tcp-syn перешли на правильный интерфейс, но с неправильным исходным адресом (из другого интерфейса).
Итак, объединяя эти наблюдения, во-первых, решение о маршрутизации принимается на основе main
таблица маршрутизации (таким образом, сеть недоступна). Затем, пока пакет обрабатывается дальше, он попадает в правила маркировки, а затем происходит перенаправление (на основе пользовательской таблицы маршрутизации). Но исходный адрес уже задан в первом решении о маршрутизации и здесь не исправляется.
Правильно ли я понимаю происхождение проблемы?
Мне нужно установить нестандартную таблицу маршрутизации для некоторых локальных процессов, а указанный выше метод не работает. Можно ли было осуществить принудительное исполнение? Например, можно ли запустить пересчет адреса источника?
РЕДАКТИРОВАТЬ. Учитывая следующую диаграмму (версия ядра здесь не такая современная, но все же полезная; диаграмма взята из http://open-source.arkoon.net/kernel/kernel_net.png):
Кажется, что первое решение о маршрутизации и выбор исходного адреса пакета действительно выполняются до того, как сработает какое-либо правило iptables (см. Правый нижний угол).