воскресенье, 22 февраля 2009 г.

Настройка PPPoE-сервера в Debian

Продолжаю тему пакета RP-PPPoE. На этот раз я решил настроить PPPoE-сервер из этого пакета. PPPoE-сервер, как и клиент, может работать в двух режимах: в режиме ядра и в пространстве пользователя.

Но прежде чем перейти к описанию настройки сервера, опишу настройки клиента. И клиент и сервер находятся в пакете pppoe Debian. Таким образом установка сервера и клиента весьма просты:
# aptitude install pppoe
1. Настройка тестового PPPoE-клиента

Клиент настраивался в режиме ядра, маршрут по-умолчанию не устанавливался, номер создаваемого интерфейса был прописан постоянным - 2.

Ниже - содержимое файла /etc/ppp/peers/dsl-provider, содержащий настройки тестового клиента:
user test
plugin rp-pppoe.so
eth1
noipdefault
usepeerdns
persist
noauth
#defaultroute
unit 2
Для пользователя test в файл /etc/ppp/chap-secrets добавим такую строчку:
test            *               testpasswd      *
На этом настройка клиента закончена. После того, как будет настроен сервер, мы установим подключение при помощи команды:
# pon dsl-provider
2. Настройка PPPoE-сервера в пространстве пользователя

Тут особых сложностей тоже не возникло. В файле /etc/ppp/pppoe-server-options были прописаны следующие опции:
auth
require-chap
ms-dns 81.30.199.5
ms-dns 81.30.199.94
noipdefault
noipx
nodefaultroute
noproxyarp
netmask 255.255.255.255
logfile /var/log/pppoe-server.log
Опция auth заставляет потребовать у удалённого клиента аутентификации, опция require-chap указывает способ аутентификации CHAP.

Опции ms-dns передают клиенту IP-адреса DNS-серверов, которые клиент воспринимает если в его настройках указазана опция usepeerdns.

Опция noipdefault не позвояет соглашаться с настройками IP-адресов, полученных от клиента, noipx отключает согласование протокола IPX, nodefaultroute запрещает добавлять маршрут по умолчанию через клиента, noproxyarp запрещает серверу создавать для клиентов ARP-записи на Ethernet-интерфейсах (эта опция нужна только если клиентам выдаются IP-адреса, пересекающиеся с IP-адресами Ethernet-сети, чтобы PPPoE-клиенты и компьютеры в локальной сети могли беспрепятственно обмениваться трафиком).

Опция "netmask 255.255.255.255" задаёт маску PPP-соединения у клиента и сервера, опция "
logfile /var/log/pppoe-server.log" предписывает вести серверу журнал. Пользы от этого журнала не очень много, т.к. в нём нет отметок времени.

По-умолчанию сервер передаёт в pppd также ещё и следующие опции: nodetach, noaccomp, nobsdcomp, nodeflate, nopcomp, novj, novjccomp, default-asyncmap.

Все опции по-умолчанию имеют приоритет над опциями из файла /etc/ppp/pppoe-server-options. Все опции, кроме первой и последней, отключают различные виды сжатия. Первая и последняя опции, на мой взгляд, спорные. Первая указывает pppd не отделяться от управляющего терминала. Какой может быть управляющий терминал, если pppd запущен из демона, то есть из программы, которая сама не имеет управляющего терминала? Последняя опция предписывает pppd не согласовывать параметр asyncmap и принудительно экранировать все управляющие символы, что не имеет особого смысла, поскольку Ethernet-среда ни коим образом не интерпретирует управляющие символы. Возможно эта опция предназначена для DSL-линии. Она, будучи последовательной линией, может использовать асинхронный режим приёма/передачи, в котором приёмник сообщает передатчику о готовности или неготовности к приёму информации с помощью специальных символов XON или XOFF.

Заведём тестового пользователя в файле /etc/ppp/chap-secrets на PPPoE-сервере, добавив строчку:
test            *               testpasswd              192.168.0.2
Последнее поле сообщает IP-адрес, который будет назначен этому клиенту в случае успешной аутентификации.

