mysurik.ru

WireGuard VPN: как я настроил безопасный доступ к дому

До недавнего времени я заходил на домашний сервер через SSH с пробросом порта на роутере. Сознаюсь, это было небезопасно, но удобно. Пока однажды в логах не увидел подозрительные попытки входа из Китая. Тут я задумался.

Перебрав варианты: OpenVPN — слишком громоздкий, IPSec — боль, Tailscale — удобно, но зависит от внешнего сервера. Остановился на WireGuard. Настройка заняла 15 минут: установил, сгенерировал ключи, прописал пару строк в конфиг.

Теперь захожу на сервер через VPN из любой точки мира. И никаких открытых портов. Телефон, ноутбук, рабочий ПК — везде стоит WireGuard и подключается к дому за секунду.

Кстати, скорость не проседает вообще. На тестах разница между прямым соединением и через WireGuard — меньше пяти процентов.

Установка на сервер. Я сидел на Ubuntu 24.04, там WireGuard уже в ядре, ставить ничего не пришлось. Просто apt install wireguard-tools, и всё. Дальше — генерация ключей. На сервере я создал пару ключей, на каждом клиенте — свою. Ключи хранятся в /etc/wireguard/. Один файл — server.conf, второй — клиентский конфиг, который я раскидываю по устройствам.

Серверный конфиг у меня выглядит так: интерфейс wg0, приватный ключ сервера, адрес 10.0.0.1/24, порт 51820. Дальше секция Peer для каждого клиента: публичный ключ клиента, разрешённые адреса (allowed-ips) — для телефона это 10.0.0.2/32, для ноутбука 10.0.0.3/32, и так далее. Важный момент — PersistentKeepalive = 25. Без этого мобильный клиент разрывает соединение через пару минут неактивности, и потом не может переподключиться, потому что NAT на роутере забыл про проброс.

Клиентские конфиги я генерирую сам. На каждом клиенте свой приватный ключ, свой IP в подсети 10.0.0.0/24. В конфиге клиента: интерфейс с приватным ключом и адресом, Peer — публичный ключ сервера, эндпоинт (мой домен или IP с портом), allowed-ips = 0.0.0.0/0 (чтобы весь трафик шёл через VPN), и DNS — я ставлю 1.1.1.1 или свой AdGuard Home.

Первая проблема, с которой я столкнулся — файрвол. ufw по умолчанию блокирует входящие на 51820 порт. Пришлось добавить правило: ufw allow 51820/udp. Без этого WireGuard просто не отвечал на запросы клиентов, и я полчаса тупил, думая что не настроил ключи.

Вторая проблема — роутинг. Если ты хочешь, чтобы весь трафик шёл через VPN (включая интернет) — ставишь allowed-ips = 0.0.0.0/0 на клиенте. Но тогда домашний сервер становится шлюзом для всего трафика клиента. На сервере нужно включить IP forwarding. Я прописал net.ipv4.ip_forward=1 в sysctl.conf и добавил iptables правило на masquerade. Без этого трафик уходит в VPN, но обратно не возвращается — роутер сервера не знает, что отвечать на пакеты с адресами из подсети 10.0.0.0/24.

Третья проблема — DNS утечки. Когда я включил полный туннель на ноутбуке, DNS запросы всё равно летели напрямую к провайдеру, потому что systemd-resolved не перенаправлял их через VPN. Пришлось править resolvectl и прописывать DNS-сервер в конфиге WireGuard. На мобильных клиентах этой проблемы нет — там DNS настраивается в конфиге приложения.

