Собственный Strongswan IPsec VPN на базе Ubuntu 16.04 LTS

С 1 ноября в России действует закон, позволяющий заблокировать любой сервис для обхода блокировок из реестров Роскомнадзора; все подряд: анонимайзеры, тор, VPN и различные расширения для браузеров.

Закон предусматривает важное исключение: «не запрещается использование анонимайзеров и сервисов VPN при условии, что круг пользователей заранее определен их владельцами и использование осуществляется в технологических целях обеспечения деятельности лица».

Напомню лишь два важных факта. VPN-сервисы, находящиеся за пределами страны, имеют полное право не читать российское законотворчество. Аргумент сомнительный: ведомству глубоко плевать — заблокируют, и дело с концом.

Важнее другое. Требования регулятора не относятся к частным лицам. Никто не запрещает вам арендовать сервер за пределами страны, настроить на его основе VPN и пользоваться им так, как сочтете нужным. (В том числе выдать реквизиты для доступа самому широкому кругу лиц.)

NB!

Необходимый уровень подготовки: средний. Вам понадобятся:

  • знакомство с DNS1 и теорией регистрации доменных имен;
  • знакомство с SSH2 и опыт работы в командной строке;
  • виртуальный выделенный сервер3.

Если насчет последнего пункта особых предпочтений нет, воспользуйтесь промо-кодом DigitalOcean (сто долларов стартового баланса после регистрации по ссылке!).

Приготовления

Определитесь с местоположением сервера. В общем случае берите тот, что географически ближе. Если же VPN нужен для использования конкретного сервиса (например, Netflix) — заводите сервер в одной с ним стране.

Для собственного VPN я зарегистрировал домен goldfinch.im; сам с собой договорился, что буду поддерживать несколько серверов (по количеству нужных мне стран). Завел поддомен g1.goldfinch.im для одного из них. После создал сервер с Ubuntu 16.04 LTS. Получил IP-адрес 178.62.195.248, который использовал для сопоставления в DNS. Настроил почту для домена и завел ящик postmaster@goldfinch.im.

Нам нужна виртуальная частная сеть с адресацией 10.10.10.0/244, внутри которой, в качестве DNS-сервера, будет использоваться гугловый 8.8.8.85 (в реальной жизни решение так себе, но для примера сойдет).

Подключаться будем по логину anonymous и аналогичному паролю.

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

Системные настройки

Убедитесь, что файрвол не содержит правил, а также установите пакет software-properties-common, который позволит подключать внешние репозитории:

sudo iptables -F
sudo apt-get update
sudo apt-get install -y software-properties-common

Настройка ядра Linux

Готовый VPN будет использовать NAT6 для обработки интернет-трафика клиентов. Для корректной работы потребуется разблокировать пересылку пакетов и отключить ICP-редиректы. Убедитесь, что в файле /etc/sysctl.conf присутствуют следующие параметры и им присвоены верные значения:

net.ipv4.ip_forward = 1
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.rp_filter = 0
net.ipv4.conf.default.accept_source_route = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.icmp_ignore_bogus_error_responses = 1

Конфигурация межсетевого экрана

Чтобы правила обработки подключений восстанавливались после перезагрузки, необходимо прописать все инструкции в файл /etc/rc.local (до строки exit 0).

Должны приниматься подключения по протоколу UDP7 на портах 500 (для IKE) и 4500 (для NAT), а также по протоколу ESP8 — на всех:

iptables --append INPUT --protocol udp --destination-port 500 --jump ACCEPT
iptables --append INPUT --protocol udp --destination-port 4500 --jump ACCEPT
iptables --append INPUT --protocol esp --jump ACCEPT

Для корректной работы NAT потребуется еще пара инструкций:

