У меня 2 провайдера, в нормальной ситуации трафик делится между ними по стоимости (одному - город, внешка - другому, у которого используется "сплошной" трафик). При падении одного из провов соответственно весь трафик "заворачивается" на второго.
Разделением трафика занимается отдельная машинка , у которой 2 входных интерфейса и 1 выходной.
Отдельный скрипт занимается слежением за состоянием сети, для чего периодически отправляются пинги на один и тот же адрес (точнее на 2 адреса - 1 в городской сети и второй во внешнке), используя для этого команду типа ping -S IP_проверяемого_интерфейса IP_которым проверяем
Кроме того, на интернет сервере крутится несколько сервисов (www, ftp, mail). Соответственно, на них может приходить коннект на любой из внешних адресов, и ответ должен быть с того же адреса.
схема отработана и крутится уже давно.
при необходимости сменить версию ОС на внешней машинке (с Freebsd 5.1 на минимум 5.4, в итоге - 6.0) столкнулся вот с чем...
итак, от нас нужно выпустить пакет.
от нас на адрес например 3.3.3.3
таблица маршрутов грубо такая :
route: городской_ип интерфейс1
route: default интерфейс2
3.3.3.3 - "внешка", то есть должен по правилам идти через интерфейс 2
если говорим просто "пинг" - то все ок...
НО - если мне надо этот пакет отправить НЕ с того интерфейса, который получается по таблице маршрутов, а с другого...
пишу ping -S IP_from_интерфейс1 3.3.3.3
и при этом у меня есть правила
ipfw add fwd гейт_интерфейса_1 ip from IP_интерфейса1 to any
ipfw add fwd гейт_интерфейса_2 ip from IP_интерфейса2 to any
так вот ...
на версии FreeBSD 5.1 (ранее - не пробовал!) fwd срабатывает правильно... пакет уходит с интерфейс1, хотя по таблице маршрутов это был бы другая сеть... Но раз он исходит ОТ адреса интерфейса1 - значит с него и идет
На версии 6.0 (на 5.3 - схема также не сработала, видимо и там также!)
пакет уходит ОТ АДРЕСА ИНТЕРФЕЙС1 НО!!!! с того интерфейса, с которого положено по таблице маршрутов... Ну и конечно не работает...
По ману на ipfw
fwd ipaddr
написано примерно так...
"если ipaddr не является локальным, то пакет перенаправляется в тот интерфейс, который положено по таблице маршрутов"... При этом явно не сказано, о каком ИП идет речь.. по логике - это речь о именно ipaddr а не адресе, для которого направлен пакет.. по факту - наоборот...
Стал копаться в ядре...
версия 5.1
файл /usr/src/sys/netinet/ip_fw.c, ip_fw2.c
обработка правил (точнее проверка) ведется одной функцией ipfw_check , где при обработке этого правила заменяется поле next_hop на новой значение... все правильно...
версия 6.0
файлы ip_fw_pfil.c и ip_fw2.c
внутри функции ipfw_check сначала определяется тип - ин или аут. потом вызывается
ipfw_check_out для исходящего пакета, которому как параметр ПЕРЕДАЕТСЯ ССЫЛКА НА ВЫХОДНОЙ ИНТЕРФЕЙС ДЛЯ ПАКЕТА, и замена next_hop на тот, что задан в правилах уже не оказывает влияния, если для нового адреса нужен другой интерфейс....
То есть в версиях 5.3 (не проверял, но настроеная схема на ней не сработала) - и старше правило
ipfw add fwd IP ip from ... to ... сработает ТОЛЬКО в том случае, если next_hop по умолчанию и навязываемый этим правилом доступны через один и тот же интерфейс....
Вот такая ошибочка...
Может кто подскажет как выйти из такой ситуации ?