Про телефоны. На iPhone WireGuard ставится из App Store, конфиг импортируешь по QR-коду. Я генерирую QR прямо в терминале: qrencode -t ansiutf8 < client.conf. На Android то же самое. Удобно: поднёс камеру, считал, готово. Kill switch. Если VPN упадёт, клиент должен блокировать весь трафик, чтобы не утекли данные. В WireGuard на десктопе это настраивается через флаг DisabledOnActivation для маршрута — чтобы без VPN никуда не ходило. На телефонах kill switch есть в официальном приложении. Про IPv6. У провайдера есть IPv6, и сначала клиенты пытались ходить в интернет через IPv6 напрямую, минуя VPN. Пришлось добавить в allowed-ips ещё и ::/0. Теперь и IPv6 трафик идёт через туннель. Мониторинг. WireGuard встроил простую команду wg show. Она показывает все пиры, их последнее подключение, переданные байты. Я добавил это в crontab — раз в час логирую, кто и когда подключался. Полезно для отладки. Бекап. Конфиги WireGuard хранятся в /etc/wireguard. Я добавил эту папку в список бекапов Proxmox. Потерять ключи — значит потерять доступ к серверу. Как бонус — я настроил доступ к своей локальной сети через VPN. То есть, подключившись к WireGuard, я могу зайти не только на сервер, но и на роутер, и на другие устройства в домашней сети. Для этого я добавил в allowed-ips подсеть 192.168.0.0/24. На сервере прописал iptables, чтобы форвардить трафик между wg0 и локальной сетью. Итог. WireGuard — это единственный VPN, который я настроил и забыл. Он работает годами без перезапуска, не жрёт память, не требует обслуживания. Если у тебя есть домашний сервер и ты до сих пор не поставил WireGuard — ты рискуешь. Поставь, это реально 15 минут. Кстати, советую всем, кто ставит WireGuard впервые — используй wg-easy. Это веб-морда, которая сама создаёт конфиги, показывает QR-коды и управляет клиентами. Я сначала крутил всё ручками, но для быстрого старта — самое то. Ставится в Docker одной командой. Ещё один момент, о котором молчат в инструкциях. Если у тебя динамический IP, а домен привязан к нему — WireGuard может не переподключаться после смены IP, если DNS не обновился. У меня так было: провайдер перезагрузил оборудование, IP сменился, и я потерял связь с сервером на полдня. Решение — использовать DDNS-клиент на сервере и обновлять DNS запись. Или использовать статический IP, если провайдер даёт. Сравнение с другими решениями. OpenVPN я ставил года три назад. Настройка заняла вечер, конфиги были на десять страниц, скорость упала вдвое. IPSec я даже не пробовал — говорят, там без бубна не разобраться. Tailscale я использую параллельно — он удобен для быстрых подключений, но не даёт контроля над инфраструктурой. WireGuard же — золотая середина. Просто, быстро, под твоим полным контролем. Про аварию. Однажды я обновил ядро на сервере и забыл перезагрузить WireGuard. Модуль ядра обновился, а wg-quick не перезапустился. Я думал, что VPN сломался, час перепроверял конфиги, пока не заметил, что wg0 интерфейса просто нет. Команда wg-quick down wg0 && wg-quick up wg0 решила проблему. Теперь после каждого обновления ядра проверяю. Что касается нескольких серверов. У меня есть VPS в Европе и домашний сервер. Оба объединены в mesh через WireGuard. Серверы видят друг друга, а я подключаюсь к любому из них и имею доступ ко всей сети. Это удобнее, чем поднимать туннели по отдельности. Ещё из полезного — PreSharedKey. Если хочешь дополнительную защиту от квантовых компьютеров (ну, мало ли), добавляешь предварительный общий ключ к каждому пиру. WireGuard генерирует его через wg genpsk. На производительность это не влияет, а безопасность повышает. Я добавил PSK всем клиентам — на всякий случай. И последнее. WireGuard не умеет сам переподключаться при обрыве, как OpenVPN. Если соединение разорвалось — клиент просто ждёт следующий handshake. PersistentKeepalive решает эту проблему частично, но если сервер перезагрузился, клиент узнает об этом только через 2-3 минуты. Я решил это написанием простого скрипта, который пингует сервер через wg0 и, если пинг не проходит, перезапускает интерфейс. Скрипт висит в cron на клиенте.

Расширю статью о WireGuard дополнительными деталями из опыта. До недавнего времени я заходил на домашний сервер через SSH с пробросом порта на роутере. Сознаюсь, это было небезопасно, но удобно. Пока однажды в логах не увидел подозрительные попытки входа из Китая. Тут я задумался. Проброс порта — это открытая дверь в ваш дом: любой сканер портов рано или поздно найдёт SSH, и начнётся перебор паролей. Заметки в логах про попытки из Китая стали той самой каплей, после которой я понял: так жить нельзя. Перебрав варианты: OpenVPN — слишком громоздкий, IPSec — боль, Tailscale — удобно, но зависит от внешнего сервера. Остановился на WireGuard. Настройка заняла 15 минут: установил, сгенерировал ключи, прописал пару строк в конфиг. Теперь захожу на сервер через VPN из любой точки мира. И никаких открытых портов. Телефон, ноутбук, рабочий ПК — везде стоит WireGuard и подключается к дому за секунду. Кстати, скорость не проседает вообще. На тестах разница между прямым соединением и через WireGuard — меньше пяти процентов. WireGuard — это современный VPN-протокол, который живёт прямо в ядре Linux. Он невесомый, быстрый и простой в настройке. Вместо сложных сертификатов и тонн конфигов — пара файлов с ключами. Вместо потери скорости — практически нулевые накладные расходы. После OpenVPN я не поверил своим глазам: вся настройка уместилась в конфиг на десять строк. Рекомендую начать с него всем, кто хочет защитить доступ к своему серверу.