iptables -t nat -A POSTROUTING -j SNAT --to-source 178.62.195.248 -o eth+
for vpn in /proc/sys/net/ipv4/conf/*; do echo 0 > $vpn/accept_redirects; echo 0 > $vpn/send_redirects; done

В итоге файл /etc/rc.local должен выглядеть примерно так:

#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.

iptables --append INPUT --protocol udp --destination-port 500 --jump ACCEPT
iptables --append INPUT --protocol udp --destination-port 4500 --jump ACCEPT
iptables --append INPUT --protocol esp --jump ACCEPT

iptables -t nat -A POSTROUTING -j SNAT --to-source 178.62.195.248 -o eth+
for vpn in /proc/sys/net/ipv4/conf/*; do echo 0 > $vpn/accept_redirects; echo 0 > $vpn/send_redirects; done

exit 0

Сохраните изменения и перезагрузите сервер:

sudo shutdown -r now

Подтверждение подлинности и сертификат X.5099

Клиенту, прежде всего, нужно убедиться в том, что сервер подлинный. Другими словами, исключить возможность того, что какой-то другой сервер «притворяется» нашим (такая «подмена» выполняется при атаках класса MITM10).

Подобную проверку проводят все клиенты защищенных протоколов (SSH, TSL, SSL и прочие). В частности, ваш браузер сделал то же самое перед тем, как открыть эту страницу. Для подтверждения подлинности, как и браузер, будем использовать сертификат X.509 со стойкой сигнатурой RSA/ECDSA.

Получить сертификат можно в действующем удостоверяющем центре, которые прописаны как доверенные в большинстве операционных систем. За деньги подобный сертификат вам предложат Comodo, Symantec, GlobalSign; бесплатно выручат Wosign, StartSSL или Let’s Encrypt.

Существует и более сложный путь — собственная инфраструктура публичных ключей11. Проще говоря, вы сами становитесь удостоверяющим центром. Это накладывает необходимость добавлять корневой сертификат в операционную систему каждого устройства, которое будет подключаться к нашему VPN. В качестве преимущества будет доступна возможность использовать сертификаты для аутентификации клиентов (это надежнее и в чем-то удобнее логинов и паролей). Изучите инструкцию Remy van Elst, чтобы пройти этот квест на повышенном уровне сложности.

В этом руководстве используется простой (и бесплатный) способ — средства Let’s Encrypt. Чтобы работать с ними, потребуется утилита Certbot из официального репозитория:

sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install -y certbot

К этому моменту домен должен быть делегирован и сопоставлен с IP-адресом. С помощью Certbot получаем сертификат на наш первый сервер g1.goldfinch.im:

sudo certbot certonly --standalone --agree-tos -m postmaster@goldfinch.im -d g1.goldfinch.im

По окончании процедуры, в директории /etc/letsencrypt/live/g1.goldfinch.im появились файлы: chain.pem — корневой и промежуточный сертификаты, cert.pem — сертификат сервера и privkey.pem — приватный ключ.

Установка и настройка Strongswan

IPsec12 — набор необходимых для VPN протоколов — встроен в ядро Linux; понадобится лишь установить демон для работы с ними. На выбор представлены Openswan, Libreswan и Strongswan; мы воспользуемся последним. Установим сам демон и набор плагинов libcharon-extra-plugins для аутентификации клиентов (содержит необходимый нам EAP-MSCHAPv2):

sudo apt-get install -y strongswan libcharon-extra-plugins

После установки обратите внимание на структуру директорий внутри /etc/ipsec.d; нас интересуют три из них: cacerts предназначена для корневых сертификатов удостоверяющих центров, certs — для сертификатов X.509 и PGP, а private — для приватных ключей RSA и ECDSA.

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

sudo cp /etc/letsencrypt/live/g1.goldfinch.im/chain.pem /etc/ipsec.d/cacerts/ca.pem && sudo chmod 644 /etc/ipsec.d/cacerts/ca.pem
sudo cp /etc/letsencrypt/live/g1.goldfinch.im/cert.pem /etc/ipsec.d/certs/certificate.pem && chmod 644 /etc/ipsec.d/certs/certificate.pem
sudo cp /etc/letsencrypt/live/g1.goldfinch.im/privkey.pem /etc/ipsec.d/private/key.pem && chmod 644 /etc/ipsec.d/private/key.pem

Обратите внимание: после обновления сертификата процедуру копирования файлов необходимо повторить.

Настройка демона

Замените содержимое файла /etc/ipsec.conf на приведенный ниже шаблон. Изучите описание параметров подключения на сайте Strongswan и, при необходимости, внесите изменения.

# ipsec.conf - strongSwan IPsec configuration file

config setup
  #  Allows few simultaneous connections with one user account.
  #  By default only one active connection per user allowed.
  #  This option also usefull if you have limited rightsourceip pool and want to kick your ghost connection while reconnecting.
  uniqueids=no

  # Increase debug level
  #charondebug="ike 2, knl 2, cfg 2, net 2, esp 2, dmn 2,  mgr 2"

conn %default
  keyexchange=ikev2

  # More advanced ciphers. Uncomment if you need it.
  # Default ciphers will works on most platforms.
  #ike=aes128-sha1-modp1024,aes128-sha1-modp1536,aes128-sha1-modp2048,aes128-sha256-ecp256,aes128-sha256-modp1024,aes128-sha256-modp1536,aes128-sha256-modp2048,aes256-aes128-sha256-sha1-modp2048-modp4096-modp1024,aes256-sha1-modp1024,aes256-sha256-modp1024,aes256-sha256-modp1536,aes256-sha256-modp2048,aes256-sha256-modp4096,aes256-sha384-ecp384,aes256-sha384-modp1024,aes256-sha384-modp1536,aes256-sha384-modp2048,aes256-sha384-modp4096,aes256gcm16-aes256gcm12-aes128gcm16-aes128gcm12-sha256-sha1-modp2048-modp4096-modp1024,3des-sha1-modp1024!
  #esp=aes128-aes256-sha1-sha256-modp2048-modp4096-modp1024,aes128-sha1,aes128-sha1-modp1024,aes128-sha1-modp1536,aes128-sha1-modp2048,aes128-sha256,aes128-sha256-ecp256,aes128-sha256-modp1024,aes128-sha256-modp1536,aes128-sha256-modp2048,aes128gcm12-aes128gcm16-aes256gcm12-aes256gcm16-modp2048-modp4096-modp1024,aes128gcm16,aes128gcm16-ecp256,aes256-sha1,aes256-sha256,aes256-sha256-modp1024,aes256-sha256-modp1536,aes256-sha256-modp2048,aes256-sha256-modp4096,aes256-sha384,aes256-sha384-ecp384,aes256-sha384-modp1024,aes256-sha384-modp1536,aes256-sha384-modp2048,aes256-sha384-modp4096,aes256gcm16,aes256gcm16-ecp384,3des-sha1!

  # Dead peer detection will ping clients and terminate sessions after timeout
  dpddelay=300s
  dpdtimeout=2000s
  dpdaction=clear

  # Left is a server side
  leftcert=certificate.pem
  leftsendcert=always

  # Routes pushed to clients. If you don't have ipv6 then remove ::/0
  leftsubnet=0.0.0.0/0

  #rekey=no
  #reauth=no
  auto=add
  fragmentation=yes

  #authby=pubkey
  #left=%any
  #leftid=g1.goldfinch.im
  #right=%any

  # Right is a remote client side
  rightsourceip=10.10.10.0/24
  rightdns=8.8.8.8

  eap_identity=%identity

#conn IPSec-IKEv2
#  keyexchange=ikev2
#  auto=add

# Windows and BlackBerry clients usually goes here
conn ikev2-mschapv2
  rightauth=eap-mschapv2

# Apple clients usually goes here
conn ikev2-mschapv2-apple
  leftid=g1.goldfinch.im
  rightauth=eap-mschapv2

Обратите внимание на следующие параметры: leftcert определяет имя файла сертификата сервера из директории /etc/ipsec.d/certs, leftid — имя хоста, на который выдан сертификат, rightsourceip — пул адресов для клиентских подключений (можно выбрать подходящий диапазон из приватных), rightdns — DNS-сервер для VPN.

Перезапустите демон:

sudo ipsec restart

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

ipsec listcerts

Результат должен быть примерно таким:

List of X.509 End Entity Certificates:

  altNames:  g1.goldfinch.im
  subject:  "CN=g1.goldfinch.im"
  issuer:   "C=US, O=Let's Encrypt, CN=Let's Encrypt Authority X3"
  serial:    03:55:c6:43:89:a9:e4:6f:2b:10:73:6b:f7:4b:23:45:13:99
  validity:  not before Sep 21 23:50:00 2017, ok
             not after  Dec 20 23:50:00 2017, ok (expires in 25 days)
  pubkey:    RSA 2048 bits, has private key
  keyid:     94:b0:d3:80:5a:58:a7:33:ef:45:f2:68:a3:41:96:d5:82:1e:60:74
  subjkey:   57:52:b5:f4:2d:11:24:e0:f8:21:87:b6:81:00:f9:bb:18:03:54:6a
  authkey:   a8:4a:6a:63:04:7d:dd:ba:e6:d1:39:b7:a6:45:65:ef:f3:a8:ec:a1

Обратите внимание на фразу has private key, она должна быть обязательно.

Настройка аутентификации

Ранее мы уже установили комплект плагинов для аутентификации. Осталось создать по крайней мере один аккаунт. Все необходимые параметры задаются в файле /etc/ipsec.secrets (: RSA key.pem определяет имя файла приватного ключа из /etc/ipsec.d/private, последняя строка описывает единственного пользователя и его пароль):

# This file holds shared secrets or RSA private keys for authentication.

# RSA private key for this host, authenticating it to any other host
# which knows the public part.

# this file is managed with debconf and will contain the automatically created private key
# this string can be removed if you not use debconf for strongswan like in our case
include /var/lib/strongswan/ipsec.secrets.inc

# This is private key located at /etc/ipsec.d/private/key.pem
: RSA key.pem

# Create VPN users accounts
anonymous : EAP "anonymous"

Снова перезапустите демон:

sudo ipsec restart

Получить информацию о текущем статусе и загруженной конфигурации можно с помощью команды:

sudo ipsec statusall

Результат

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

Пара опций для параноиков

При желании можно писать системные логи в /dev/null:

sudo rm /var/log/syslog && sudo ln -s /dev/null /var/log/syslog
sudo rm /var/log/auth.log && sudo ln -s /dev/null /var/log/auth.log