Категорії
FreeBSD Routers, GW, Internet

[pf] Несколько ppp сессий и reply-to из PF

В этой статье хочу рассказать, как заставить работать одновременно 2 канала, каждый из которых поднимается через ppp на примере USB модемов.

Огромный нюанс заключается в том, что мы наперёд не знаем IP-адреса шлюзов для ppp-сессий. Но это нам не помешает правильно реализовать задуманное.

Тестовый стенд: FreeBSD 8.2 i386, USB модемы Novatel U720, AnyData ADU-500.

1) Подготовка модемов.

Для того, что бы можно было работать с модемами, достаточно драйвера u3g, который уже присутствует в ядре GENERIC.

Послу подключения модемов, они у вас должны определиться, как показано ниже:

# usbconfig | grep CDMA
ugen0.2: <AnyDATA CDMA Products AnyDATA Corporation> at usbus0, cfg=0 md=HOST spd=FULL (12Mbps) pwr=ON
ugen1.2: <Novatel Wireless CDMA Novatel Wireless Inc.> at usbus1, cfg=0 md=HOST spd=FULL (12Mbps) pwr=ON

Если у вас не видятся модемы, возможно требуется загрузить дополнительные драйвера, информацию о которых можно найти в статьях через Поиск на сайте по ключевому слову USB.

2) Настройка ppp.

Вот пример конфигурационного файла ppp.conf (напомню, что все строки, кроме itc и mts начинаются с отступов):

itc:
ident user-ppp VERSION (built COMPILATIONDATE)
set log PHase Chat LCP IPCP CCP tun command
set device /dev/cuaU4.0
set phone "#777"
set dial "ABORT BUSY ABORT NO\\sCARRIER TIMEOUT 5 \"\" AT OK-AT-OK ATE1Q0s7=60 OK \\dATDT\\T TIMEOUT 40 CONNECT"
set login
set timeout 0
set authname "IT"
set authkey "IT"
add default HISADDR
disable ipv6cp

mts:
set log Phase Chat LCP IPCP CCP tun command
ident user-ppp VERSION (built COMPILATIONDATE)
set device /dev/cuaU0.0
set speed 115200
set ctsrts off
set phone "#777"
set dial "ABORT BUSY ABORT NO\\sCARRIER TIMEOUT 5 \"\" AT OK-AT-OK ATE1Q0 OK \\dATD\\T TIMEOUT 40 CONNECT"
set login
set timeout 0
set authname "mobile"
set authkey "internet"
set ifaddr 0.0.0.0/0 0.0.0.0/0 0.0.0.0/0
#  add default HISADDR
set ipcpretries 10 5
disable ipv6cp

Теперь перейдём к файлу ppp.linkup. Этот файл используется для возможности выполнять определённые действия при поднятии/опускании ppp-соединения. Формат похож на ppp.conf. Добавим в него такие строки (строки начинающиеся с ! должны иметь отступы):

itc:
!bg /etc/pf-anchor.sh itc INTERFACE HISADDR

mts:
!bg /etc/pf-anchor.sh mts INTERFACE HISADDR

Которые собственно означают, что при поднятии соответствующего соединения запускать указанный скрипт с нужными параметрами.

Точно так же можно создать файл ppp.linkdown.

Примечание.

Обратите внимание на строки set device. У вас они могут отличаться и самое главное выяснить, какому модему отвечает какое устройство. Я нашёл соответствие экспериментальным путём.

Осталось добавить строки в /etc/rc.conf для запуска демона ppp. Они выглядят так:

ppp_enable="YES"
ppp_mode="ddial"
ppp_nat="NO"
ppp_profile="itc mts"
ppp_user="root"

Примечание.

Здесь могут быть нюансы в том плане, что перечислять “профили” нужно именно в таком порядке. В другом порядке поднимался только 1 модем.

3) Настройка PF.

Файл с правилами /etc/pf.rules содержит такие строки (я пока рассматриваю самый простой вариант):

nat-anchor itc
nat-anchor mts

anchor itc
anchor mts

Теперь создадим файл я правилами, которые будут применяться для каждого якоря (/etc/pf-anchor.conf):

nat on $ext_if from 10.1.0.0/24 to any -> ($ext_if)
pass in on $ext_if reply-to ($ext_if $gw) from any to ($ext_if) keep state

Здесь тоже всё просто: правило для NAT’a и правило для пакетов, что бы шли туда, откуда пришли, а не через таблицу маршрутизации.