Теперь запустим сервер. У сервера есть несколько важных опций:
-I - задаёт имя интерфейса, на котором сервер будет ожидать соединений,
-L - задаёт собственный IP-адрес сервера внутри канала PPP,
-p - позволяет задать файл, содержащий список IP-адресов, выдаваемых клиентам внутри канала PPP,
-O - позволяет задать другой файл вместо используемого по умолчанию /etc/ppp/pppoe-server-options,
-N - позволяет указать максимальное количество одновременных соединений, по умолчанию 64.
Я запустил так:
# pppoe-server -I eth1 -L 192.168.0.1
Сервер запускается и переходит в фоновый режим. После этого запускаем на другом компьютере PPPoE-клиента:
# pon dsl-provider
Связь успешно установилась и на клиенте был создан интерфейс ppp2 с IP-адресами 192.168.0.2 и 192.168.0.1, на на сервере был создан интерфейс ppp0 с IP-адресами 192.168.0.1 и 192.168.0.2.
Теперь можно проверить работу связи. Для этого я на клиенте запустил команду:
$ ping -S 192.168.0.2 192.168.0.1
А на сервере запустил команду:
# tcpdump -i ppp0
Можно было увидеть, что клиент получает от сервера отклики на эхо-запросы, а сервер принимает и отправляет ICMP-сообщения "echo request" и "echo reply".

3. Настройка PPPoE-сервера в режиме ядра

Здесь, казалось бы, всё просто: добавляем серверу опцию -k и вперёд, но оказалось всё не так просто. В Debian pppoe-server собран без поддержки режима ядра и наотрез отказывается принимать опцию -k. Я решил собрать pppoe самостоятельно из deb-src. Направление для мыслей задал вот этот багрепорт: #298185 - pppoe-server: invalid option -- k - Debian Bug report logs. После долгого процесса копания по опциям получилось такое mini-how-to:

Устанавливаем зависимости для построения pppoe:
# apt-get build-dep pppoe
Скачиваем и распаковываем в текущий каталог исходники:
# apt-get source pppoe
Переходим в каталог rp-pppoe-3.8/src и выполняем конфигурирование:
# cd rp-pppoe-3.8/src
# ./configure
Теперь в только что созданном файле config.h нужно заменить строчку
/* #undef HAVE_LINUX_KERNEL_PPPOE */
на строчку
#define HAVE_LINUX_KERNEL_PPPOE 1
Теперь выходим из каталога src и выполняем сборку, указав путь к плагину rp-pppoe.so, который как раз и реализует поддержку PPPoE-сеансов на уровне ядра:
# cd ..
# ./debian/rules PLUGIN_PATH=/usr/lib/pppd/2.4.4/rp-pppoe.so
Собираем пакет и устанавливаем его:
# ./debian/rules binary
# cd ..
# dpkg -i pppoe_3.8-3_i386.deb
Заморозим пакет в системе, чтобы предотвратить его автоматическое обновление:
# echo pppoe hold | dpkg --set-selections
С этого момента нужно как минимум при каждом обновлении системы просматривать список обновлений. Если для pppoe будет выпущено обновление, закрывающее уязвимость, необходимо будет собрать пакет из свежих исходников заново, снять фиксацию пакета в системе с помощью команды:
# echo pppoe install | dpkg --set-selections
Затем заменить пакет новым и заново зафиксировать. Всё это - неизбежная плата за использование самосборного пакета. Конечно можно автоматизировать пересборку пакета, написав shell-скрипт, запускающий в нужной последовательности все указанные команды и заменяющий нужную строчку с помощью sed.

Так или иначе, теперь в системе установлен пакет с PPPoE-сервером, позволяющим поддерживать PPPoE-соединения на уровне ядра. Для запуска сервера в этом режиме, к команде описанной в предыдущем разделе нужно добавить опцию -k:
# pppoe-server -I eth1 -L 192.168.0.1 -k
Можно проверить связь так же, как это было описано выше, у меня всё заработало.

Осталось написать стартовые скрипты для запуска PPPoE-сервера и добавить их в систему.

18 комментариев:

Анонимный комментирует...

Опечатка у Вас.
./debina/rules PLUGIN_PATH=/usr/lib/pppd/2.4.4/rp-pppoe.so
а надо
./debian/rules PLUGIN_PATH=/usr/lib/pppd/2.4.4/rp-pppoe.so
А вообще, спасибо за статью. И правда жалко что по-умолчанию ни конфигов, ни скриптов, да еще и kernel-mode отключен.

morbo комментирует...

Спасибо, опечатку поправил.

В каждой бочке мёда обычно бывает капля дёгтя. Но мёд всё равно рулит и педалит :)

Анонимный комментирует...

Отличная заметка. Спасибо!

Анонимный комментирует...

Спасибо.

Анонимный комментирует...

