У меня 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 по умолчанию и навязываемый этим правилом доступны через один и тот же интерфейс....Вот такая ошибочка...
Может кто подскажет как выйти из такой ситуации ?
Проблема решилась путем правки исходников...файл
/usr/src/sys/netinet/ip_fastwrd.cстрока 477 (FreeBSD 6.0)
if (fwd_tag) {
if (!in_localip(ip->ip_src) && !in_localaddr(ip->ip_dst))
dest.s_addr = ((struct sockaddr_in *)(fwd_tag+1))->sin_addr.s_addr;
m_tag_delete(m, fwd_tag);
}/usr/src/sys/netinet/ip_output.c
строка 714
аналогично...что говорит о том, что новой next_hop будет расчитываться ТОЛЬКО если оба и адрес на который будет делаться forward и ИСХОДЯЩИЙ адрес НЕ являются локальными...
То есть в моей ситуации, когда на МОЕЙ машине 2 внешних ИП адреса - никогда не выполняется...
Из условия надо удалить "!in_local(ip->ip_src) &&" - ну и пересобрать ядро...
После этого FORWARD начинает работать так, как указано в документации
>/usr/src/sys/netinet/ip_fastwrd.c
сорри, имелось в виду
/usr/src/sys/netinet/ip_fastfwd.c
>Может кто подскажет как выйти из такой ситуации ?Добавить в конфиг ядра IPFIREWALL_FORWARD_EXTENDED.
>>Может кто подскажет как выйти из такой ситуации ?
>
>Добавить в конфиг ядра IPFIREWALL_FORWARD_EXTENDED.
Дык - добавлено.... ессно...результат - описан выше...
После удаления !in_localip(ip->src) заработало именно так, как обещала документация...
без удаления - не работает (да и немудрено... ip->src - он как раз локальный, факт)
>>>Может кто подскажет как выйти из такой ситуации ?
>>
>>Добавить в конфиг ядра IPFIREWALL_FORWARD_EXTENDED.
>
>
>Дык - добавлено.... ессно...
>
>результат - описан выше...
>
>После удаления !in_localip(ip->src) заработало именно так, как обещала документация...
>без удаления - не работает (да и немудрено... ip->src - он как раз локальный, факт)
http://www.freebsd.org/cgi/cvsweb.cgi/src/sys/netinet/ip_fas...