Ну и завершающий этап – создание скрипта для применения правил (/etc/pf-anchor.sh):

#!/bin/sh

anchor=$1
ext_if=$2
gw=$3

pf_config="/etc/pf-anchor.conf"
pf="/sbin/pfctl"

$pf -a $anchor -Fa
$pf -a $anchor -D ext_if=$ext_if -D gw=$gw -f $pf_config

Не забудьте сделать скрипт исполняемым!

Объяснять здесь нечего, кроме последней строки – тут мы собственно передаём переменные для якоря, которые потом в зависимости от того, какая сессия ppp их вызвала трансформируются в соответствующие правила.

Примечание.

Можно обойтись и без использования якорей. Для этого можно использовать такие правила:

pass in on $int2 reply-to ($int2 $int2:peer) from any to ($int2) keep state
pass in on $int1 reply-to ($int1 $int1:peer) from any to ($int1) keep state

но тогда вы можете столкнутся с тем, что правила применяться раньше, чем поднимутся интерфейсы tun0/tun1.

4) Проверка работы.

После поднятия сессий мы увидим такое:

srv-test# ifconfig tun0
tun0: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> metric 0 mtu 1500
options=80000<LINKSTATE>
inet 195.128.XX.XX --> 195.128.XX.XX netmask 0xffffffff
Opened by PID 456
srv-test# ifconfig tun1
tun1: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> metric 0 mtu 1500
options=80000<LINKSTATE>
inet 77.52.YY.YY --> 80.255.YY.YY netmask 0xffffffff
Opened by PID 465

Смотрим теперь правила:

srv-test# pfctl -a '*' -sr
anchor "itc" all {
pass in on tun0 reply-to (tun0 195.128.XX.XX) inet from any to (tun0) flags S/SA keep state
}
anchor "mts" all {
pass in on tun1 reply-to (tun1 80.255.YY.YY) inet from any to (tun1) flags S/SA keep state
}

Замечу, что если бы мы использовали просто pf -sr, увидели бы следующее:

anchor "itc" all
anchor "mts" all

Тоже самое касается и правил трансляции:

srv-test# pfctl -a 'itc' -sn
nat on tun0 inet from 10.1.0.0/24 to any -> (tun0) round-robin
srv-test# pfctl -a 'mts' -sn
nat on tun1 inet from 10.1.0.0/24 to any -> (tun1) round-robin

5) Нюансы

Для UDP приложению, которое слушает “любой IP” (*:port), нельзя выяснить,
на который именно IP пришел запрос, поэтому нельзя ответить с него.

bind (и ntpd и другие) обходят эту проблему, создавая по отдельному сокету
для каждого IP и принимая запросы в разные сокеты.

Что это значит? А то, что, если вы к примеру, повесите на * демон openvpn’a, то ответные пакеты не будут уходить на НЕ default route. Как выходить из такого? Вешать по отдельному демону на каждый такой интерфейс, который НЕ смотрит на default route.

4 коментарі “[pf] Несколько ppp сессий и reply-to из PF”

freebsd 8.2 , работают два модема U720 и U760 от Интертелеком, сегодня с утра оба получают один и тот же IP адрес на стороне провайдера. Соответственно имеем в ppp.log:
tun1: IPCP: myaddr 93.180.XX.XX hisaddr = 195.128.182.33
tun1: Warning: iface add: ioctl(SIOCAIFADDR, 93.180.XX.XX -> 195.128.182.33): File exists
tun1: Error: ipcp_InterfaceUp: unable to set ip address
как бы так сделать, что бы работало? Спасибо.

Только обращаться в ИнтерТелеком, так как модемы должны получать разные IP. Может слетели настройки? Кстати, они у себя там пару месяцев назад меняли частоты и из-за этого у меня часть модемов не работала. Отвёз им, перепрошили, сейчас вроде бы нормально работают.
Ещё как вариант, попробуй вставить в разные компы и проверить, получат ли в этом случае один и тот же адрес. Или как вариант по отдельности их включить.

Хм, проблема была в попытке ppp добавить в маршруты, повторно один и тот же адрес шлюза провайдера. Решил добавлением в ppp.linkup
route delete 195.128.182.33
криво но работает 🙂

Залишити відповідь

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *

Домашняя страничка Andy
Записки молодого админа
Самостоятельная подготовка к Cisco CCNA
Самостоятельная подготовка к Cisco CCNP
Powered by Muff