воскресенье, 28 апреля 2013 г.

VPN-подключение к Уфанет с помощью xl2tpd

Прочитал на днях на уфанетовском форуме новость начале тестирования PPPoE, который в Уфе доступен пока ещё не везде. Попробовал на всякий случай настроить, хотя и ожидал, что не заработает - мой район попадает в ту область, где PPPoE ещё нет. Всё же почувствовал себя немного обманутым и решил попробовать настроить L2TP, так как зуд в руках и голове не давал успокоиться :)

Настройка в общих чертах совпадает с описанной в VPN-подключение к Уфанет и локальные ресурсы через Ethernet.

1. Установка пакетов

Для начала установим необходимые пакеты:
# apt-get install resolvconf iproute bind9-host
Забегая вперёд, хочу сказать, что в процессе настройки xl2tpd я столкнулся с одной проблемой - значение опции ipparam, настроенное в файле /etc/ppp/options.l2tp, игнорировалось им и вместо него подставлялся IP-адрес VPN-сервера 10.8.0.1.

Можно понять, почему так происходит, если посмотреть вывод команды:
# systemctl status xl2tpd.service
В списке опций pppd опция ipparam с IP-адресом идёт после опции file, поэтому перекрывает определённое в файле опций. Это видно по строчке:
/usr/sbin/pppd passive nodetach : name 111111 debug file /etc/ppp/options.l2tp ipparam 10.8.0.1 /dev/pts/0
Поиски подобных проблем в интернете приводят на страницу: обновил xl2tpd пропал ipparam.

Чтобы посмотреть на пресловутый кусок кода, заходим на сайт компании-разработчика xl2tpd: http://xelerance.com, переходим в разделы меню Services -> Other Software -> xl2tpd и попадаем на страницу http://www.xelerance.com/services/software/xl2tpd/, где сообщается, что проект располагается по адресу https://github.com/xelerance/xl2tpd.

Если посмотреть исходники файла control.c, то можно увидеть несколько фрагментов, похожих на этот:
if (c->lac->pppoptfile[0])
            {
                po = add_opt (po, "file");
                po = add_opt (po, c->lac->pppoptfile);
            }
        };
        if (c->lac->pass_peer)
        {
            po = add_opt (po, "ipparam");
            po = add_opt (po, IPADDY (t->peer.sin_addr));
        }
Для того, чтобы значения опций из файла имели приоритет над определёнными автоматически, нужно переместить блок if так, чтобы он обрабатывался раньше предыдущего блока (который оканчивается на точку с запятой, которые в этом случае излишни).

Чтобы исправить это, качаем исходники для сборки пакета:
# apt-get source xl2tpd
# vim xl2tpd-1.3.1+dfsg/control.c
Переносим пары строк, добавляющих опцию ipparam выше блоков, в которых добавляется опция file.

Готовим исходники для сборки своей версии deb-пакета:
# cd xl2tpd-1.3.1+dfsg/
# dch -i
Приводим верхнюю запись в changelog к следующему виду:
xl2tpd (1.3.1+dfsg-1.1) UNRELEASED; urgency=low

  * Non-maintainer upload.
  * Moved "ipparam" option detection before adding "file" option.

 -- Vladimir Stupin   Sat, 27 Apr 2013 13:35:45 +0600
И выходим из редактора.

Теперь осталось собрать и установить новый пакет (перед сборкой мне потребовалось поставить дополнительный пакет-зависимость):
# apt-get install libpcap0.8-dev
# dpkg-buildpackage -B -us -uc -rfakeroot
# cd ..
# dpkg -i xl2tpd_1.3.1+dfsg-1.1_i386.deb
Теперь всё готово для того, чтобы начать настройку. Скачать получившийся пакет можно здесь: http://stupin.su/files/xl2tpd_1.3.1_dfsg-1.1_i386.deb.

Не стесняясь самоплагиата, помещу сюда описание процедуры настройки интерфейса Ethernet, расстановку приоритетов DNS-серверов и настройки маршрутизации по политикам (полиси-роутинг).

2. Настроим сетевые интерфейсы

Настроим локальный петлевой интерфейс, Ethernet-интерфейс Уфанет, и автоматическое подключение внешнего VPN-соединения.

В файл /etc/network/interfaces пропишем следующие настройки:
auto lo
iface lo inet loopback

auto eth0
iface eth0 inet dhcp
Добавляем в файл конфигурации DHCP-клиента /etc/dhcp3/dhclient.conf новую секцию, связанную с интерфейсом eth0:
interface "eth0" {
  script "/root/bin/dhclient-ufanet";
}
Вам может понадобиться заменить в файлах инициализации интерфейс eth0 (выше он выделен жирным шрифтом) на тот, к которому подключен Ethernet-кабель Уфанет.

Копируем сценарий, выполняющийся по умолчанию, в каталог /root/bin/ под именем dhclient-ufanet:
# mkdir /root/bin/
# cp /sbin/dhclient-script /root/bin/dhclient-ufanet
Заменяем в скопированном сценарии строчки следующего вида в двух местах:
for router in $new_routers; do
    route add default dev $interface gw $router $metric_arg
done
на блок:
for router in $new_routers; do
  for dns in $new_domain_name_servers; do
    ip route add $dns/32 dev $interface via $router $metric_arg
    vpn=`host -t A pptp.ufanet.ru $dns | cut -d" " -f4`
    ip route add $vpn/32 dev $interface via $router $metric_arg
    ip route add default dev $interface src $new_ip_address via $router $metric_arg table lufanet
    ip rule add from $new_ip_address table lufanet
  done
