- Опубликовано: 11 июл 2026
- 18
Свой VPN на VPS за полчаса: WireGuard без магии
Часть 7 из 14 · Серия «Сервер в бою»
Спросите людей, зачем они впервые арендовали VPS, — и «поднять свой VPN» уверенно войдёт в тройку ответов, где-то рядом с «хостить сайт». Причины житейские: не доверять Wi-Fi в кафе и аэропортах, иметь стабильный «домашний» IP из любой точки мира, дотягиваться до сервисов, которые капризничают к географии. А для читателей этой серии есть и четвёртая, самая вкусная причина: частная дверь на собственный сервер. Помните панель Netdata из статьи про мониторинг, которую я велел ни в коем случае не выставлять в интернет и обещал спрятать за VPN? Сегодня выполняем обещание.
Одна честная оговорка до старта, чтобы потом не было разочарований: VPN на своём VPS — это не анонимность. Сервер арендован на ваше имя и оплачен вашей картой; для провайдера кафе вы невидимы, но сам VPS — это просто вы с другим адресом. Наш VPN — про шифрование трафика в недоверенных сетях и про приватный доступ к своей инфраструктуре. Для этих задач он идеален.
Инструмент — WireGuard, и «без магии» в заголовке — принципиальная позиция. В интернете полно скриптов «VPN одной командой», которые набросают конфигов, — и оставят вас один на один с системой, которую вы не понимаете (а мы с первой статьи знаем, чем кончается администрирование непонятного). WireGuard тем и прекрасен, что магия ему не нужна: весь конфиг — десяток строк, и каждую мы напишем руками, понимая зачем.
Почему именно WireGuard
Старожилы жанра — OpenVPN и IPsec — это сотни тысяч строк кода, простыни конфигов и сертификатная бюрократия. WireGuard — примерно 4 тысячи строк, встроен прямо в ядро Linux (с версии 5.6 — ничего компилировать не надо), заметно быстрее на слабых VPS и построен на одной элегантной идее: связь устанавливается по обмену ключами, как в SSH. Никаких логинов, паролей и сертификатов: у каждой стороны есть приватный ключ и публичный; вы обмениваетесь публичными — и всё, стороны узнают друг друга криптографически. Точь-в-точь та же модель, что мы полюбили в статье про SSH-ключи, только для всего трафика.
Ещё из приятного: WireGuard молчалив. Он не отвечает на пакеты, не подписанные правильным ключом, — вообще. Сканер портов даже не увидит, что на UDP-порту что-то живёт. Ботам из третьей статьи тут ловить нечего: брутфорсить нечего, стучаться некуда.
Словарик на три термина
Вся ментальная модель WireGuard умещается в три понятия:
Interface — виртуальная сетевая карта wg0, которая появится и на сервере, и на телефоне/ноутбуке. У каждой — свой адрес в частной сети, которую мы придумаем сами: пусть будет 10.8.0.0/24. Сервер — 10.8.0.1, ваш ноутбук — 10.8.0.2, телефон — 10.8.0.3.
Peer — «собеседник». В конфиге сервера пиры — это клиенты; в конфиге клиента пир — сервер. Отношения равноправные, никакой клиент-серверной иерархии в протоколе нет — просто у «сервера» есть публичный IP, поэтому все звонят ему.
AllowedIPs — самая недопонятая настройка WireGuard и причина 80% вопросов «почему не работает». Запомните формулу: это не список разрешений, а таблица маршрутизации: «какие адреса назначения отправлять в этот туннель» (и заодно «от каких адресов принимать»). На клиенте AllowedIPs = 0.0.0.0/0 значит «весь мой трафик — в VPN», а AllowedIPs = 10.8.0.0/24 — «в VPN только частная сеть, остальное — как обычно». К этой развилке ещё вернёмся.
Сервер: конфиг в десять строк
Ставим и генерируем ключи:
apt install wireguard
cd /etc/wireguard
umask 077 # чтобы приватный ключ не был читаем всем подряд
wg genkey | tee server.key | wg pubkey > server.pub
Пишем /etc/wireguard/wg0.conf:
[Interface]
Address = 10.8.0.1/24
ListenPort = 51820
PrivateKey = <содержимое server.key>
# NAT: выпускаем трафик клиентов в интернет через сервер.
# eth0 замените на имя вашего внешнего интерфейса (смотрится через `ip a`)
PostUp = iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
Две строки PostUp/PostDown — единственное «сложное» место, поясню. Пакет от вашего телефона приходит на сервер с адресом 10.8.0.3 — интернет про такие адреса ничего не знает и ответ вернуть не сможет. MASQUERADE подменяет адрес отправителя на публичный IP сервера (это и есть NAT) — теперь для всего мира трафик выглядит как трафик самого VPS. А чтобы сервер вообще согласился пересылать чужие пакеты между интерфейсами, включаем форвардинг — вторая классическая забытая мелочь:
echo "net.ipv4.ip_forward=1" > /etc/sysctl.d/99-wireguard.conf
sysctl --system
Открываем UDP-порт в файрволе (ufw allow 51820/udp — или что у вас) и запускаем:
systemctl enable --now wg-quick@wg0
Сервер готов. Да, это правда всё.
Клиент: развилка «весь трафик или только сервер»
Генерируем ключи для первого клиента (можно тут же, на сервере):
wg genkey | tee laptop.key | wg pubkey > laptop.pub
Конфиг клиента — например, для варианта «весь трафик через VPN» (сценарий кафе и аэропортов):
[Interface]
Address = 10.8.0.2/24
PrivateKey = <содержимое laptop.key>
DNS = 1.1.1.1
[Peer]
PublicKey = <содержимое server.pub>
Endpoint = ваш-публичный-IP:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25
Вторая ветка развилки — split tunnel, «в VPN только частная сеть»: меняете одну строку на AllowedIPs = 10.8.0.0/24, и туннель используется исключительно для доступа к серверу, а YouTube и всё остальное идёт напрямую, не гоняя гигабайты через VPS. Для сценария «частная дверь к Netdata» это идеальный режим: быстро, дёшево по трафику, и никаких сюрпризов «почему у меня банк ругается на иностранный IP».
Осталось представить клиента серверу — дописываем в wg0.conf на сервере:
[Peer]
# Ноутбук
PublicKey = <содержимое laptop.pub>
AllowedIPs = 10.8.0.2/32
Обратите внимание на зеркальную логику AllowedIPs: на сервере для пира это «какие адреса живут за этим ключом» — строго его личный /32. Перезапускаем (systemctl restart wg-quick@wg0) — и проверяем с клиента:
ping 10.8.0.1 # сервер по частному адресу
wg show # на сервере: смотрим handshake
Появился latest handshake: N seconds ago — туннель жив. Для телефона всё ещё проще: ставим qrencode, показываем конфиг QR-кодом прямо в терминал —
qrencode -t ansiutf8 < phone.conf
— и приложение WireGuard на телефоне сканирует его камерой. Тридцать минут не истекли, а VPN уже работает.
И выполняем обещание: Netdata за частной дверью
Теперь красивый финал сюжета из четвёртой статьи. Netdata слушает порт 19999. Говорим ему слушать только VPN-интерфейс — в /etc/netdata/netdata.conf:
[web]
bind to = 10.8.0.1
Перезапускаем Netdata, закрываем 19999 в файрволе от внешнего мира — и панель открывается по адресу http://10.8.0.1:19999 только у устройств внутри туннеля. Никаких basic auth, никаких SSH-туннелей по памяти: подключил VPN — приборная панель твоя, отключил — её не существует. Тот же трюк работает для phpMyAdmin, панелей администрирования, staging-версий сайтов — всего, что должно быть доступно вам и не должно — интернету. Это, пожалуй, самый недооценённый режим использования личного VPN.
Подводные камни: полный список
Собрал всё, обо что реально спотыкаются, — включая то, на что наступал сам.
| Камень | Симптом | Лечение |
|---|---|---|
Забыт ip_forward |
Handshake есть, пинг до 10.8.0.1 есть, интернета нет | sysctl net.ipv4.ip_forward должен вернуть 1 |
| Не тот интерфейс в MASQUERADE | То же самое | Сверить eth0 в PostUp с выводом ip a (бывает ens3, enp1s0...) |
| Непонятый AllowedIPs | «Подключился к VPN — отвалился SSH к серверу по публичному IP» и прочие странности маршрутизации | Перечитать словарик: это таблица маршрутов, не «права доступа» |
| Клиент за суровым NAT (мобильная сеть, офис) | Туннель «засыпает»: работает, потом молчит до переподключения | PersistentKeepalive = 25 на клиенте — пустой пакет раз в 25 с держит пробитую в NAT дырку |
| MTU | Сайты открываются наполовину, SSH-сессия виснет на больших выводах, мелкие пинги ходят | MTU = 1380 в [Interface] клиента; классика поверх PPPoE и мобильных сетей |
| Утечка DNS | Трафик в туннеле, а DNS-запросы — мимо, старому провайдеру | Строка DNS = ... в конфиге клиента при full tunnel обязательна |
| UDP-порт зарезан сетью | Из дома работает, из офиса/отеля — нет | Сменить ListenPort на 443/udp — его режут реже |
SaveConfig = true |
Правки в wg0.conf таинственно исчезают | Эта опция перезаписывает конфиг состоянием из памяти при остановке. Либо она и wg set, либо правки файла руками — не смешивать |
| Файрвол-самострел | Включили «запретить всё, кроме VPN» и потеряли сервер | Правило из третьей статьи: новую сессию проверяем, старую не закрываем; UDP 51820 и SSH — в разрешённых до включения запретов |
Отдельно подчеркну камень с AllowedIPs и SSH, он коварнейший: если на клиенте стоит 0.0.0.0/0, то и SSH-соединение к серверу поедет через туннель. Обычно это нормально, но если туннель моргнёт — вы теряете и SSH. Держите в голове (и в заметках) аварийный обходной путь: VNC-консоль провайдера, наш старый друг из первой статьи, работает всегда.
Что в итоге
За полчаса и двадцать строк конфига вы получили: шифрование всего трафика в любых недоверенных сетях, стабильный личный IP, и — главное для нашей серии — частный контур инфраструктуры, куда переехала панель мониторинга и куда со временем переедет всё административное. Причём вы понимаете каждую строчку этой системы, а значит, сможете её чинить — WireGuard попадает под общую диагностику как обычный systemd-сервис: systemctl status wg-quick@wg0, journalctl -u wg-quick@wg0, wg show. Никакой магии — как и обещал.
В следующей статье вернёмся к веб-хозяйству. Один VPS — и три сайта, которые надо на нём разместить так, чтобы они не подрались: виртуальные хосты nginx, отдельные пулы PHP-FPM для каждого сайта, изоляция пользователей и права на файлы, при которых взлом одного WordPress не означает взлом всех соседей. Тема скучная ровно до первого инцидента — поэтому разберём её до.
- 1 Сервер упал в три ночи: разбор полётов без паники
- 2 Логи, которые говорят: учимся читать journalctl, nginx и syslog
- 3 Fail2ban и брутфорс: как перестать кормить ботов
- 4 Мониторинг для одного сервера: Uptime Kuma, Netdata и здравый смысл
- 5 Диск закончился внезапно: куда деваются гигабайты на VPS
- 6 Обновления без страха: apt upgrade, который ничего не сломает
- 7 Свой VPN на VPS за полчаса: WireGuard без магии вы здесь
- 8 Несколько сайтов на одном VPS: делим ресурсы без драки скоро
- 9 Тормозит сайт — виноват не хостинг: тюним nginx и PHP-FPM скоро
- 10 MySQL на маленьком VPS: почему база съедает всю память скоро
- 11 Кэширование на пальцах: Redis, FastCGI cache и когда хватит просто заголовков скоро
- 12 Cron, systemd-таймеры и скрипты: автоматизируем рутину сервера скоро
- 13 Деплой без FTP в 2026-м: git pull, хуки и простой CI/CD на своём VPS скоро
- 14 Переезд на другой VPS без даунтайма: чек-лист миграции скоро
Была статья полезной: