URL: https://www.opennet.ru/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID1
Нить номер: 65678
[ Назад ]

Исходное сообщение
"ip forwarding - ошибка в реализации FreeBSD > 5.1 ?"

Отправлено vadimcj , 16-Апр-06 20:43 
У меня 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 по умолчанию и навязываемый этим правилом доступны через один и тот же интерфейс....

Вот такая ошибочка...

Может кто подскажет как выйти из такой ситуации ?


Содержание

Сообщения в этом обсуждении
"ip forwarding - ошибка в реализации FreeBSD > 5.1 ?"
Отправлено vadimcj , 16-Апр-06 23:23 
Проблема решилась путем правки исходников...

файл
/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 начинает работать так, как указано в документации


"ip forwarding - ошибка в реализации FreeBSD > 5.1 ?"
Отправлено vadimcj , 17-Апр-06 00:38 
>/usr/src/sys/netinet/ip_fastwrd.c
сорри, имелось в виду
/usr/src/sys/netinet/ip_fastfwd.c

"ip forwarding - ошибка в реализации FreeBSD > 5.1 ?"
Отправлено butcher , 16-Апр-06 23:41 
>Может кто подскажет как выйти из такой ситуации ?

Добавить в конфиг ядра IPFIREWALL_FORWARD_EXTENDED.


"ip forwarding - ошибка в реализации FreeBSD > 5.1 ?"
Отправлено vadimcj , 17-Апр-06 00:22 
>>Может кто подскажет как выйти из такой ситуации ?
>
>Добавить в конфиг ядра IPFIREWALL_FORWARD_EXTENDED.


Дык - добавлено.... ессно...

результат - описан выше...

После удаления !in_localip(ip->src) заработало именно так, как обещала документация...
без удаления - не работает (да и немудрено... ip->src - он как раз локальный, факт)


"ip forwarding - ошибка в реализации FreeBSD > 5.1 ?"
Отправлено 225206207206201205 , 18-Апр-06 13:23 
>>>Может кто подскажет как выйти из такой ситуации ?
>>
>>Добавить в конфиг ядра IPFIREWALL_FORWARD_EXTENDED.
>
>
>Дык - добавлено.... ессно...
>
>результат - описан выше...
>
>После удаления !in_localip(ip->src) заработало именно так, как обещала документация...
>без удаления - не работает (да и немудрено... ip->src - он как раз локальный, факт)


http://www.freebsd.org/cgi/cvsweb.cgi/src/sys/netinet/ip_fas...