Debian.pro/

Про Debian


Openvpn-сервер с удобной вебмордой. TL/DR — pritunl.

Некоторое время я искал вебморду для openvpn-сервера. Чуть было не написал «не простую, а золотую», но на самом деле ничего особенного — из хоть каких-то требований у меня было только 2:
— полноценное управление пользователями (хотя бы отзыв сертификата) — вот тут-то почти все морды и отсеивались
— деплой самого openvpn-сервера (минорно) и CA-шки, чтобы VPN можно было поднять побыстрее.

И я нашел почти идеальный вариант — называется pritunl. В общем-то дальше статью особого смысла читать нет =)
Пара картинок для понимания, как оно выглядит:
— раз
— два

Ладно, расскажу всё же, что умеет бесплатная версия (и потом — как её побыстрее поставить).
— умеет openvpn/wireguard-сервер (сама их запускает, по умолчанию — openvpn, про него и будет идти речь)
— умеет дополнительно спрашивать логин+пароль у клиента при подключении (пароль у них называется PIN).
— умеет 2 factor auth через google authenticator — не пробовал, но заявлено. Имейте в виду, что 2FA включается для всех аккаунтов сразу, и если у вас среди клиентов есть те, кто не поддерживает 2FA (банальный пример — сервер, который подключается к этой VPN), то они не смогут подключаться
— у всех клиентов — статические IP-адреса (удобно). client2client включен по умолчанию, имейте в виду — с одной стороны можно подцепить сервер в VPN и ходить на него напрямую по всем портам с других клиентов, с другой — на клиентах что-то может лишнее торчать в сеть
— маршруты можно выдавать кастомные, с default или без него.
— ну и самое главное — есть рубильник, отключающий пользователя (без удаления). Само собой, есть и удаление.

В принципе, у pritunl есть и платная версия (и нет, денег мне за статью они не платили — а жаль хД), она умеет какие-то интересные вещи. Но версия за $10/month не умеет ничего такого, чего нельзя настроить руками. Самая полезная фича там, пожалуй, возможность мышкой в вебе настроить роутинг в сеть через подключенного клиента (например, ваш шлюз в офисе подключается к VPN серверу, остальные клиенты VPN маршрутизируются через этот шлюз в локалку офиса). Удобно (серьёзно), но, повторюсь, такое и вручную делается без проблем. Ещё из полезных фич за $10 — отключение 2FA для отдельных клиентов.

Версия же за $50/month представляет из себя какой-то адовый комбайн, на котором можно наворотить любой сложности виртуальную сеть с failover-маршрутами, кластером VPN-серверов, пирингом с облачными сетями и хер его знает чем ещё — я там не все слова понял в описании, честно говоря.
Если строите корпоративную VPN-сеть и заколебались воротить openvpn-конфигами и ip ro add — можете попробовать, если денег выделят.

Дальше речь пойдет о бесплатной версии — всё же я больше рассматриваю здесь случай, когда нужно за 5 минут поднять VPN-сервер для пары-тройки человек. Да и даже если для одного — всё равно будет быстрее, чем самому ковырять easy-rsa. Ну и писать я буду про вариант с openvpn — wireguard на сервере в общем-то настраивается абсолютно также, нужно только галочку в вебе поставить и порт второй пробросить.
Так же стоит понимать, что особой паранойи в статье описано не будет. В конце я в общих чертах напишу, что я делаю для хоть какой-то безопасности, но без подробностей.

Итак, вам понадобится:
— KVM-виртуалка или железный сервер, минимум 1 штука
— любой дистрибутив, где есть docker и compose (да-да, скатился)
— какой-нибудь домен для вебморды, чтобы получить на него сертификат

В идеальном случае нам нужна чистая система, но совсем не обязательно, просто читайте комментарии в compose-файле (копипастом сработает только если у вас порты 80/443 не заняты).

Ставим docker и compose:

user@host:~$ apt-get install docker-compose docker.io bridge-utils

Создадим пару необходимых каталогов:

user@host:~$ mkdir -p /var/lib/vpn/db /etc/vpn

Создаём compose.yml, например /etc/vpn/docker-compose.yml с примерно таким содержимым (не забудьте, что у yml важны пробелы/табуляция):

version: '3'

services:
  mongo:
    image: mongo:4.4
    container_name: pritunldb
    hostname: pritunldb
    networks:
      vpcbr:
        ipv4_address: 172.17.0.2
    volumes:
      - /var/lib/vpn/db:/data/db

  pritunl:
    # следующие 2 строки нужны только в том случае, если вы собираетесь использовать отдельный nginx поверх вебморды
    environment:
      - REVERSE_PROXY: true
    image: goofball222/pritunl:latest
    container_name: pritunl
    hostname: pritunl
    depends_on:
      - mongo
    networks:
      vpcbr:
        ipv4_address: 172.17.0.3
    privileged: true
    sysctls:
      - net.ipv6.conf.all.disable_ipv6=0
    links:
      - mongo
    volumes:
      - /etc/localtime:/etc/localtime:ro
    ports:
      # будущий порт vpn-сервера
      - 1194:1194
      - 1194:1194/udp
      # 80-й порт пробрасываем только если собираетесь использовать letsencrypt внутри панели
      # ну то есть, скорее всего, если у вас нет отдельного nginx-а на хосте и letsencrypt рядом
      - 80:80
      # 443 порт - порт самой вебморды.
      # если на хосте нет nginx и нужно побыстрее - пробрасывайте прямо здесь.
      - 443:443
    environment:
      - TZ=UTC

networks:
  vpcbr:
    driver: bridge
    ipam:
      config:
        - subnet: 172.17.0.0/24
        #gateway: 172.17.0.1

Делаем пробный запуск:

user@host:~$ /usr/bin/docker-compose -f /etc/vpn/docker-compose.yml up

Если что-то ругается про iptables — рестартните docker.
Если начало активно гадить в консоль — всё хорошо, можно продолжать. Через полминуты-минуту запустится вебморда на https://server. Только повесьте туда домен какой-нибудь, чтобы сертификат валидный получить.
Если всё пошло хорошо, то на вебморде вы увидите надпись «Use «sudo pritunl default-password» to get default login information». Давайте сделаем:

user@host:~$ docker exec -it $(docker ps -f name=pritunl$ -q) /usr/bin/pritunl default-password
...
Administrator default password:
  username: "pritunl"
  password: "..."

Используем эти данные для входа в вебморду.
После первого входа по default-паролю откроется форма «Initial Setup». В целом там всё понятно, спросят username и пароль (для входа в вебморду), внешний ipv4, внешний ipv6 (будут фигурировать в конфигах vpn для клиентов), web-console порт (не забудьте поменять его и в docker-compose.yml, если поменяете здесь) и домен, на который панель попытается получить сертификат в letsencrypt (сработает только если публично доступен 80-й порт из контейнера).
Заполняем, жмём save, идём покурить.

Ну и осталось понажимать кнопки в вебморде. Я постараюсь описать всё без скриншотов (лень же верстать статью потом, ну), там в начале была парочка для понимания.
Итак, в вебморде закрываем глаза и жмём по очереди:
— Users -> Add Organization, добавляем
— Servers -> Add server. Здесь порт обязательно должен совпадать с портом в compose.yml (у нас был 1194). Остальное сами решайте
— На той же странице жмём Attach Organisation — выбирать там будет особо не из чего, просто добавляем связь
— по вкусу удаляем маршрут для 0.0.0.0/0 внизу, добавляем другие маршруты
— жмем «Start server»
— Возвращаемся в Users и жмем либо «Bulk Add Users», либо «Add user»
— жмём кнопку «Download profile» у нужных пользователей, скачается tar-ник с .ovpn-файлом внутри, раздаём ovpn-ы пользователям
Дальше всем всё должно быть понятно, думаю.