done
3. Настроим приоритеты DNS-серверов

DNS-серверы на интерфейсе ppp должны быть приоритетнее DNS-серверов на интерфейсе Ethernet, поэтому в файле /etc/resolvconf/interface-order строчку ppp* поместим перед eth*.

Файл /etc/resolvconf/interface-order примет следующий вид:
# interface-order(5)
lo.inet*
lo.dnsmasq
lo.pdnsd
lo.!(pdns|pdns-recursor)
lo
tun*
tap*
ppp*
eth*
ath*
wlan*
*
4. Создадим таблицы маршрутизации

Добавим две таблицы с именами lunlim и iunlim, которые будут содержать маршруты ответственные за работу ответного трафика соединений устанавливаемых снаружи.

В файл /etc/iproute2/rt_tables приведём к следующему виду:
#
# reserved values
#
255     local
254     main
253     default
0       unspec
#
# local
#
#1      inr.ruhep

201     ufanet
202     lufanet
5. Подготовим скрипты для управления маршрутами через VPN-подключение

Создадим и пропишем в файл /etc/ppp/ip-up.d/route следующее:
#!/bin/sh

case "$PPP_IPPARAM" in
        ufanet)

        ip route add default dev $PPP_IFACE src $PPP_LOCAL table main

        ip route add default dev $PPP_IFACE src $PPP_LOCAL table ufanet
        ip rule add from $PPP_LOCAL table ufanet
        ;;

        *)
        echo "No PPP_IPPARAM defined"
        ;;
esac
Создадим парный файл /etc/ppp/ip-down.d/route и пропишем в него следующее:
#!/bin/sh

case "$PPP_IPPARAM" in
        ufanet)

        ip route del default dev $PPP_IFACE src $PPP_LOCAL table main

        ip route del default dev $PPP_IFACE src $PPP_LOCAL table ufanet
        ip rule del from $PPP_LOCAL table ufanet
        ;;

        *)
        echo "No PPP_IPPARAM defined"
        ;;
esac
Не забываем проставить у файлов флаг выполнимости:
# chmod +x /etc/ppp/ip-up.d/route
# chmod +x /etc/ppp/ip-down.d/route
6. Настройка xl2tpd

В файл конфигурации /etc/xl2tpd/xl2tdp.conf пропишем следующие настройки:
[global]
access control = yes

[lac ufanet]
lns = vpn.ufanet.ru
redial = yes
redial timeout = 10
require chap = yes
require authentication = no
ppp debug = yes
pppoptfile = /etc/ppp/options.l2tp
require pap = no
autodial = yes
name = 111111
Создаём файл /etc/ppp/options.l2tp с настройками для демона pppd:
unit 0
remotename vpn.ufanet.ru
ipparam ufanet
connect /bin/true
mru 1460
mtu 1460
nodeflate
nobsdcomp
persist
maxfail 0
nopcomp
noaccomp
noauth
noproxyarp
name 111111
Теперь нужно создать файл /etc/xl2tpd/l2tp-secrets с паролем для подключения:
111111          vpn.ufanet.ru   password
Во всех трёх файлах вместо отмеченных жирным шрифтом цифр нужно указать ваш логин для подключения, а в последнем файле выделенное жирным шрифтом слово password - заменить на ваш пароль.

Теперь, в принципе, всё готово для установки подключения. Достаточно перезапустить сеть и запустить демон xl2tpd:
# /etc/init.d/networking stop
# /etc/init.d/networking start
# /etc/init.d/xl2tpd start
Для автоматического запуска xl2tpd в процессе загрузки можно выполнить следующую команду:
# update-rc.d xl2tpd defaults
Я же на этом не остановился и, поскольку на домашнем компьютере использую systemd, написал service-файл.

7. Настройка systemd для запуска xl2tpd

По умолчанию systemd использует скрипты из каталога /etc/init.d, если для них нет service-файла с таким-же именем. Попробуем создать service-файл /etc/systemd/system/xl2tpd.service со следующим содержимым:
[Unit]
Description=layer 2 tunelling protocol daemon xl2tpd
After=network.target

[Service]
ExecStart=/usr/sbin/xl2tpd -D -c /etc/xl2tpd/xl2tpd.conf -s /etc/xl2tpd/l2tp-secrets -p /run/xl2tpd/xl2tpd.pid -C /run/xl2tpd/l2tp-control
ExecStop=/usr/sbin/xl2tpd-control -c /run/xl2tpd/l2tp-control disconnect ufanet
Type=simple
PIDFile=/var/run/xl2tpd/xl2tpd.pid

[Install]
WantedBy=multi-user.target
Для запуска xl2tpd понадобится создать каталог /run/xl2tpd. Для этого создадим файл /etc/tmpfiles.d/xl2tpd.conf с настройками для создания каталога:
d /run/xl2tpd 0755 root root -
Теперь можно сообщить systemd об изменении настроек:
# systemctl daemon-reload
Сообщить systemd о том, что нужно запускать xl2tpd.service при загрузке системы:
# systemctl enable xl2tpd.service
И запустить xl2tpd средствами systemd:
# systemctl start xl2tpd.service
У этого service-файла есть одна недоработка, которую я не смог побороть: правильное завершение процесса xl2tpd. После завершения сервиса, systemd назначает сервису статус ошибки.

Использованные материалы:
1. Настройка VPN (протокол L2TP) на примере провайдера Корбина Телеком,
2. обновил xl2tpd пропал ipparam.

P.S. Работает не стабильно, поэтому вернулся обратно, на PPTP.

Комментариев нет: