Проблематика
Ещё совсем недавно многие не знали, как это — работать из дома. Пандемия резко изменила ситуацию в мире, все начали адаптироваться к сложившимся обстоятельствам, а именно к тому, что выходить из дома стало просто небезопасно. И многим пришлось быстро организовывать работу из дома для своих сотрудников.
Однако отсутствие грамотного подхода в выборе решений для удалённой работы может привести к необратимым потерям. Пароли пользователей могут быть украдены, а это даст возможность злоумышленнику бесконтрольно подключаться к сети и ИТ-ресурсам предприятия.
Именно поэтому сейчас выросла потребность в создании надёжных корпоративных VPN сетей. Я расскажу вам о надёжной, безопасной и простой в использовании VPN сети.
Она работает по схеме IPsec/L2TP, использующей для аутентификации клиентов неизвлекаемые ключи и сертификаты, хранящиеся на токенах, а также передает данные по сети в зашифрованном виде.
В качестве демонстрационных стендов для настройки использовались сервер с CentOS 7 (адрес: centos.vpn.server.ad) и клиент с Ubuntu 20.04, а также клиент с Windows 10.
Описание системы
VPN будет работать по схеме IPSec + L2TP + PPP. Протокол Point-to-Point Protocol (PPP) работает на канальном уровне модели OSI и обеспечивает аутентификацию пользователя и шифрование передаваемых данных. Его данные инкапсулируются в данные протокола L2TP, который собственно обеспечивает создание соединения в VPN сети, но не обеспечивает аутентификацию и шифрование.
Данные L2TP инкапсулируются в протокол IPSec, который тоже обеспечивает аутентификацию и шифрование, но в отличие от протокола PPP аутентификация и шифрование происходит на уровне устройств, а не на уровне пользователей.
Данная особенность позволяет обеспечить аутентификацию пользователей только с определённых устройств. Мы же будем использовать протокол IPSec как данное и позволим производить аутентификацию пользователей с любого устройства.
Аутентификация пользователя с помощью смарт-карт будет производиться на уровне протокола PPP с помощью протокола EAP-TLS.
Более подробную информации о работе данной схемы можно найти в этой статье.
Почему данная схема отвечает всем трём требованиям хорошей VPN сети
- Надёжность данной схемы проверена временем. Она используется для развёртывания VPN сетей с 2000 года.
- Безопасную аутентификацию пользователя обеспечивает протокол PPP. Стандартная реализация протокола PPP разработанная Paul Mackerras не обеспечивает достаточного уровня безопасности, т.к. для аутентификации в лучшем случае случае используется аутентификация с помощью логина и пароля. Все мы знаем, что логин-пароль можно подсмотреть, подобрать или украсть. Тем не менее уже давно разработчик Jan Just Keijser в своей реализации данного протокола исправил этот момент и добавил возможность использования для аутентификации протоколы, основанные на асимметричном шифровании, такой как EAP-TLS. Кроме того, он добавил возможность использования смарт-карт для аутентификации, что сделало данную систему более безопасной.
В настоящий момент ведутся активные переговоры для слияния этих двух проектов и можно быть уверенными в том, что рано или поздно это всё равно произойдёт. Так, например, в репозиториях Fedora уже давно лежит пропатченная версия PPP, использующая для аутентификации безопасные протоколы. - Ещё совсем недавно данную сеть могли использовать только пользователи Windows, но наши коллеги из МГУ Василий Шоков и Александр Смирнов нашли старый проект L2TP клиента для Linux и доработали его. Совместными усилиями мы исправили множество багов и недочетов в работе клиента, упростили установку и настройку системы, даже при сборке из исходников. Наиболее существенными из них являются:
- Исправлены проблемы совместимости старого клиента с интерфейсом новых версий openssl и qt.
- Удалена передача pppd PIN-кода токена через временный файл.
- Исправлен некорректный запуск программы запроса пароля через графический интерфейс. Это было сделано за счет установки корректного окружения для xl2tpd сервиса.
- Сборка демона L2tpIpsecVpn теперь осуществляется совместно со сборкой самого клиента, что облегчает процесс сборки и настройки.
- Для удобства разработки подключена система Azure Pipelines для тестирования корректности сборки.
- Добавлена возможность принудительно понижать security level в контексте openssl. Это полезно для корректной поддержки новых операционных систем, где стандартный security level установлен на 2, с VPN сетями, в которых используются сертификаты, не удовлетворяющие требованиям безопасности данного уровня. Данная опция будет полезна для работы с уже существующими старыми VPN сетями.
Исправленную версию можно найти в данном репозитории.
Данный клиент поддерживает использование смарт-карт для аутентификации, а также максимально скрывает все тяготы и невзгоды настройки данной схемы под Linux, делая настройку клиента максимально простой и быстрой.
Конечно, для удобной связи PPP и GUI клиента не обошлось и без дополнительных правок каждого из проектов, но тем не менее их удалось минимизировать и свести к минимуму:
- Исправлена ошибка некорректного пробрасывания PIN-кода токена из PPP в контекст openssl
- Исправлена ошибка в порядке загрузки конфигурации и инициализации openssl контекста. Данная ошибка не позволяла подгружать из локального /etc/ppp/openssl.cnf файла с конфигурацией ничего, кроме сведений о движках openssl для работы со смарт-картами, что составляло серьёзное неудобство, если, например, кроме информации об энджинах мы хотели задать что-то ещё. Например, зафиксировать security level при установке соединения.
Теперь можно приступить к настройке.
Настройка сервера
Установим все необходимые пакеты.
Установка strongswan (IPsec)
В первую очередь, настроим firewall для работы ipsec
sudo firewall-cmd --permanent --add-port=1701/{tcp,udp}
sudo firewall-cmd --permanent --add-service=ipsec
sudo firewall-cmd --reload
Затем приступим к установке
sudo yum install epel-release ipsec-tools dnf
sudo dnf install strongswan
После установки необходимо задать конфигурацию для strongswan (одну из реализаций IPSec). Для этого отредактируем файл /etc/strongswan/ipsec.conf :
config setup
nat_traversal=yes
virtual_private=%v4:10.0.0.0/8,%v4:192.168.0.0/16,%v4:172.16.0.0/12
oe=off
protostack=netkey
conn L2TP-PSK-NAT
rightsubnet=vhost:%priv
also=L2TP-PSK-noNAT
conn L2TP-PSK-noNAT
authby=secret
pfs=no
auto=add
keyingtries=3
rekey=no
ikelifetime=8h
keylife=1h
type=transport
left=%any
leftprotoport=udp/1701
right=%any
rightprotoport=udp/%any
ike=aes128-sha1-modp1536,aes128-sha1-modp1024,aes128-md5-modp1536,aes128-md5-modp1024,3des-sha1-modp1536,3des-sha1-modp1024,3des-md5-modp1536,3des-md5-modp1024
esp=aes128-sha1-modp1536,aes128-sha1-modp1024,aes128-md5-modp1536,aes128-md5-modp1024,3des-sha1-modp1536,3des-sha1-modp1024,3des-md5-modp1536,3des-md5-modp1024
Также зададим общий пароль для входа. Общий пароль должен быть известен всем участникам сети для аутентификации. Данный способ и является заведомо ненадёжным, т.к. данный пароль с лёгкостью может стать известным личностям, которым мы не хотим предоставлять доступ к сети.
Тем не менее, даже этот факт не повлияет на безопасность организации сети, т.к. основное шифрование данных и аутентификация пользователей осуществляется протоколом PPP. Но справедливости ради стоит заметить, что strongswan поддерживает более безопасные технологии для аутентификации, например, с помощью приватных ключей. Так же в strongswan имеется возможность обеспечить аутентификацию с помощью смарт-карт, но пока поддерживается ограниченный круг устройств и поэтому аутентификация с помощью токенов и смарт-карт Рутокен пока затруднительна. Зададим общий пароль через файл /etc/strongswan/ipsec.secrets:
# ipsec.secrets - strongSwan IPsec secrets file
%any %any : PSK "SECRET_PASSPHRASE"
Перезапустим strongswan:
sudo systemctl enable strongswan
sudo systemctl restart strongswan
Установка xl2tp
sudo dnf install xl2tpd
Сконфигурируем его через файл /etc/xl2tpd/xl2tpd.conf:
[global]
force userspace = yes
listen-addr = 0.0.0.0
ipsec saref = yes
[lns default]
exclusive = no
; определяет статический адрес сервера в виртуальной сети
local ip = 100.10.10.1
; задает диапазон виртуальных адресов
ip range = 100.10.10.1-100.10.10.254
assign ip = yes
refuse pap = yes
require authentication = yes
; данную опцию можно отключить после успешной настройки сети
ppp debug = yes
length bit = yes
pppoptfile = /etc/ppp/options.xl2tpd
; указывает адрес сервера в сети
name = centos.vpn.server.ad
Перезапустим сервис:
sudo systemctl enable xl2tpd
sudo systemctl restart xl2tpd
Настройка PPP
UPD: предложенные нами изменения были приняты начиная с версии pppd 2.4.9. Поэтому пакет pppd можно взять из репозиториев.
Желательно поставить последнюю версию pppd. Для этого выполним следующую последовательность команд:
sudo yum install git make gcc openssl-devel
git clone "https://github.com/jjkeijser/ppp"
cd ppp
./configure --prefix /usr
make -j4
sudo make install
Впишите в файл /etc/ppp/options.xl2tpd следующее (если там присутствуют какие-то значения, то их можно удалить):
ipcp-accept-local
ipcp-accept-remote
ms-dns 8.8.8.8
ms-dns 1.1.1.1
noccp
auth
crtscts
idle 1800
mtu 1410
mru 1410
nodefaultroute
debug
lock
proxyarp
connect-delay 5000
Выписываем корневой сертификат и сертификат сервера:
#директория с сертификатами пользователей, УЦ и сервера
sudo mkdir /etc/ppp/certs
#директория с закрытыми ключами сервера и УЦ
sudo mkdir /etc/ppp/keys
#запрещаем любой доступ к этой дирректории кроме администатора
sudo chmod 0600 /etc/ppp/keys/
#генерируем ключ и выписываем сертификат УЦ
sudo openssl genrsa -out /etc/ppp/keys/ca.pem 2048
sudo openssl req -key /etc/ppp/keys/ca.pem -new -x509 -out /etc/ppp/certs/ca.pem -subj "/C=RU/CN=L2TP CA"
#генерируем ключ и выписываем сертификат сервера
sudo openssl genrsa -out /etc/ppp/keys/server.pem 2048
sudo openssl req -new -out server.req -key /etc/ppp/keys/server.pem -subj "/C=RU/CN=centos.vpn.server.ad"
sudo openssl x509 -req -in server.req -CAkey /etc/ppp/keys/ca.pem -CA /etc/ppp/certs/ca.pem -out /etc/ppp/certs/server.pem -CAcreateserial
Таким образом, мы закончили с основной настройкой сервера. Остальная часть конфигурации сервера связана с добавлением новых клиентов.
Добавление нового клиента
Чтобы добавить нового клиента в сеть, необходимо записать его сертификат в список доверенных для данного клиента.
Если пользователь хочет стать участником VPN сети, он создаёт ключевую пару и заявку на сертификат для данного клиента. Если пользователь доверенный, то данную заявку можно подписать, а получившийся сертификат записать в директорию сертификатов:
sudo openssl x509 -req -in client.req -CAkey /etc/ppp/keys/ca.pem -CA /etc/ppp/certs/ca.pem -out /etc/ppp/certs/client.pem -CAcreateserial
Добавим строчку в файл /etc/ppp/eaptls-server для сопоставления имени клиента и его сертификата:
"client" * /etc/ppp/certs/client.pem /etc/ppp/certs/server.pem /etc/ppp/certs/ca.pem /etc/ppp/keys/server.pem *
NOTE
Чтобы не запутаться, лучше чтобы: Common Name, имя файла с сертификатом и имя пользователя были уникальными.
Также стоит проверить, что в других файлах аутентификации нигде не фигурирует имя пользователя, которого мы добавляем, иначе возникнут проблемы со способом аутентификации пользователя.
Этот же сертификат необходимо отправить пользователю обратно.
Генерация ключевой пары и сертификата
Для успешной аутентификации клиенту необходимо:
- сгенерировать ключевую пару;
- иметь корневой сертификат УЦ;
- иметь сертификат для своей ключевой пары, подписанный корневым УЦ.
для клиента на Linux
Для начала сгенерируем ключевую пару на токене и создадим заявку на сертификат:
#идентификатор ключа (параметр --id) можно заменить на любой другой.
pkcs11-tool --module /usr/lib/librtpkcs11ecp.so --keypairgen --key-type rsa:2048 -l --id 45
openssl
OpenSSL> engine dynamic -pre SO_PATH:/usr/lib/x86_64-linux-gnu/engines-1.1/pkcs11.so -pre ID:pkcs11 -pre LIST_ADD:1 -pre LOAD -pre MODULE_PATH:librtpkcs11ecp.so
...
OpenSSL> req -engine pkcs11 -new -key 45 -keyform engine -out client.req -subj "/C=RU/CN=client"
Появившуюся заявку client.req отправьте в УЦ. После того как вы получите сертификат для своей ключевой пары, запишите его на токен с тем же id, что и у ключа:
pkcs11-tool --module /usr/lib/librtpkcs11ecp.so -l -y cert -w ./client.pem --id 45
для клиентов Windows и Linux (более универсальный способ)
Данный способ является более универсальным, т.к. позволяет сгенерировать ключ и сертификат, который будет успешно распознаваться у пользователей Windows и Linux, но он требует наличие машины на Windows для проведения процедуры генерации ключей.
Перед генерацией запросов и импортом сертификатов необходимо добавить корневой сертификат VPN сети в список доверенных. Для этого откроем его и в открывшемся окне выберем опцию "Установить сертификат":
В открывшемся окне выберем установку сертификата для локального пользователя:
Установим сертификат в хранилище доверенных корневых сертификатов УЦ:
После всех этих действий соглашаемся со всеми дальнейшими пунктами. Теперь система настроена.
Создадим файл cert.tmp со следующим содержимым:
[NewRequest]
Subject = "CN=client"
KeyLength = 2048
KeySpec = "AT_KEYEXCHANGE"
ProviderName = "Microsoft Base Smart Card Crypto Provider"
KeyUsage = "CERT_KEY_ENCIPHERMENT_KEY_USAGE"
KeyUsageProperty = "NCRYPT_ALLOW_DECRYPT_FLAG"
RequestType = PKCS10
SMIME = FALSE
После этого сгенерируем ключевую пару и создадим заявку на сертификат. Для этого откроем powershell и введём следующую команду:
certreq.exe -new -pin $PIN .\cert.tmp .\client.req
Отправьте созданную заявку client.req в ваш УЦ и дождитесь получения сертификата client.pem. Его можно записать на токен и добавить в хранилище сертификатов Windows с помощью следующей команды:
certreq.exe -accept .\client.pem
Стоит заметить, что аналогичные действия можно воспроизвести с помощью графического интерфейса программы mmc, но данный способ является более времязатратным и менее программируемым.
Настройка клиента Ubuntu
NOTE
Настройка клиента на Linux в данный момент является достаточно длительной по времени, т.к. требует сборки отдельных программ из исходников. Мы постараемся в ближайшее время добиться, чтобы все изменения попали в официальные репозитории.
Для обеспечения подключения на уровне IPSec к серверу — используется пакет strongswan и демон xl2tp. Для упрощения подключения к сети с помощью смарт-карт – будем использовать пакет l2tp-ipsec-vpn, обеспечивающий графическую оболочку для упрощенной настройки подключения.
Начнём сборку элементов поэтапно, но перед этим установим все необходимые пакеты для непосредственной работы VPN:
sudo apt-get install xl2tpd strongswan libp11-3
Установка ПО для работы с токенами
Установите последнюю версию библиотеки librtpkcs11ecp.so с сайта, также библиотеки для работы со смарт-картами:
sudo apt-get install pcscd pcsc-tools opensc libengine-pkcs11-openssl
Подключите Рутокен и проверьте, что он распознается системой:
pkcs11-tool --module /usr/lib/librtpkcs11ecp.so -O -l
Установка пропатченного ppp
UPD: предложенные нами изменения были приняты начиная с версии pppd 2.4.9. Поэтому пакет pppd можно взять из репозиториев.
sudo apt-get -y install git make gcc libssl-dev
git clone "https://github.com/jjkeijser/ppp"
cd ppp
./configure --prefix /usr
make -j4
sudo make install
Установка клиента L2tpIpsecVpn
В данный момент клиента тоже нужно собирать из исходников. Делается это с помощью следующей последовательности команд:
sudo apt-get -y install git qt5-qmake qt5-default build-essential libctemplate-dev libltdl-dev
git clone "https://github.com/Sander80/l2tp-ipsec-vpn"
cd l2tp-ipsec-vpn
make -j4
sudo make install
Настройка клиента L2tpIpsecVpn
Запускаем установленный клиент:
После запуска у вас должен открыться апплет L2tpIpsecVPN. Нажмём на него правой кнопкой мыши и произведём настройку соединения:
Для работы с токенами, в первую очередь, укажем путь opensc движка OpenSSL и PKCS#11 библиотеки. Для этого откройте вкладку "Preferences" для настройки параметров openssl:
.
Закроем окно настроек OpenSSL и перейдём к настройке сети. Добавим новую сеть, нажав на клавишу Add… в панели настроек и введите имя сети:
После этого данная сеть станет доступна в панели настроек. Дважды кликнем правой кнопкой мыши по новой сети, чтобы настроить её. На первой вкладке необходимо произвести настройки IPsec. Зададим адрес сервера и общий ключ:
После этого переходим на вкладку настройки PPP и укажем там имя пользователя, под которым мы хотим зайти в сеть:
После этого откроем вкладку Properties и укажем путь до ключа, сертификата клиента и УЦ:
Закроем данную вкладку и выполним финальную настройку, для этого откроем вкладку "IP settings" и поставим галочку напротив опции "Obtain DNS server address automatically":
Данная опция позволит клиенту получать от сервера личный IP-адрес внутри сети.
После всех настроек закроем все вкладки и перезагрузим клиент:
Подключение к сети
После настроек можно произвести подключение к сети. Для этого откроем вкладку апплета и выберем сеть, к которой мы хотим подключиться:
В процессе установки соединения клиент попросит ввести нас PIN-код Рутокен:
Если в статус-баре появится оповещение о том, что соединение успешно установлено, значит, настройка была произведена успешно:
В противном случае стоит разобраться, почему соединение не было установлено. Для этого стоит посмотреть лог программы, выбрав в апплете команду "Connection information":
Настройка клиента Windows
Настройка клиента в Windows осуществляется гораздо проще, чем в Linux, т.к. весь необходимый софт уже встроен в систему.
Настройка системы
Установим все необходимые драйверы для работы с Рутокенами скачав их c оф. сайта.
Импорт корневого сертификата для аутентификации
Скачаем корневой сертификат сервера и установим в систему. Для этого откроем его и в открывшемся окне выберем опцию "Установить сертификат":
В открывшемся окне выберем установку сертификата для локального пользователя. Если хочется, чтобы сертификат был доступен всем пользователям на компьютере, то тогда следует выбрать установку сертификата на локальный компьютер:
Установим сертификат в хранилище доверенных корневых сертификатов УЦ:
После всех этих действий соглашаемся со всеми дальнейшими пунктами. Теперь система настроена.
Настройка VPN соединения
Для настройки VPN соединения перейдите в панель управления и выберите пункт для создания нового соединения.
Во всплывшем окне выберите опцию создания соединения для подключения к рабочему месту:
В следующем окне выберете подключение по VPN:
и введите данные VPN соединения, а также укажите опцию для использования смарт-карты:
На этом настройка не закончена. Осталось указать общий ключ для протокола IPsec, для этого перейдём на вкладку “Настройки сетевых подключений” и затем перейдём на вкладку “Свойства для данного соединения”:
В открывшемся окне перейдём на вкладку "Безопасность", укажем в качестве типа сети "Сеть L2TP/IPsec" и выберем "Дополнительные параметры":
В открывшемся окне укажем общий ключ IPsec:
Подключение
После завершения настройки можно попробовать подключиться к сети:
В процессе подключения от нас потребуют ввести PIN-код токена:
Мы с вами настроили безопасную VPN сеть и убедились в том, что это несложно.
Благодарности
Хотелось бы ещё раз поблагодарить наших коллег Василия Шокова и Александра Смирнова за совместно проделанную работу для упрощения создания VPN соединений для клиентов Linux.