Развёртывание L2TP-сервера с IPSec / PSK

()

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

Для большинства популярных устройств (на Windows, Android и iOS) от этого недостатка свободен протокол L2TP. По умолчанию L2TP не использует шифрование, однако его можно использовать в связке с IPSec, инициализируемым с помощью PSK (Pre-shared Key - дополнительный ключ). Далее будет показано как можно быстро настроить IPSec L2TP-сервер с PSK на Ubuntu.

Для начала берём недорогую VPS с Ubuntu 16.04 и сразу устанавливаем на неё неободимые пакеты. Нам понадобятся:

  • strongswan: для управления IPSec;
  • xl2tpd: демон, который будет обслуживать L2TP-соединения;
  • iptables-persistent: для управления правилами пакетного фильтра (файрволла);
  • denyhosts: для защиты SSH от перебора пароля;

Устанавливаем:

apt-get install strongswan xl2tpd iptables-persistent denyhosts

Следующим шагом придумываем ключ для шифрования IPSec, например "Sup3rP4ss", и приведём файл "/etc/ipsec.secrets" к виду:

%any %any : PSK "Sup3rP4ss"

Далее открываем файл "/etc/ipsec.conf", удаляем всё его содержимое и заносим в него следующее:

config setup
        virtual_private=%v4:10.0.0.0/8,%v4:192.168.0.0/16,%v4:172.16.0.0/12
        nat_traversal=yes
        protostack=netkey

conn l2tpvpn
        type=transport
        authby=secret
        pfs=no
        rekey=no
        keyingtries=1
        left=%any
        leftprotoport=udp/l2tp
        leftid=@l2tpvpnserver
        right=%any
        rightprotoport=udp/%any
        auto=add

На этом настройка IPSec закончена. Остаётся перезапустить обслуживающий IPSec демон strongswan:

service strongswan restart

Приступаем к настройке xl2tpd. Основная часть его настроек находится в файле "/etc/xl2tpd/xl2tpd.conf", который нужно привести к виду:

[global]
port = 1701
access control = no
ipsec saref = yes
force userspace = yes

; Файл с логинами и паролями
auth file = /etc/ppp/chap-secrets

[lns default]
; Диапазон адресов, динамически выдаваемых клиентам
; Мы ограничимся подсетью 172.28.253.64/26
; Первую её часть оставим под статически привязанные к логинам адреса
; А вторая - динамический пул
ip range = 172.28.253.96-172.28.253.126

; IP-адрес на стороне сервера
local ip = 172.28.253.65

; Это имя используется в качестве ipparam при поиске логинов и паролей в auth file
name = l2tpserver

; Файл с дополнительными опциями для ppp
pppoptfile = /etc/ppp/options.xl2tpd

flow bit = yes
exclusive = no
hidden bit = no
length bit = yes
require authentication = yes
require chap = yes
refuse pap = yes

Следующим на очереди у нас идёт файл "/etc/ppp/options.xl2tpd" В нём описываются дополнительные опции ppp. В нашем случае он будет иметь вид:

noccp
auth
crtscts
mtu 1410
mru 1410
nodefaultroute
lock
noproxyarp
silent
modem
asyncmap 0
hide-password
require-mschap-v2
ms-dns 8.8.8.8
ms-dns 8.8.4.4

На этом настройка xl2tpd заканчивается. Перезапускаем процесс:

service xl2tpd restart

Приступаем к настройке пакетного фильтра (файрволла). Для удобства создадим скрипт "firewall.sh", в котором опишем все необходимые нам правила:

#!/bin/bash

# Внешний интерфейс сервера
IF_EXT="ens3"

# Внутренние интерфейсы (обслуживающие ВПН-клиентов)
IF_INT="ppp+"

# Сеть, адреса из которой будут получать ВПН-клиенты
NET_INT="172.28.253.64/26"

# Сбрасываем все правила
iptables -F
iptables -F -t nat