а как быть если нужно слушать несколько vlan eth0.340 eth0.341 и т.п. , при запуске pppoe-server -I eth0 не работает.

morbo комментирует...

>а как быть если нужно слушать несколько vlan eth0.340 eth0.341 и т.п. , при запуске pppoe-server -I eth0 не работает.

pppoe-server -I eth0.340 -I eth0.341

Анонимный комментирует...

как сделать что бы в файл
radattr.pppX
добавить атрибуты

calling-station-id
и login абонента

----
в логах
peer from calling number 00:23:8B:9D:EE:A9 authorized

rcvd [CHAP Response id=0xa7 <4382489dfe58b111431d287b0f77f37b>, name = "rein"]

Анонимный комментирует...

вроде запостил комментарий , а что то его нет.

хочу увидеть в radattr.pppX
mac клиента
в режиме debug в логе он есть
peer from calling number 00:13:D4:4A:09:14 authorized

и логин туда бы добавить
rcvd [CHAP Response id=0xf1 <94203413e3c701c234bb8361c738e8fb>, name = "xaritonov"]

morbo комментирует...

MAC-адрес клиента может знать только pppoe-server. И то, не факт что он не поддельный и пришёл не от pppoe-proxy.

Скорее всего в сислог информацию пишет именно pppoe-server.

Логин абонента можно узнать в скрипте /etc/ppp/ip-auth.

Если этого недостаточно - тогда могу посоветовать только лезть в исходники пакета rp-pppoe.

Анонимный комментирует...

в логи пишет pppoe-server

в настройках pppoe-server-options
указано
logfile /var/log/pppoe-server.log
debug

в radattr.pppx есть только

Service-Type Framed-User
Framed-Protocol PPP
Framed-IP-Address 192.168.11.18
Framed-IP-Netmask 255.255.255.255 Session-Timeout 86400
Acct-Interim-Interval 61 PPPD-Upstream-Speed-Limit 4600
PPPD-Downstream-Speed-Limit 4600

Alexey Osipov комментирует...

Спасибо за инструкцию. :)

Выложил пересобранный пакетик в PPA: https://launchpad.net/~lion-simba/+archive/fixes

Анонимный комментирует...

Спасибо за статью, всё грамотно и доходчиво))
Есть вопрос: как можно решить проблему подвисшей сессии? т.е. когда пропадает физика и сессия рвётся, интерфейс ppp0 на сервере не пропадает... и при повторном соединении (после восстановления физики) подключение устанавливается, но пакеты не идут пока не сделаешь ррр0 down/up на сервере.

Анонимный комментирует...

извините, вопрос касался другой статьи:
http://vladimir-stupin.blogspot.com/2009/02/pppoe-debian.html

morbo комментирует...

С подобной проблемой не сталкивался.

По логике - нужно настроить таймаут PPPoE.

Попробуйте к строчке запуска PPPoE-сервера добавить опцию -T:

pppoe-server -I eth1 -L 192.168.0.1 -k -T 60

Это таймаут в минуту. В комментариях к этой опции написано, что нужно настроить опцию lcp-echo-interval на значение в 4 раза меньшее, чем то, что указано в -T.

В комментариях к опции lcp-echo-interval указано, что она может использоваться совместно с опцией lcp-echo-failure, которая задаёт количество пропущенных эхо-ответов, после которых соединение будет закрыто pppd.

В общем, попробуйте разные значения этих опций. Более частая отправка эхо-запросов позволит быстрее обнаружить потерю соединения, но в то же время увеличит нагрузку на сеть и на компьютеры сервера и клиента.

Я бы порекомендовал такие опции:
lcp-echo-interval 10 - проверяем связность каждые 10 секунд
lcp-echo-failure 3 - после 3 пропавших эхо-ответов, считаем что связь пропала (к этому моменту связь будет отсутствовать более 30 секунд),
-T 60 - через 60 секунд отсутствия активности перезапускаем по-жёсткому уже сам pppoe (будет срабатывать в том случае, если pppd не сможет переустановить связь сам).

Анонимный комментирует...

Спасибо за оперативный ответ, завтра попробую - отпишусь.

Анонимный комментирует...

Сработало!
Большое, человеческое СПАСИБО!!! )))

Анонимный комментирует...

Подскажите, пожалуйста, а в чём преимущество работы в режиме ядра?

morbo комментирует...

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

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

Таким образом, если трафик туннеля обрабатывается внутри ядра, меньше нагрузка на систему, а скорость обработки трафика получается выше.