klink0v (klink0v) wrote,
klink0v
klink0v

Странная "недоделка" в линуксовом policy-based routing

Столкнулся с одной очень странной багофичей в линуксовом ядре.

Допустим, имеется multihome-машина (т.е. на борту несколько сетевых интерфейсов с разными IP-адресами). Допустим, на неё навешена какая-то до фига хитрозадая система маршрутизации IPv4-пакетов. Например, source routing, либо по меткам (fwmark), либо ещё как-то. Допустим, некое приложение, работающее на этой машине хочет послать IP-пакет "в мир".

Перед ядром системы при этом возникает две независимые задачи.


  1. Выбрать Source IP для пакета (очевидно, это поле надо чем-то заполнить).

  2. Выбрать маршрут для этого пакета (куда бы его покошернее запульнуть).

В простейшем случае при использовании одного только Destination-based routing обе эти задачи решаются легко и приятно обычным просмотром правил и таблиц маршрутизации. Находим в таблицах нечто наиболее подходящее под Destination IP нашего пакета, берём оттуда Gateway, там же рядом видим "scope link" и подставляем соответствующий этому линку Source IP. (Лирическое отступление: все желающие могут от рута дать на линуксе команду "ip route show" и сразу поймут о чём это я толкую).

Но что если у нас что-то более сложное? Source-based routing, например, или вообще fwmark-и? Тогда приложение должно явно указать, на какой IP оно хочет заBINDиться. Большинство более-менее нормально написанных софтин это умеют. И даже банальный "ping" имеет ключик "-I", который как раз для этого и предназначен. То есть в данном случае никаких проблем вроде как и нет.

Окей, едем дальше. А что если пакет генерируется не приложением, а самим ядром? Например, icmp echo reply или TCP RST, а может быть icmp fragmentation needed? Каким образом ядро допетрит какой Source IP в такой пакет вкорячить, а? Особенно если в таблице "main" нет маршрута на "0.0.0.0/0"?

Правильный ответ: никак.

То есть в случае с echo reply ещё всё более-менее понятно: можно использовать source routing по принципу "куда пришло - оттуда и отправляй". Но если мы хотим использовать не source routing, а iptables + fwmark, то тут уже наступает большой облом. Потому что поле Source IP должно быть заполнено до того, как в работу включится механизм маршрутизации по меткам.

В случае же с icmp fragmentation needed дела обстоят ещё более грустно. Потому что тут даже source routing применить не получится: шлюз-то транзитный. И даже параметр ядра "net.ipv4.fwmark_reflect=1" нам абсолютно ничем не поможет. Ну и что с того, что на пакете будет метка? Source IP прямо здесь и сейчас мы всё равно можем выбрать только исходя из destination IP. А если пресловутый fragmentation needed нам нужно отдать в "большой интернет" не абы как, а через какого-то строго определённого провайдера в зависимости от конкретной ситуации? Упс, задача не решается. Точнее, решается, но адовыми костылями с применением SRC NAT.

Вот я и не могу понять.


  1. Как мы жили до сих пор? Почему на эту багофичу за столько лет никто не обратил внимания и не пофиксил её?

  2. Каким образом подобная трудность преодолевается в тех же цисках, жуниперах и прочем "профессиональном" сетевом оборудовании? Есть ли там аналогичные затыки, или всё таки как-то предусмотрено и продумано?

Линуксоиды, welcome к обсуждению.
Tags: linux, администрирование, вопрос, сети
Subscribe
  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

  • 4 comments