Теперь в консоли, где запускали docker-compose жмите ctrl-c.
Создаём systemd-unit (дада, compose через systemd, я больной ублюдок и всё такое, но а что делать?), например /etc/systemd/system/vpn.service

[Unit]
Description=Some usefull text
After=docker.service
BindsTo=docker.service

[Service]
Type=simple
ExecStart=/usr/bin/docker-compose -f /etc/vpn/docker-compose.yml up
ExecStop=/usr/bin/docker-compose -f /etc/vpn/docker-compose.yml down
Restart=on-failure
RestartSec=10s
User=root
Group=root

[Install]
WantedBy=multi-user.target

Стопаем корректно compose до конца:

user@host:~$ /usr/bin/docker-compose -f /etc/vpn/docker-compose.yml down

Пинаем systemctl, включаем автозапуск, запускаем сервис:

user@host:~$ systemctl daemon-reload; systemctl enable vpn; systemctl start vpn

(кстати, на тестовой машинке что-то было поломано и здесь опять понадобилось делать docker restart — у вас тоже такое может случиться).
Всё, можно ребутаться, проверять, пользоваться и тыды.

Теперь о безопасности.
В первую очередь, конечно же, стоит каталог /var/lib/vpn/db убрать в зашифрованный раздел или LUKS image file (так и гуглится). Сам каталог будет занимать около пятисот мегабайт, хотя может со временем и вырастет — логи и вот это вот всё. Но стопнуть service vpn и перекинуть все данные в image побольше не проблема в общем-то.
Возможно, и в /var/lib/docker останется что-то, что не мешало бы зашифровать, но тут уже сами смотрите — в базе-то точно есть сертификаты, логины, хеши паролей и так далее.
Второй момент — я бы всё же рекомендовал использовать отдельно стоящий nginx c proxy_pass в https://172.17.0.3 (если адреса не меняли). Таким образом вы сможете настроить дополнительную авторизацию — по basic_auth или адресам, или ещё как.
Можно поступить ещё проще — вообще не пробрасывать наружу 443-порт, если лень ставить nginx. Ходить в саму вебморду можно при помощи sshuttle (во время изначальной настройки), а потом она и так будет доступна внутри VPN по серому адресу https://172.17.0.3 (маршрут только добавьте сюда клиентам, если дефолтный удалили). Ну или ещё проще вариант — сначала пробросить 443-порт, настроить VPN, подключиться к VPN, убрать проброс порта наружу (и сертификат не будет смысла получать, его на серый IP lets не выдаст, если только сами на DNS что-то нагородите с вьюхами — но зачем тогда вам вообще читать мои смешные рассуждения о том, как обезопасить вебморду?).

Как-то так.


Комментарии (4):

  1. yahan :

    Да достойный продукт. Не без ляпов, конечно. Много что разработчика годами не исправляют.
    Но тоже на нем остановился.

    Непонравилось, что с Mikrotik его никак не подружить.
    Остальное решаемо, много чего в монге можно по настройкам подправить, да и сам движок на pyton часть настроек там запрятана.

  2. > Непонравилось, что с Mikrotik его никак не подружить.
    У микрота openvpn не настоящий, к сожалению )
    Но вообще — почему не получилось-то? Pritunl вроде TCP openvpn умеет

  3. Pavel :

    А я консольку больше люблю: https://github.com/angristan/openvpn-install и не надо с easy-rsa возиться, ccd конфиги для каждого клиента, управление доступом череp firewall ufw в файле /etc/ufw/before.rules

  4. Уже слишком часто списком пользователей стали рулить не-технари вообще.

    У меня одна инсталляция крутится, там вообще ген. директор пользователями рулит. В таких случаях лучше всё же вебморду натянуть)

Написать комментарий