Установка на сервер. Я сидел на Ubuntu 24.04, там WireGuard уже в ядре, ставить ничего не пришлось. Просто apt install wireguard-tools, и всё. Дальше — генерация ключей. На сервере я создал пару ключей, на каждом клиенте — свою. Ключи хранятся в /etc/wireguard/. Один файл — server.conf, второй — клиентский конфиг, который я раскидываю по устройствам. Серверный конфиг у меня выглядит так: интерфейс wg0, приватный ключ сервера, адрес 10.0.0.1/24, порт 51820. Дальше секция Peer для каждого клиента: публичный ключ клиента, разрешённые адреса (allowed-ips) — для телефона это 10.0.0.2/32, для ноутбука 10.0.0.3/32, и так далее. Важный момент — PersistentKeepalive = 25. Без этого мобильный клиент разрывает соединение через пару минут неактивности, и потом не может переподключиться, потому что NAT на роутере забыл про проброс. Установка на Ubuntu тривиальна: модуль ядра уже в системе, остаётся только инструменты. Генерация ключей — пара команд: wg genkey и wg pubkey. Каждый клиент имеет свою пару ключей, и на сервере для каждого прописывается его публичный ключ. Схема адресов — простая приватная подсеть 10.0.0.0/24: сервер получает 10.0.0.1, клиенты — остальные адреса. PersistentKeepalive отправляет короткий пакет каждые 25 секунд, чтобы NAT на роутере не забыл о соединении. Клиентские конфиги я генерирую сам. На каждом клиенте свой приватный ключ, свой IP в подсети 10.0.0.0/24. В конфиге клиента: интерфейс с приватным ключом и адресом, Peer — публичный ключ сервера, эндпоинт (мой домен или IP с портом), allowed-ips = 0.0.0.0/0 (чтобы весь трафик шёл через VPN), и DNS — я ставлю 1.1.1.1 или свой AdGuard Home. Клиентский конфиг зеркален серверному: приватный ключ клиента, адрес в подсети, и один Peer — сервер с его публичным ключом и адресом для подключения. allowed-ips решает, какой трафик уходить через туннель: 0.0.0.0/0 — весь трафик, или только подсети, куда нужен доступ. DNS можно указать прямо в конфиге — тогда все запросы уйдут через VPN. Первая проблема, с которой я столкнулся — файрвол. ufw по умолчанию блокирует входящие на 51820 порт. Пришлось добавить правило: ufw allow 51820/udp. Без этого WireGuard просто не отвечал на запросы клиентов, и я полчаса тупил, думая что не настроил ключи. Файрвол — первое, что блокирует VPN, и это самая частая ошибка новичков. По умолчанию ufw закрывает всё, кроме разрешённого. Одна команда ufw allow 51820/udp — и порт открыт. Симптом: клиент шлёт запросы, но сервер молчит. Проверка: sudo ufw status показывает, открыт ли порт. Запомните этот пункт — он сэкономит вам полчаса.