# Устанавливаем политики по умолчанию
iptables -P INPUT DROP
iptables -P OUTPUT ACCEPT
iptables -P FORWARD DROP

# Разрешаем весь трафик на петлевом интерфейсе
iptables -A INPUT -i lo -j ACCEPT

# Разрешаем всё для ВПН-клиентов
iptables -A INPUT -i ${IF_INT} -s ${NET_INT} -j ACCEPT


# Разрешаем входящие соединения к L2TP
# Но только с шифрованием!
iptables -A INPUT -p udp -m policy --dir in --pol ipsec -m udp --dport 1701 -j ACCEPT

# Разрешаем IPSec
iptables -A INPUT -p esp -j ACCEPT
iptables -A INPUT -p ah -j ACCEPT
iptables -A INPUT -p udp --dport 500 -j ACCEPT
iptables -A INPUT -p udp --dport 4500 -j ACCEPT

# Разрешаем доступ к серверу по SSH
iptables -A INPUT -m tcp -p tcp --dport 22 -j ACCEPT


# Разрешаем входящие ответы на исходящие соединения
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

# NAT для локальной сети (ВПН-клиентов)
iptables -t nat -A POSTROUTING -s ${NET_INT} -j MASQUERADE -o ${IF_EXT}
iptables -A FORWARD -i ${IF_INT} -o ${IF_EXT} -s ${NET_INT} -j ACCEPT
iptables -A FORWARD -i ${IF_EXT} -o ${IF_INT} -d ${NET_INT} -m state --state RELATED,ESTABLISHED -j ACCEPT

Применяем правила и сохраняем их для автоматической загрузки при старте системы:

bash firewall.sh
netfilter-persistent save

Ещё надо включить саму возможность пересылки пакетов между интерфейсами. Делается это в файле "/etc/sysctl.conf" добавлением (или раскомментированием) строки:

net.ipv4.ip_forward=1

Чтобы эти изменения вступили в силу до перезагрузки нужно выполнить:

sysctl -p /etc/sysctl.conf

Остаётся обезопасить SSH от попыток перебора пароля и можно заводить пользователей. За это отвечает сервис "denyhosts", который блокирует IP-адреса, с которых идёт перебор паролей. В целом конфигурация по умолчанию (находится в файле "/etc/denyhosts.conf") нас вполне устроит. Единственный момент который стоит поправить: по умолчанию адреса блокируются навсегда. Лучше всё-таки их удалять из чёрного списка через несколько дней после блокировки:

PURGE_DENY = 3d

И перезапускаем сервис:

service denyhosts restart

Теперь можно заводить пользователей нашего VPN-сервера. Для этого нужно открыть в текстовом редакторе файл "/etc/ppp/chap-secrets" и добавлять примерно такие строки:

# "логин" имя_сервиса(ipparam) "пароль" "IP-клиента(опционально)"
# Пользователь с постоянным IP-адресом:
"user1"    l2tpserver    "D4dLMy44gc"    "172.28.253.67"
# Пользователь, получающий динамический адрес
"user2"    l2tpserver    "HPg0dBZRxv"

На этом настройка сервера заканчивается и можно переходить к настройке клиентских устройств. На Android 7.0 нужно зайти в настройки VPN, выбрать пункт "добавить" и добавить соединение, указав тип соединения "L2TP/IPSec PSK", в качестве сервера указать IP-адрес нашей VPS, в качестве общего ключа IPsec - выбранную ранее ключевую фразу. Имя соединения - произвольное. Создав соединение сразу можно подключаться (потребуется ввести логин и пароль).

L2TP IPSec / PSK соединение на Android

Следует помнить что на Android для использования штатного (встроенного в систему) VPN-клиента необходимо предварительно настроить блокировку экрана с помощью пароля, пин-кода, графического ключ, отпечатка пальца или какого-ещё доступного на вашем устройстве способа.

На Windows 10 настройки находятся в панели параметров: "Настройки сети", "VPN". Поля заполняются полностью аналогично Android. После чего так же можно сразу выполнять подключение.

L2TP IPSec / PSK соединение на Windows 10

На этом всё. Приятной работы!

Ключевые слова: vpn, l2tp, ipsec, psk, xl2tpd, strongswan, iptables-persistent, android, windows.

Подписаться на обновления: RSS-лента Telegram канал Twitter

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

Ladm 2018-05-18 12:30:05 (#)

Осталось найти время проверить правильность написанного выше.

MooSE 2018-05-18 15:50:13 (#)

Осталось найти время проверить правильность написанного выше.
Какая часть написанного тебя смущает?:)

Anonymous 2018-06-18 22:22:48 (#)

Сделал все по инструкции, к сожелению не работает(

Anonymous 2018-06-18 22:25:43 (#)

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

MooSE 2018-06-18 23:32:29 (#)

Попробовал вместо скрипта взять часть другой инструкции с iptables - заработало, но совершенно не обращает внимание на общий пароль, т.е. можно любой писать((
Это означает что у вас не работает IPSec. Т.е. L2TP работает, но без шифрования. Видно что-то у вас всё-таки настроено не так.

Собственно скорее всего у вас не "взлетел" strongswan. Потому и пришлось в iptables разрешать весь udp-трафик по порту 1701, а не только тот что с шифрованием. Так дело было?:)

Смотрите логи strongswan для начала.

Anonymous 2018-06-18 23:57:44 (#)

service strongswan restart корректно перезапустился, я так понимаю значит он работает. А где логи strongswan смотреть, в /var/log/ нет ничего похожего? и я не могу у вас на сайте авторизоваться "Notice: Undefined index: result in /home/moose/www/ylsoftware.com/enter.inc on line 25"

MooSE 2018-06-19 13:26:15 (#)

service strongswan restart корректно перезапустился, я так понимаю значит он работает. А где логи strongswan смотреть
Попробуйте:
journalctl -xe -u strongswan.service


не могу у вас на сайте авторизоваться "Notice: Undefined index: result in /home/moose/www/ylsoftware.com/enter.inc on line 25"
Каюсь. Косяк в коде. Исправил. Если сейчас не получится авторизоваться то напишите на moose@ylsoftware.com. Будем разбираться детальнее.

Anonymous 2018-06-26 08:37:46 (#)

root@vps46396:~# journalctl -xe -u strongswan.service
Jun 22 03:45:26 vps46396 ipsec_starter[3295]: ### 4 parsing errors (0 fatal) ###
Jun 22 03:45:26 vps46396 systemd[1]: Started strongSwan IPsec services.
-- Subject: Unit strongswan.service has finished start-up
-- Defined-By: systemd
-- Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
--
-- Unit strongswan.service has finished starting up.
--
-- The start-up result is done.
Jun 22 03:45:26 vps46396 charon[3310]: 00[DMN] Starting IKE charon daemon (stron
Jun 22 03:45:26 vps46396 charon[3310]: 00[CFG] loading ca certificates from '/et
Jun 22 03:45:26 vps46396 charon[3310]: 00[CFG] loading aa certificates from '/et
Jun 22 03:45:26 vps46396 charon[3310]: 00[CFG] loading ocsp signer certificates
Jun 22 03:45:26 vps46396 charon[3310]: 00[CFG] loading attribute certificates fr
Jun 22 03:45:26 vps46396 charon[3310]: 00[CFG] loading crls from '/etc/ipsec.d/c
Jun 22 03:45:26 vps46396 charon[3310]: 00[CFG] loading secrets from '/etc/ipsec.
Jun 22 03:45:26 vps46396 charon[3310]: 00[CFG] loaded IKE secret for %any %any
Jun 22 03:45:26 vps46396 charon[3310]: 00[LIB] loaded plugins: charon test-vecto
Jun 22 03:45:26 vps46396 charon[3310]: 00[LIB] dropped capabilities, running as
Jun 22 03:45:26 vps46396 charon[3310]: 00[JOB] spawning 16 worker threads
Jun 22 03:45:26 vps46396 ipsec_starter[3309]: charon (3310) started after 20 ms
Jun 22 03:45:26 vps46396 charon[3310]: 07[CFG] received stroke: add connection '
Jun 22 03:45:26 vps46396 charon[3310]: 07[CFG] added configuration 'l2tpvpn'
lines 80-102/102 (END)
Jun 22 03:45:26 vps46396 ipsec_starter[3295]: ### 4 parsing errors (0 fatal) ###
Jun 22 03:45:26 vps46396 systemd[1]: Started strongSwan IPsec services.
-- Subject: Unit strongswan.service has finished start-up
-- Defined-By: systemd
-- Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
--
-- Unit strongswan.service has finished starting up.
--
-- The start-up result is done.
Jun 22 03:45:26 vps46396 charon[3310]: 00[DMN] Starting IKE charon daemon (strongSwan 5.3.5, Linux 2.6.32-042stab127.2, x86_64)
Jun 22 03:45:26 vps46396 charon[3310]: 00[CFG] loading ca certificates from '/etc/ipsec.d/cacerts'
Jun 22 03:45:26 vps46396 charon[3310]: 00[CFG] loading aa certificates from '/etc/ipsec.d/aacerts'
Jun 22 03:45:26 vps46396 charon[3310]: 00[CFG] loading ocsp signer certificates from '/etc/ipsec.d/ocspcerts'
Jun 22 03:45:26 vps46396 charon[3310]: 00[CFG] loading attribute certificates from '/etc/ipsec.d/acerts'
Jun 22 03:45:26 vps46396 charon[3310]: 00[CFG] loading crls from '/etc/ipsec.d/crls'
Jun 22 03:45:26 vps46396 charon[3310]: 00[CFG] loading secrets from '/etc/ipsec.secrets'
Jun 22 03:45:26 vps46396 charon[3310]: 00[CFG] loaded IKE secret for %any %any
Jun 22 03:45:26 vps46396 charon[3310]: 00[LIB] loaded plugins: charon test-vectors aes rc2 sha1 sha2 md4 md5 random nonce x509 revocation constraints pubkey pkcs1 pkcs7 pkcs8 pkcs12 pgp dnskey sshkey pem openssl fips-prf gmp agent xcbc h
Jun 22 03:45:26 vps46396 charon[3310]: 00[LIB] dropped capabilities, running as uid 0, gid 0
Jun 22 03:45:26 vps46396 charon[3310]: 00[JOB] spawning 16 worker threads
Jun 22 03:45:26 vps46396 ipsec_starter[3309]: charon (3310) started after 20 ms
Jun 22 03:45:26 vps46396 charon[3310]: 07[CFG] received stroke: add connection 'l2tpvpn'
Jun 22 03:45:26 vps46396 charon[3310]: 07[CFG] added configuration 'l2tpvpn'

Anonymous 2018-07-12 22:52:31 (#)

авторизоваться так и не могу, на почту написал давно уже. Лог скинул - тоже полчек(

MooSE 2018-07-14 23:28:36 (#)

По авторизации: починил. При обновлении MySQL произошли изменения, из-за которых один запрос некорректно отрабатывал.

По срокам ответа: этот проект моё хобби, а не работа. Я занимаюсь им в личное время, которого, к сожалению, не так уж много. Быстрой реакции стоит искать у тех, кому за это платят:)

По логу: с виду всё нормально. Покажите вывод:
sudo netstat -lpntu|grep -E ":(4500|1701|500)"


А так же:
iptables-save -t filter

Anonymous 2018-08-22 13:08:33 (#)

Вот в этом снипплете опечатка, из-за которой не работает:
# "логин" имя_сервиса(ipparam) "пароль" "IP-клиента(опционально)"
# Пользователь с постоянным IP-адресом:
"user1"    l2tpserver    "D4dLMy44gc"    "172.28.253.67"
# Пользователь, получающий динамический адрес
"user2"    l2tpserver    "HPg0dBZRxv"


Если IP прописан — всё ок, если нет — то ой.
Там последняя строчка должна выглядеть вот так (для выдачи динамического адреса):
"user2"    l2tpserver    "HPg0dBZRxv"    *

сервис онлайн-займов GreenMoney.ru 2018-09-06 07:48:11 (#)

Доброго времени суток. Сделал все по мануалу, vpn цепляется, сервер пингуется, но траффик не идет в подсеть сервера. Не подскажете в какую сторону копать для нуба?

MooSE 2018-09-06 11:23:51 (#)

Что значит "трафик не идёт в подсеть сервера"? А куда идёт? Как проверяли? Как выглядит таблица маршрутизации на клиенте?

Timofey 2018-10-22 18:19:28 (#)

У меня похожая ситуация, и то после добавления параметра lac = 0.0.0.0-255.255.255.255 в /etc/xl2tpd/xl2tpd.conf (Была ошибка Denied connection to unauthorized peer... )
Но дальше никуда не пускает.

Вроде исходящие соединения для подсети vpn открыты в iptables:
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE all -- 172.28.253.64/26 anywhere
root@VM:~# iptables -L
Chain INPUT (policy DROP)
target prot opt source destination
DROP all -- 112.85.42.233 anywhere
DROP all -- 116.31.116.8 anywhere
DROP all -- 5.188.10.76 anywhere
ACCEPT all -- anywhere anywhere
ACCEPT all -- 172.28.253.64/26 anywhere
ACCEPT udp -- anywhere anywhere policy match dir in pol ipsec udp dpt:l2f
ACCEPT esp -- anywhere anywhere
ACCEPT ah -- anywhere anywhere
ACCEPT udp -- anywhere anywhere udp dpt:isakmp
ACCEPT udp -- anywhere anywhere udp dpt:ipsec-nat-t
ACCEPT tcp -- anywhere anywhere tcp dpt:ssh
ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED

Chain FORWARD (policy DROP)
target prot opt source destination
ACCEPT all -- 172.28.253.64/26 anywhere
ACCEPT all -- anywhere 172.28.253.64/26 state RELATED,ESTABLISHED

Chain OUTPUT (policy ACCEPT)
target prot opt source destination
root@VM:~#

Пакеты на dns сервер идут.
U 172.28.253.96:55159 -> 8.8.8.8:53 #32
.............yandex.ru.....

U 172.28.253.96:55159 -> 8.8.8.8:53 #33
.............yandex.ru.....

U 172.28.253.96:55159 -> 8.8.4.4:53 #34
.............yandex.ru.....


Как дальше дебажить это дело?

MooSE 2018-10-22 22:44:38 (#)

Как дальше дебажить это дело?

sysctl net.ipv4.ip_forward
iptables -L -n -t nat

_igor_ 2018-11-15 09:19:32 (#)

Добрый день. Большое спасибо за мануал по настройке. Единственное внятное руководство, что нашел.
Всё почти заработало как надо. Но есть несколько вопросов. Я развернул VPN сервер на VPS(Ubuntu).
- При этих настройках 2 разных устройства подключенных к серверу должны видеть друг друга? Я развернул домашний postgres для опытов. Хотелось бы иметь к нему доступ отовсюду.
- На сервере стоит ajenti. что прописать в настройки фаирвола, чтоб к ней можно было подключиться только из VPN?
Ну и самое проблемное. После настройки 2 ноута под win10 подключились без проблем сразу, а вот два Android смартфона, Ubuntu desctop 18.04 и mikrotik наотрез отказываются подключаться. В чём может быть проблема?
p.s. Все устройства были подрублены к одному wifi
Новый комментарий

Жирный текстКурсивный текстПодчёркнутый текстЗачёркнутый текстПрограммный кодСсылкаИзображение




© 2006-2018 Вадим Калинников aka MooSE