Security Lab

WireGuard через веб-морду: ставим wg-easy на Ubuntu 24 за 15 минут

WireGuard через веб-морду: ставим wg-easy на Ubuntu 24 за 15 минут

Ручной WireGuard — это двадцать команд в терминале, ковыряние ключей через cat и правка wg0.conf в nano. Админы так ставили годами. Но есть способ в десять раз короче: контейнер wg-easy с графическим интерфейсом и генерацией QR-кодов по клику. Ниже — пошагово с граблями, о которых молчит официальная документация.

Что понадобится

  • VPS с Ubuntu 24.04, минимум 512 МБ ОЗУ и доступ от root.
  • Внешний IP сервера (в примере ниже — 10.10.10.10, подставьте свой).
  • SSH-клиент: PuTTY, встроенный терминал macOS или Windows Terminal.
  • 15 минут и желание не заниматься ерундой.

Шаг 1. Обновить систему и поставить Docker

Первая команда — обновление пакетов. Вторая — официальный установщик Docker от самой компании Docker, а не тот огрызок, что лежит в репозиториях Ubuntu.

sudo apt update && sudo apt upgrade -y
 curl -fsSL https://get.docker.com | sudo sh
 sudo docker --version

Последняя команда покажет версию — что-то вроде Docker version 29.4.0. Значит встало.

⚠ Грабли №1. На свежем VPS apt часто ругается: «Could not get lock /var/lib/dpkg/lock-frontend. It is held by process 1584». Это фоновый unattended-upgrades тянет обновления безопасности. Подождите 2–5 минут и повторите. Если висит дольше — посмотрите, жив ли процесс: ps aux | grep apt. Мёртвый убивается через sudo kill 1584, дальше sudo rm /var/lib/dpkg/lock-frontend и sudo dpkg --configure -a.

Шаг 2. Сгенерировать bcrypt-хэш пароля

В версии wg-easy v14 разработчики запретили передавать пароль в открытом виде через переменную окружения. Теперь принимается только его криптографический отпечаток — bcrypt-хэш. Генерируется одной командой через Python:

sudo apt install python3-pip -y
 pip install bcrypt --break-system-packages
 python3 -c "import bcrypt; print(bcrypt.hashpw(b'ВашПароль123!', bcrypt.gensalt()).decode())"

Вместо ВашПароль123! — свой пароль. На выходе получите строку вида:

$2b$12$KYum4CSmy2IeYG7K8Y4kPu7rUiBJ99yJZvSe6Ihv6bQk0P8vK7TX6

Сохраните и хэш, и сам пароль. Хэш уйдёт в контейнер. Пароль будете вводить в веб-интерфейсе.

Шаг 3. Запустить контейнер wg-easy

Команда длинная, но её надо выполнить один раз. Подставьте свой внешний IP вместо 10.10.10.10 и свой хэш в PASSWORD_HASH:

sudo docker run -d 
   --name=wg-easy 
   -e LANG=ru 
   -e WG_HOST=10.10.10.10 
   -e PASSWORD_HASH='$2b$12$KYum4CSmy2IeYG7K8Y4kPu7rUiBJ99yJZvSe6Ihv6bQk0P8vK7TX6' 
   -e PORT=51821 
   -e WG_PORT=51820 
   -v ~/.wg-easy:/etc/wireguard 
   -p 51820:51820/udp 
   -p 51821:51821/tcp 
   --cap-add=NET_ADMIN 
   --cap-add=SYS_MODULE 
   --sysctl="net.ipv4.conf.all.src_valid_mark=1" 
   --sysctl="net.ipv4.ip_forward=1" 
   --restart unless-stopped 
   ghcr.io/wg-easy/wg-easy
⚠ Грабли №2. Хэш bcrypt начинается с $2b$. В двойных кавычках bash попытается подставить переменные $2 и $b — пароль сломается. Только одинарные кавычки. Если на выходе контейнер в цикле Restarting и в логах — invalid credentials, дело именно в этом.

Проверяем, что запустилось:

sudo docker ps

В статусе должно быть Up N seconds (health: starting). Надпись Restarting — плохой знак, смотрите логи через sudo docker logs wg-easy.

Шаг 4. Открыть порты в брандмауэре

UDP 51820 — это сам туннель WireGuard. TCP 51821 — веб-интерфейс.

sudo ufw allow OpenSSH
 sudo ufw allow 51820/udp
 sudo ufw allow 51821/tcp
 sudo ufw enable
Совет. Команда OpenSSH в первой строке — не украшение. Без неё при включении ufw вы отвалитесь от сервера и не сможете зайти повторно. SSH открывается первым, всегда.

Шаг 5. Зайти в веб-интерфейс и добавить клиента

Открываем в браузере http://10.10.10.10:51821, вводим пароль. Видим пустой список клиентов. Жмём кнопку «+ New», пишем имя (например, phone), получаем QR-код и файл .conf.

На телефоне: приложение WireGuard из магазина, кнопка «+» → «Сканировать QR-код». На ноутбуке: скачиваем файл, импортируем через клиент WireGuard для Windows, macOS или Linux.

Проверка работы одна: заходим на 2ip.ru с включённым туннелем. Адрес совпал с IP сервера? Всё поднялось.

Грабли, о которых молчит документация

Имя сетевого интерфейса

У ручного WireGuard в wg0.conf есть правила NAT с указанием интерфейса. На VPS он может называться ens3, eth0, enp1s0 или ещё как-то. Узнать своё имя: ip -o -4 route show to default | awk '{print $5}'. У wg-easy этот геморрой скрыт внутри контейнера — ещё один плюс в его копилку.

Старый wg0.conf от предыдущих попыток

Если раньше возились с ручной установкой и пакет wireguard уже стоит, в /etc/wireguard/ лежит старый конфиг с другим портом. Перед запуском wg-easy остановите старый сервис: sudo systemctl stop wg-quick@wg0 && sudo systemctl disable wg-quick@wg0. Иначе два WireGuard подерутся за порт 51820.

Провайдер режет UDP

Некоторые хостеры блокируют UDP на нестандартных портах либо требуют открыть их в панели управления, а не только в ufw. Если docker ps говорит «всё ок», веб-интерфейс доступен, а VPN не подключается — проверьте панель провайдера. Beget, Timeweb, ВДСина — у каждого свои правила.

Обслуживание: шпаргалка команд

sudo docker logs wg-easy          # посмотреть логи
 sudo docker restart wg-easy       # перезапустить
 sudo docker stop wg-easy          # остановить
 sudo docker start wg-easy         # запустить
 sudo docker rm -f wg-easy         # снести контейнер

Данные клиентов и ключи живут в ~/.wg-easy на хосте, не внутри контейнера. Снесёте контейнер — настройки останутся. Захотите обновить образ: sudo docker pull ghcr.io/wg-easy/wg-easy, потом sudo docker rm -f wg-easy и заново запустите команду из Шага 3.

Часто задаваемые вопросы

Чем wg-easy лучше ручной установки WireGuard?

Графический интерфейс, QR-коды по клику, добавление и удаление клиентов мышкой, статистика трафика в реальном времени. Ручной вариант даёт те же функции через редактирование конфигов и перезапуск службы. За те же полчаса вы в wg-easy поднимете пять клиентов, а в ручном — один.

Насколько это безопасно?

Криптография та же — WireGuard сам по себе. Веб-интерфейс закрыт паролем через bcrypt. Риск — порт 51821 смотрит в интернет. Для серьёзного использования закройте его через iptables и оставьте доступ только со своего IP либо пробрасывайте через SSH-туннель: ssh -L 51821:localhost:51821 root@10.10.10.10, потом localhost:51821 в браузере.

Работает ли это на Ubuntu 22.04 или Debian 12?

Работает на любом дистрибутиве, где запускается Docker. Инструкция одинакова для Ubuntu 22.04, 24.04, Debian 11, 12 и CentOS Stream. Меняется только менеджер пакетов (apt на dnf) и имя файрвола (ufw или firewalld).

Почему контейнер в цикле Restarting?

В 90% случаев — из-за пароля. Либо забыли перейти на PASSWORD_HASH (старый PASSWORD в v14 запрещён), либо bash съел знаки доллара из хэша. Лекарство: sudo docker logs wg-easy покажет точную строку ошибки. Вторая по популярности причина — занятый порт 51820, если раньше ставили ручной WireGuard.

Сколько клиентов тянет одна виртуалка?

На VPS с 1 ГБ ОЗУ и одним виртуальным ядром — 50 одновременных подключений без просадки. WireGuard дико экономичен. Узкое место — не процессор, а канал хостера.

Что делать, если забыл пароль?

Генерируете новый bcrypt-хэш, сносите контейнер через docker rm -f wg-easy, запускаете заново с новым PASSWORD_HASH. Конфиги клиентов в ~/.wg-easy останутся живы, переподключаться никому не придётся.

Можно ли получить доступ через доменное имя вместо IP?

Можно и нужно. Настройте A-запись в DNS (например, vpn.example.ru → IP сервера), подставьте домен в WG_HOST при запуске контейнера. Сверху накрутите reverse proxy через Nginx Proxy Manager или Caddy с Let's Encrypt, чтобы веб-интерфейс работал по HTTPS. На это уходит ещё 20 минут, но появляется зелёный замочек вместо предупреждения о небезопасном соединении.


Alt text
Обращаем внимание, что все материалы в этом блоге представляют личное мнение их авторов. Редакция SecurityLab.ru не несет ответственности за точность, полноту и достоверность опубликованных данных. Вся информация предоставлена «как есть» и может не соответствовать официальной позиции компании.
GIS
Газинформ
Сервис
SafeERP
Полный контроль безопасности 1С
Мониторинг платформы и анализ кода в едином интерфейсе
Подробнее
Реклама. 18+ ООО «Газинформсервис»
ОГРН 1047833006099

Юрий Кочетов

Здесь я делюсь своими не самыми полезными, но крайне забавными мыслями о том, как устроен этот мир. Если вы устали от скучных советов и правильных решений, то вам точно сюда.