Вторая проблема — роутинг. Если ты хочешь, чтобы весь трафик шёл через VPN (включая интернет) — ставишь allowed-ips = 0.0.0.0/0 на клиенте. Но тогда домашний сервер становится шлюзом для всего трафика клиента. На сервере нужно включить IP forwarding. Я прописал net.ipv4.ip_forward=1 в sysctl.conf и добавил iptables правило на masquerade. Без этого трафик уходит в VPN, но обратно не возвращается — роутер сервера не знает, что отвечать на пакеты с адресами из подсети 10.0.0.0/24. Полный туннель — это когда весь интернет-трафик клиента идёт через ваш сервер. Это скрывает ваш IP и позволяет обходить блокировки, но требует двух вещей на сервере: включённого IP forwarding и правила masquerade в iptables. Иначе пакеты уходят в туннель, а ответы теряются. Проверка работает так: ping 8.8.8.8 через VPN — и сайт открывается в браузере. Третья проблема — DNS утечки. Когда я включил полный туннель на ноутбуке, DNS запросы всё равно летели напрямую к провайдеру, потому что systemd-resolved не перенаправлял их через VPN. Пришлось править resolvectl и прописывать DNS-сервер в конфиге WireGuard. На мобильных клиентах этой проблемы нет — там DNS настраивается в конфиге приложения. DNS утечки — скрытая проблема полных туннелей: сам трафик идёт через VPN, а DNS-запросы — напрямую провайдеру. Провайдер видит, какие сайты вы открываете. Решение — прописать DNS прямо в конфиге WireGuard и настроить resolvectl. На мобильных всё проще: DNS из конфига подхватывается приложением автоматически. Про телефоны. На iPhone WireGuard ставится из App Store, конфиг импортируешь по QR-коду. Я генерирую QR прямо в терминале: qrencode -t ansiutf8 < client.conf. На Android то же самое. Удобно: поднёс камеру, считал, готово. Настройка телефона — это минута: поставить приложение и отсканировать QR-код. Конфиг генерируется на сервере, код печатается в терминале, камера считывает — и VPN работает. Никаких файлов пересылать не нужно. Красивый и удобный процесс. Kill switch. Если VPN упадёт, клиент должен блокировать весь трафик, чтобы не утекли данные. В WireGuard на десктопе это настраивается через флаг DisabledOnActivation для маршрута — чтобы без VPN никуда не ходило. На телефонах kill switch есть в официальном приложении. Kill switch — страховка от утечек: если VPN разорвался, весь трафик блокируется, а не уходит напрямую провайдеру. Это важно, когда вы подключены к общественному Wi-Fi: без kill switch ваши данные летят в открытом виде. На телефонах функция встроена, на десктопе — настраивается маршрутом с DisabledOnActivation. Про IPv6. У провайдера есть IPv6, и сначала клиенты пытались ходить в интернет через IPv6 напрямую, минуя VPN. Пришлось добавить в allowed-ips ещё и ::/0. Теперь и IPv6 трафик идёт через туннель. IPv6 — частая ловушка: даже с полным туннелем IPv4, IPv6-трафик уходит мимо VPN. Всё потому, что allowed-ips = 0.0.0.0/0 покрывает только IPv4. Добавьте ::/0 — и IPv6 пойдёт через туннель. Проверка: ifconfig wg0 показывает адреса обоих протоколов. Мониторинг. WireGuard встроил простую команду wg show. Она показывает все пиры, их последнее подключение, переданные байты. Я добавил это в crontab — раз в час логирую, кто и когда подключался. Полезно для отладки. Команда wg show — это панель управления в терминале: все пиры, статус соединения, объём трафика. Пара строк в crontab — и история подключений пишется автоматически. Если что-то пойдёт не так, всегда есть логи, чтобы понять, что происходило. Просто и эффективно. Бекап. Конфиги WireGuard хранятся в /etc/wireguard. Я добавил эту папку в список бекапов Proxmox. Потерять ключи — значит потерять доступ к серверу. Бекап ключей — это вопрос не удобства, а доступа. Потеряли /etc/wireguard — потеряли VPN, а с ним и все подключения. Добавьте папку в бекапы сервера — и при любой аварии восстановите туннель за минуты. Ключи — единственная ценная часть конфигурации, всё остальное пересоздаётся. Как бонус — я настроил доступ к своей локальной сети через VPN. То есть, подключившись к WireGuard, я могу зайти не только на сервер, но и на роутер, и на другие устройства в домашней сети. Для этого я добавил в allowed-ips подсеть 192.168.0.0/24. На сервере прописал iptables, чтобы форвардить трафик между wg0 и локальной сетью. Доступ к домашней сети — это возможность управлять всеми устройствами из любой точки мира: роутер, NAS, умный дом, другие серверы. Одна подсеть в allowed-ips и правило форвардинга на сервере — и вы дома, даже находясь за тысячи километров. Итог. WireGuard — это единственный VPN, который я настроил и забыл. Он работает годами без перезапуска, не жрёт память, не требует обслуживания. Если у тебя есть домашний сервер и ты до сих пор не поставил WireGuard — ты рискуешь. Поставь, это реально 15 минут. Кстати, советую всем, кто ставит WireGuard впервые — используй wg-easy. Это веб-морда, которая сама создаёт конфиги, показывает QR-коды и управляет клиентами. Я сначала крутил всё ручками, но для быстрого старта — самое то. Ставится в Docker одной командой. wg-easy — это ускоренный старт для тех, кто не хочет разбираться в ключах. Веб-интерфейс сам генерирует конфиги, показывает QR-коды и управляет клиентами. Одна команда Docker — и всё работает. Для экспериментов — идеально, для полного контроля — лучше ручная настройка. Начните с wg-easy, а потом разберётесь с деталями. Ещё один момент, о котором молчат в инструкциях. Если у тебя динамический IP, а домен привязан к нему — WireGuard может не переподключаться после смены IP, если DNS не обновился. У меня так было: провайдер перезагрузил оборудование, IP сменился, и я потерял связь с сервером на полдня. Решение — использовать DDNS-клиент на сервере и обновлять DNS запись. Или использовать статический IP, если провайдер даёт. Динамический IP — это подводный камень: провайдер меняет адрес, клиент не может найти сервер. Если эндпоинт привязан к домену — DDNS-клиент обновляет запись автоматически. Настройка занимает десять минут, а спасает от часов простоя. Или закажите статический IP — если провайдер предоставляет такую опцию. Сравнение с другими решениями. OpenVPN я ставил года три назад. Настройка заняла вечер, конфиги были на десять страниц, скорость упала вдвое. IPSec я даже не пробовал — говорят, там без бубна не разобраться. Tailscale я использую параллельно — он удобен для быстрых подключений, но не даёт контроля над инфраструктурой. WireGuard же — золотая середина. Просто, быстро, под твоим полным контролем. Сравнение говорит само за себя: OpenVPN — вечер настройки и вдвое меньше скорость, IPSec — ад для новичков, Tailscale — удобство без контроля. WireGuard объединяет простоту и скорость: пятнадцать минут, почти нулевые потери, полный контроль. Про аварию. Однажды я обновил ядро на сервере и забыл перезагрузить WireGuard. Модуль ядра обновился, а wg-quick не перезапустился. Я думал, что VPN сломался, час перепроверял конфиги, пока не заметил, что wg0 интерфейса просто нет. Команда wg-quick down wg0 && wg-quick up wg0 решила проблему. Теперь после каждого обновления ядра проверяю. Обновление ядра — классическая причина «сломанного» VPN: модуль обновился, а интерфейс не пересоздался. Симптом — wg show не показывает интерфейс. Лечение — wg-quick down и up. Профилактика — проверка после каждого обновления. Добавьте проверку в свои рутины обслуживания сервера. Что касается нескольких серверов. У меня есть VPS в Европе и домашний сервер. Оба объединены в mesh через WireGuard. Серверы видят друг друга, а я подключаюсь к любому из них и имею доступ ко всей сети. Это удобнее, чем поднимать туннели по отдельности. Mesh из нескольких серверов — это когда каждый узел соединён с каждым через WireGuard. Я могу зайти на VPS и получить доступ к домашней сети и наоборот. Один туннель между серверами — и вся инфраструктура как единая сеть. Это основа для резервирования и распределённых сервисов. Ещё из полезного — PreSharedKey. Если хочешь дополнительную защиту от квантовых компьютеров (ну, мало ли), добавляешь предварительный общий ключ к каждому пиру. WireGuard генерирует его через wg genpsk. На производительность это не влияет, а безопасность повышает. Я добавил PSK всем клиентам — на всякий случай. PreSharedKey — это дополнительный секрет между парой пиров, который усложняет подбор ключей. Одна команда wg genpsk — и ключ готов. Влияния на скорость нет, а безопасность выше. И последнее. WireGuard не умеет сам переподключаться при обрыве, как OpenVPN. Если соединение разорвалось — клиент просто ждёт следующий handshake. PersistentKeepalive решает эту проблему частично, но если сервер перезагрузился, клиент узнает об этом только через 2-3 минуты. Я решил это написанием простого скрипта, который пингует сервер через wg0 и, если пинг не проходит, перезапускает интерфейс. Скрипт висит в cron на клиенте. Автопереподключение — это последний штрих к идеальному VPN. Скрипт на клиенте пингует сервер каждые пару минут и, если ответа нет, перезапускает интерфейс. Двадцать строк bash, одна запись в cron — и вы никогда не останетесь без связи. WireGuard сам по себе ждёт следующий handshake, а скрипт ускоряет восстановление. В итоге — VPN, который работает сам, без вашего участия. Если у вас домашний сервер — поставьте WireGuard сегодня. Пятнадцать минут, и вы навсегда забудете об открытых портах и переборе паролей.

Ваш комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *