В продолжении статьи (http://skeletor.org.ua/?p=1263) про reply-to захотелось найти решение для ipfw. Тестовый стенд такой же, настройки те же. Отличия я опишу отдельно.
1) Настройка ppp.
Изменения коснутся лишь файла /etc/ppp/ppp.linkup. Вот как он будет выглядеть для ipfw (естественно, все строки !bg с отступами):
itc:
!bg ipfw add 100 skipto 300 tag 1 ip from any to any in recv INTERFACE keep-state
!bg ipfw add 400 fwd HISADDR ip from any to any tagged 1
mts:
!bg ipfw add 200 skipto 300 tag 2 ip from any to any in recv INTERFACE keep-state
!bg ipfw add 500 fwd HISADDR ip from any to any tagged 2
2) Подготовка ipfw
Для того, что бы можно было использовать в ipfw аналог reply-to нужно сделать такие вещи:
– пересобрать ядро с поддержкой fwd (options IPFIREWALL_FORWARD)
– пропатчить код ipfw
С первым пунктом всё понятно. А вот второй пункт разберём подробно. Об этом можно прочесть здесь (http://www.freebsd.org/cgi/query-pr.cgi?pr=147720). Собственно сам патч можно взять оттуда.
3) Правила ipfw
В файл с правилами нужно добавить такие строки:
ext_if1="tun0"
ext_if2="tun1"
int_if="age0"
ipfw -f flush
ipfw add 10 check-state
ipfw add 300 allow { recv $ext_if1 or recv $ext_if2 }
ipfw add 400 allow in recv $int_if
4) Проверка работы
Собственно можно посмотреть счётчики:
# ipfw show
00010 0 0 check-state
00100 6477 1059256 skipto 300 tag 1 ip from any to any in recv tun0 keep-state
00200 1457 88615 skipto 300 tag 2 ip from any to any in recv tun1 keep-state
00300 7526 1492475 allow ip from any to any { recv tun0 or recv tun1 }
00400 9403 1219630 allow ip from any to any in recv age0
00400 3001 302297 fwd 195.128.XX.XX ip from any to any tagged 1
00500 786 45680 fwd 80.255.YY.YY ip from any to any tagged 2
65535 3005 426678 allow ip from any to any
5) Благодарности.
Огромное спасибо хочу выразить Вадиму Гончарову за помощь с патчами и советами. Подробно про работу reply-to можно прочесть по адресу http://nuclight.livejournal.com/124348.html
6) Ложка дёгтя.
В процессе тестирования одновременной работы 2-х каналов столкнулся с такими проблемами.
На некоторых серверах всё нормально работает, даже без тех динамических правил, которые у в статье Вадима Гончарова, то есть просто оставляете обычный набор правил. На остальных наблюдаются такого рода проблемы: перестаёт работать VPN(pptp) подключение. В качестве VPN’a используется mpd, тип подключения – pptp. То есть подключение происходит, но вот трафик я так понял неправильно маршрутизируется.
Опишу что получилось:
– FreeBSD 8.1 amd64 (VPN server), 2 белых внешний IP – не заработал VPN
– FreeBSD 8.2 i386 (VPN client) , 1 белый внешний IP, 1 серый (но настроены пробросы портов) – нет подключения по второму каналу (там где сервый IP)
– FreeBSD 8.1 i386 (VPN client), 2 белый внешних IP – всё заработало даже без динамических правил.
– FreeBSD 8.2 i386 (VPN client), 1 белый внешний IP, 1 серый (но настроены пробросы портов) – подключение по второму каналу есть, но не работает VPN.
Подведя итог скажу: правильнее конечно же использовать динамические правила, но если с ними у вас не заработало – попробуйте без них. Так же могут быть проблемы, если один из каналов у вас имеет серый IP.
7) Новинки.
Начиная с 8.2 появилась возможность использовать global_port (nat global). Приведу цитату с одного форума:
Теперь при нескольких каналах и балансировке трафика между ними, маршрутизацию от источника можно будет делать не через злоипучие keep-state, а просто перенаправляя трафик на globalport. Так как таблица у нескольких экземпляров будет общей, то в ней и будет храниться соответствие.
Очень подробно о global nat описано здесь
8 ) Нюансы
Для UDP приложению, которое слушает “любой IP” (*:port), нельзя выяснить,
на который именно IP пришел запрос, поэтому нельзя ответить с него.bind (и ntpd и другие) обходят эту проблему, создавая по отдельному сокету
для каждого IP и принимая запросы в разные сокеты.
Что это значит? А то, что, если вы к примеру, повесите на * демон openvpn’a, то ответные пакеты не будут уходить на НЕ default route. Как выходить из такого? Вешать по отдельному демону на каждый такой интерфейс, который НЕ смотрит на default route.