WireGuard и Tailscale VPN на Linux VPS
Настройка WireGuard с нуля или развёртывание Tailscale для управляемого VPN-доступа на Ubuntu 24.04 и Debian 12, с защитой от DNS-утечек, усилением PreSharedKey и нейтральным сравнением с Headscale.
Это руководство описывает два подхода к VPN-доступу на Linux VPS: WireGuard (ручная настройка, полный контроль) и Tailscale (управляемый, готовый из коробки). Оба используют протокол WireGuard. Разница в том, кто управляет ключами, маршрутизацией и координацией.
Выбери нужный раздел или прочитай все три части, чтобы принять обоснованное решение.
Требования:
- VPS с Ubuntu 24.04 или Debian 12 (подойдёт VPS Virtua Cloud)
- SSH-доступ с не-root пользователем с sudo
- Настроенный и активный файрвол
- Локальная машина (Linux, macOS или Windows) в качестве VPN-клиента
Зачем VPN к Linux VPS?
Каждый сервис на публичном IP — мишень. Боты для брутфорса SSH находят новые серверы за считанные минуты. Порты баз данных, админки и API-эндпоинты сканируются непрерывно. VPN позволяет полностью убрать интерфейсы управления из публичного интернета.
Принцип простой: привязываешь чувствительные сервисы к адресу VPN-интерфейса вместо 0.0.0.0. Только устройства с валидными VPN-ключами смогут до них достучаться. Публичный интернет вообще не видит, что эти порты существуют.
Типичные сценарии:
- Админский доступ без публичного SSH. Привяжи
sshdк IP WireGuard. Больше никакого порта 22, торчащего наружу. Fail2ban становится необязательным, когда брутфорсить нечего. - Туннель к приватным API инференса ИИ. Крутишь Ollama или приватный LLM-эндпоинт на VPS? Убери его за VPN. Не нужен API-шлюз, не нужна токен-аутентификация для внутреннего доступа.
- Мультиоблачная mesh-сеть. Свяжи VPS-ноды у разных провайдеров (Virtua, Hetzner, OVH) в приватную сеть. Сервисы общаются по зашифрованным туннелям без публичных эндпоинтов.
- Шифрование трафика в ненадёжных сетях. Маршрутизируй весь трафик через VPS, когда работаешь из кофейни или гостиничного WiFi. Твой провайдер и оператор локальной сети видят только зашифрованные WireGuard-пакеты.
Модель угроз имеет значение. Если ты заходишь на VPS только с фиксированного офисного IP, правил файрвола может хватить. Но если работаешь из разных мест, используешь несколько устройств или управляешь командой с разными уровнями доступа, VPN — более чистое решение.
Как установить WireGuard на Ubuntu 24.04 или Debian 12?
WireGuard — VPN-протокол, встроенный в ядро Linux с версии 5.6. Использует Curve25519 для обмена ключами, ChaCha20 для шифрования и содержит около 4 000 строк кода (против 100 000+ у OpenVPN). Ставится через apt, генерируешь ключи, пишешь конфиг, запускаешь туннель. Весь процесс занимает меньше 10 минут.
Установи WireGuard на сервере:
sudo apt update && sudo apt install wireguard wireguard-tools -y
Пакет wireguard предоставляет модуль ядра. Пакет wireguard-tools предоставляет утилиты wg и wg-quick.
Как сгенерировать ключи WireGuard и настроить сервер?
WireGuard использует асимметричные пары ключей (по одной на каждый пир) плюс опциональный предварительно распределённый ключ (PreSharedKey) для постквантовой защиты. Сгенерируй серверную пару ключей, клиентскую пару и общий предварительно распределённый ключ. PreSharedKey добавляет слой симметричного шифрования поверх обмена Curve25519. Если будущий квантовый компьютер сломает асимметричный обмен ключами, симметричный PreSharedKey всё ещё защищает туннель.
На сервере генерируй ключи с ограничительным umask, чтобы файлы создавались с правами 600:
umask 077
wg genkey | sudo tee /etc/wireguard/server_private.key | wg pubkey | sudo tee /etc/wireguard/server_public.key
wg genpsk | sudo tee /etc/wireguard/psk.key
ls -la /etc/wireguard/
-rw------- 1 root root 45 Mar 19 10:01 psk.key
-rw------- 1 root root 45 Mar 19 10:01 server_private.key
-rw------- 1 root root 45 Mar 19 10:01 server_public.key
Все три файла имеют права 600 (чтение/запись только для владельца). Приватный ключ и PreSharedKey никогда не должны покидать сервер.
На локальной машине (клиенте) сгенерируй собственную пару ключей:
umask 077
wg genkey | tee client_private.key | wg pubkey > client_public.key
Тебе нужен публичный ключ клиента на сервере и публичный ключ сервера на клиенте. PreSharedKey идёт на обе стороны. Приватные ключи никогда не передавай.
Включение IP-форвардинга
Сервер должен маршрутизировать трафик для VPN-клиентов. Включи форвардинг IPv4 и IPv6:
echo 'net.ipv4.ip_forward = 1' | sudo tee /etc/sysctl.d/99-wireguard.conf
echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.d/99-wireguard.conf
sudo sysctl -p /etc/sysctl.d/99-wireguard.conf
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1
Файл в /etc/sysctl.d/ предпочтительнее прямого редактирования /etc/sysctl.conf. Он переживает обновления пакетов и явно показывает, какие настройки к какому сервису относятся.
Конфигурационный файл сервера
Определи публичный сетевой интерфейс сервера:
ip route show default
default via 203.0.113.1 dev eth0 proto static metric 100
В этом примере интерфейс — eth0. У тебя может быть ens3, ens18 или что-то другое. Используй то, что стоит после dev.
Создай конфиг сервера:
sudo nano /etc/wireguard/wg0.conf
[Interface]
Address = 10.66.66.1/24, fd42:42:42::1/64
ListenPort = 51820
PrivateKey = <содержимое /etc/wireguard/server_private.key>
PostUp = nft add table ip wireguard; nft add chain ip wireguard forward { type filter hook forward priority 0 \; policy accept \; }; nft add rule ip wireguard forward iifname "wg0" accept; nft add table ip nat; nft add chain ip nat postrouting { type nat hook postrouting priority 100 \; }; nft add rule ip nat postrouting oifname "eth0" masquerade
PostDown = nft delete table ip wireguard; nft delete table ip nat
[Peer]
PublicKey = <содержимое client_public.key>
PresharedKey = <содержимое /etc/wireguard/psk.key>
AllowedIPs = 10.66.66.2/32, fd42:42:42::2/128
Замени eth0 в строках PostUp/PostDown на имя своего реального интерфейса.
Что делает каждая секция:
Address: VPN-IP, назначенный серверу./24и/64определяют размер VPN-подсети.ListenPort: UDP-порт, на котором слушает WireGuard. 51820 — условность.PostUp/PostDown: правила nftables, включающие NAT masquerading. Когда VPN-клиент отправляет трафик в интернет, сервер подменяет исходный IP на свой публичный. Так работает VPN с полным туннелем.AllowedIPsв секции[Peer]: какие VPN-IP может использовать этот клиент./32значит ровно один IP. Это не даёт клиентам подделывать другие VPN-адреса.
Если используешь ufw вместо nftables напрямую, замени PostUp/PostDown на:
PostUp = ufw route allow in on wg0 out on eth0; iptables -t nat -I POSTROUTING -o eth0 -j MASQUERADE
PostDown = ufw route delete allow in on wg0 out on eth0; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
Заблокируй права на конфиг. В нём твой приватный ключ:
sudo chmod 600 /etc/wireguard/wg0.conf
Открытие файрвола и запуск туннеля
Разреши UDP-порт WireGuard в файрволе:
sudo ufw allow 51820/udp
Или напрямую через nftables:
sudo nft add rule inet filter input udp dport 51820 accept
Запусти туннель. Директива enable делает его автозапускаемым. Флаг --now стартует сразу:
sudo systemctl enable --now wg-quick@wg0
sudo systemctl status wg-quick@wg0
● wg-quick@wg0.service - WireGuard via wg-quick(8) for wg0
Loaded: loaded (/usr/lib/systemd/system/wg-quick@.service; enabled; preset: enabled)
Active: active (exited) since ...
Статус показывает active (exited), потому что wg-quick настраивает интерфейс и завершается. Модуль ядра управляет туннелем дальше. Проверь работающий туннель:
sudo wg show
interface: wg0
public key: aB3dEfGhIjKlMnOpQrStUvWxYz1234567890abc=
private key: (hidden)
listening port: 51820
peer: xY9zAbCdEfGhIjKlMnOpQrStUvWxYz1234567890=
preshared key: (hidden)
allowed ips: 10.66.66.2/32, fd42:42:42::2/128
Вывод (hidden) означает, что WireGuard защищает чувствительный ключевой материал. Если видишь latest handshake для пира, значит этот пир успешно подключился.
Конфигурация клиента
На локальной машине создай конфиг WireGuard:
sudo nano /etc/wireguard/wg0.conf
[Interface]
Address = 10.66.66.2/24, fd42:42:42::2/64
PrivateKey = <содержимое client_private.key>
DNS = 10.66.66.1
[Peer]
PublicKey = <содержимое server_public.key>
PresharedKey = <содержимое psk.key>
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = YOUR_SERVER_PUBLIC_IP:51820
PersistentKeepalive = 25
Пояснение ключевых параметров:
AllowedIPs = 0.0.0.0/0, ::/0маршрутизирует весь трафик через VPN (полный туннель). Для split tunneling, когда через туннель идёт только трафик VPN-подсети, используйAllowedIPs = 10.66.66.0/24, fd42:42:42::/64.Endpoint— публичный IP и порт сервера. Клиенту он нужен для инициации соединения. Серверу endpoint клиента не нужен, он узнаёт его из входящих пакетов.PersistentKeepalive = 25отправляет keepalive-пакет каждые 25 секунд. Это поддерживает NAT-маппинги, чтобы сервер мог достучаться до клиента. Без этого соединение рвётся после таймаута NAT (обычно 30-120 секунд бездействия).DNS = 10.66.66.1направляет DNS-запросы на VPN-адрес сервера. Это предотвращает утечки DNS (подробнее в следующем разделе).
На macOS и Windows используй приложение WireGuard. Импортируй конфиг или вставь его.
Подключись с клиента:
sudo wg-quick up wg0
ping 10.66.66.1
PING 10.66.66.1 (10.66.66.1) 56(84) bytes of data.
64 bytes from 10.66.66.1: icmp_seq=1 ttl=64 time=4.23 ms
64 bytes from 10.66.66.1: icmp_seq=2 ttl=64 time=3.98 ms
С локальной машины убедись, что публичный IP изменился (при полном туннеле):
curl -s https://ifconfig.me
Должен вернуться публичный IP VPS, а не домашний.
Добавление новых клиентов
Для каждого дополнительного клиента сгенерируй новую пару ключей и новый PreSharedKey (по одному PSK на пару пиров). Добавь блок [Peer] в wg0.conf сервера:
[Peer]
PublicKey = <новый публичный ключ клиента>
PresharedKey = <новый PreSharedKey>
AllowedIPs = 10.66.66.3/32, fd42:42:42::3/128
Увеличивай IP-адрес для каждого клиента. После редактирования перезагрузи конфиг без разрыва существующих соединений:
sudo wg syncconf wg0 <(sudo wg-quick strip wg0)
Это применяет новую конфигурацию пиров без перезапуска интерфейса. Существующие соединения остаются активными.
Настройка MTU
WireGuard добавляет 60 байт накладных расходов на пакет (28 байт внешние IPv4 и UDP заголовки, 32 байта заголовок WireGuard). Если у VPS стандартный MTU 1500 байт, установи MTU WireGuard в 1420 в секции [Interface]:
MTU = 1420
Устанавливай и на сервере, и на клиенте. Несовпадающие MTU вызывают фрагментацию пакетов и падение пропускной способности, которые сложно диагностировать. Если WireGuard работает поверх линка с уже уменьшенным MTU (PPPoE, VXLAN), вычитай соответственно.
Как предотвратить DNS-утечки с WireGuard?
DNS-утечки происходят, когда система отправляет DNS-запросы мимо VPN-туннеля, раскрывая провайдеру или локальной сети, какие домены ты посещаешь. Это сводит на нет преимущество приватности VPN. Решение: запусти локальный DNS-резолвер на VPN-сервере и направь DNS клиента на него через туннель.
Установи Unbound на сервере:
sudo apt install unbound -y
Создай конфиг, чтобы Unbound слушал на интерфейсе WireGuard:
sudo nano /etc/unbound/unbound.conf.d/wireguard.conf
server:
interface: 10.66.66.1
interface: fd42:42:42::1
interface: 127.0.0.1
access-control: 10.66.66.0/24 allow
access-control: fd42:42:42::/64 allow
access-control: 127.0.0.0/8 allow
do-ip6: yes
hide-identity: yes
hide-version: yes
harden-glue: yes
harden-dnssec-stripped: yes
use-caps-for-id: yes
prefetch: yes
Директивы hide-identity и hide-version не дают Unbound раскрывать версию ПО в DNS-ответах. Раскрытие версии помогает атакующим эксплуатировать известные уязвимости. Опции harden-* обеспечивают валидацию DNSSEC и предотвращают отравление кеша. Опция use-caps-for-id добавляет 0x20-кодировку к DNS-запросам — лёгкая защита от поддельных ответов.
На Ubuntu 24.04 systemd-resolved по умолчанию слушает порт 53 и конфликтует с Unbound. Выключи его:
sudo systemctl disable --now systemd-resolved
sudo rm /etc/resolv.conf
echo "nameserver 127.0.0.1" | sudo tee /etc/resolv.conf
Запусти Unbound:
sudo systemctl enable --now unbound
sudo systemctl status unbound
● unbound.service - Unbound DNS server
Loaded: loaded (/usr/lib/systemd/system/unbound.service; enabled; preset: enabled)
Active: active (running) since ...
Проверь, что Unbound резолвит с интерфейса WireGuard:
dig @10.66.66.1 example.com +short
Должен получить один или несколько IP-адресов. Конкретные IP зависят от текущих DNS-записей домена.
В конфиге клиента уже стоит DNS = 10.66.66.1. Когда туннель WireGuard активен, все DNS-запросы идут через зашифрованный туннель в Unbound. Ни один запрос не утекает к провайдеру.
Для проверки на стороне клиента подключись к VPN и проверь:
resolvectl status wg0
DNS-сервер должен показывать только 10.66.66.1. Можно также использовать dnsleaktest.com.
| Тест | До VPN | После VPN (с Unbound) |
|---|---|---|
| Показанный DNS-сервер | Резолвер провайдера (напр. 192.168.1.1) | 10.66.66.1 (Unbound на VPS) |
| IP, видимый тестовым сайтом | Домашний/офисный IP | Публичный IP VPS |
| DNS-запросы видны провайдеру | Да | Нет |
Подробнее о безопасности DNS, включая DNSSEC и DNS-over-HTTPS, см. .
Kill switch: что происходит, когда туннель падает?
Если туннель WireGuard падает, трафик идёт в открытом виде через маршрут по умолчанию. Твой реальный IP и DNS-запросы оказываются на виду. Kill switch предотвращает это, блокируя весь не-VPN трафик на уровне файрвола.
На клиенте добавь правила nftables, разрешающие трафик только через интерфейс WireGuard и зашифрованное соединение к эндпоинту сервера:
sudo nft add table inet killswitch
sudo nft add chain inet killswitch output { type filter hook output priority 0 \; policy drop \; }
sudo nft add rule inet killswitch output oifname "wg0" accept
sudo nft add rule inet killswitch output ip daddr YOUR_SERVER_PUBLIC_IP udp dport 51820 accept
sudo nft add rule inet killswitch output oifname "lo" accept
С этими правилами, если wg0 упадёт, весь исходящий трафик блокируется. Никаких DNS-утечек, никаких пакетов в открытом виде. Единственный разрешённый трафик — зашифрованный WireGuard-хендшейк к серверу.
Удали kill switch для восстановления обычной маршрутизации:
sudo nft delete table inet killswitch
Для постоянного kill switch, который активируется автоматически, сохрани эти правила в файл и загружай через systemd-сервис, стартующий перед wg-quick@wg0.
Как установить Tailscale на Linux VPS?
Tailscale — mesh-VPN-сервис на базе WireGuard. Он берёт на себя распределение ключей, NAT traversal и обнаружение пиров через координационный сервер. Ставишь клиент, аутентифицируешься через провайдера идентификации, и устройства видят друг друга. Никакого ручного обмена ключами, никакого проброса портов, никаких правил файрвола.
Компромисс: координационный сервер Tailscale — сторонний сервис. Он видит метаданные устройств (IP, имена хостов, какие устройства онлайн), но никогда не видит трафик — тот идёт peer-to-peer через WireGuard.
Как установить Tailscale на Ubuntu 24.04 или Debian 12?
Добавь официальный репозиторий Tailscale и установи пакет. Это лучше, чем curl | sh, и позволяет проверять обновления через apt.
Для Ubuntu 24.04 (Noble):
sudo mkdir -p --mode=0755 /usr/share/keyrings
curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/noble.noarmor.gpg | sudo tee /usr/share/keyrings/tailscale-archive-keyring.gpg >/dev/null
curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/noble.tailscale-keyring.list | sudo tee /etc/apt/sources.list.d/tailscale.list
sudo apt-get update && sudo apt-get install tailscale -y
Для Debian 12 (Bookworm):
sudo mkdir -p --mode=0755 /usr/share/keyrings
curl -fsSL https://pkgs.tailscale.com/stable/debian/bookworm.noarmor.gpg | sudo tee /usr/share/keyrings/tailscale-archive-keyring.gpg >/dev/null
curl -fsSL https://pkgs.tailscale.com/stable/debian/bookworm.tailscale-keyring.list | sudo tee /etc/apt/sources.list.d/tailscale.list
sudo apt-get update && sudo apt-get install tailscale -y
Запусти Tailscale и аутентифицируйся:
sudo tailscale up
Будет выведен URL для аутентификации. Открой его в браузере и войди через провайдера идентификации (Google, Microsoft, GitHub и т.д.). После аутентификации VPS присоединяется к tailnet.
sudo systemctl status tailscaled
● tailscaled.service - Tailscale node agent
Loaded: loaded (/usr/lib/systemd/system/tailscaled.service; enabled; preset: enabled)
Active: active (running) since ...
Проверь назначенный Tailscale IP:
tailscale ip -4
100.64.0.1
Каждое устройство в tailnet получает стабильный адрес 100.x.x.x (CGNAT-диапазон). Этот IP сохраняется через перезагрузки и переподключения. Используй его для доступа к VPS с любого другого устройства в том же tailnet.
Проверь связность с другими устройствами:
tailscale status
100.64.0.1 vps-frankfurt youruser@ linux -
100.64.0.2 laptop youruser@ macOS active; direct 203.0.113.50:41641
Пометка direct означает, что трафик идёт peer-to-peer через WireGuard. Если написано relay, трафик проходит через DERP-релей, что добавляет задержку. DERP-релей используется, когда оба пира за ограничительными NAT, не позволяющими прямые соединения.
Отключение истечения ключей для серверов
Ключи Tailscale по умолчанию истекают через 180 дней. При истечении устройство уходит в оффлайн, пока кто-то не переаутентифицирует его. Для VPS, который должен оставаться подключённым, есть два варианта.
Вариант 1: отключить истечение в админ-консоли. Зайди на страницу Machines, найди свой VPS, нажми на меню и выбери «Disable key expiry».
Вариант 2 (рекомендуемый): использовать тегированный auth-ключ. У тегированных устройств истечение автоматически отключено. Сгенерируй переиспользуемый тегированный auth-ключ в админ-консоли под Settings > Keys, затем подключись:
sudo tailscale up --auth-key=tskey-auth-XXXXX --advertise-tags=tag:server
Теги также работают с ACL (рассмотрены ниже), что делает их лучшим выбором для серверной инфраструктуры.
Как настроить exit node Tailscale на VPS?
Exit node маршрутизирует весь интернет-трафик твоих устройств через VPS. Исходящий трафик выглядит как идущий с IP-адреса VPS. Это работает как традиционный VPN: шифруем всё, выходим с локации VPS.
Включи IP-форвардинг на VPS:
echo 'net.ipv4.ip_forward = 1' | sudo tee /etc/sysctl.d/99-tailscale.conf
echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf
sudo sysctl -p /etc/sysctl.d/99-tailscale.conf
Объяви VPS как exit node:
sudo tailscale set --advertise-exit-node
Одобри exit node в админ-консоли. Найди VPS, нажми на меню, зайди в «Edit route settings» и включи «Use as exit node».
С клиентского устройства начни использовать exit node:
sudo tailscale set --exit-node=<vps-tailscale-ip>
Чтобы сохранить доступ к локальной сети (принтеры, NAS, другие устройства), маршрутизируя интернет через exit node:
sudo tailscale set --exit-node=<vps-tailscale-ip> --exit-node-allow-lan-access=true
Чтобы прекратить маршрутизацию через exit node:
sudo tailscale set --exit-node=
Убедись, что exit node работает, проверив публичный IP с клиента:
curl -s https://ifconfig.me
Должен вернуться публичный IP VPS.
Маршрутизация подсетей
Маршрутизация подсетей (subnet routing) открывает приватную сеть за VPS для tailnet. Полезно, когда VPS может достучаться до приватной подсети базы данных или внутренних сервисов, на которых не стоит Tailscale.
sudo tailscale set --advertise-routes=192.168.1.0/24
Одобри маршрут в админ-консоли так же, как exit node. После одобрения все устройства tailnet могут достучаться до 192.168.1.0/24 через VPS как шлюз, без установки Tailscale на каждый хост в этой подсети.
Можно объявить несколько маршрутов через запятую:
sudo tailscale set --advertise-routes=192.168.1.0/24,10.0.0.0/16
Для нагруженных маршрутизаторов подсетей с большим количеством одновременных потоков Tailscale рекомендует kernel mode (только Linux) вместо userspace mode. На Linux kernel mode используется по умолчанию. Проверь:
tailscale debug prefs | grep RouteAll
Как настроить ACL Tailscale для доступа к VPS?
По умолчанию все устройства в tailnet могут обращаться друг к другу на всех портах. В продакшене ограничь это через ACL в файле политики tailnet.
Минимальная политика, ограничивающая доступ к VPS группой админов:
{
"groups": {
"group:admins": ["alice@example.com", "bob@example.com"]
},
"tagOwners": {
"tag:server": ["group:admins"]
},
"acls": [
{
"action": "accept",
"src": ["group:admins"],
"dst": ["tag:server:*"]
}
]
}
Это значит: только члены group:admins могут обращаться к устройствам с тегом tag:server. Все остальные соединения запрещены по умолчанию. Редактируй в админ-консоли под Access Controls.
Пометь VPS тегом при подключении к tailnet:
sudo tailscale up --advertise-tags=tag:server
Более гранулярная политика может ограничивать по портам:
{
"groups": {
"group:admins": ["alice@example.com"],
"group:developers": ["bob@example.com", "charlie@example.com"]
},
"tagOwners": {
"tag:server": ["group:admins"]
},
"acls": [
{
"action": "accept",
"src": ["group:admins"],
"dst": ["tag:server:*"]
},
{
"action": "accept",
"src": ["group:developers"],
"dst": ["tag:server:22,80,443"]
}
]
}
Разработчики получают доступ к SSH (22) и вебу (80, 443). Админы — полный доступ. Остальные не могут достучаться до сервера. Tailscale применяет эти правила на стороне клиента, так что трафик блокируется до того, как доберётся до сервера.
MagicDNS
Tailscale включает MagicDNS, который даёт каждому устройству имя хоста, резолвимое внутри tailnet. Вместо запоминания 100.64.0.1 делаешь SSH на vps-frankfurt. Включи в админ-консоли в настройках DNS. Никакого Unbound или ручной настройки DNS не нужно.
Что такое Headscale и когда его использовать?
Headscale — open-source реализация координационного сервера Tailscale с возможностью самостоятельного хостинга. Использует стандартные клиенты Tailscale, но запускает control plane на твоей инфраструктуре. Без лимитов на устройства, без телеметрии, без зависимости от SaaS Tailscale. Совместим со всеми официальными клиентами Tailscale (Linux, macOS, Windows, iOS, Android).
Архитектура:
┌─────────────┐ ┌──────────────────┐ ┌─────────────┐
│ Клиент A │──────▶│ Headscale │◀──────│ Клиент B │
│ (tailscale) │ │ (твой сервер) │ │ (tailscale) │
└──────┬───────┘ └──────────────────┘ └──────┬───────┘
│ │
└────────────── WireGuard-туннель ─────────────────┘
(прямой, peer-to-peer)
Headscale управляет обменом ключами, регистрацией устройств и применением ACL. Фактический VPN-трафик идёт напрямую между пирами через WireGuard. Headscale никогда не видит твой трафик данных, только координационные метаданные.
Что Headscale поддерживает сейчас: регистрацию устройств (CLI и OIDC), ACL, маршрутизаторы подсетей, exit node, MagicDNS, pre-auth ключи и теги. Покрывает основной набор функций Tailscale.
Чего не поддерживает: Tailscale Funnel, Serve, логи сетевых потоков и некоторые бета-функции. Интерфейс администрирования — только CLI. Существуют веб-интерфейсы от сообщества (headscale-ui), но они покрывают не все функции.
Когда Headscale имеет смысл:
- Регуляторные требования запрещают сторонние координационные серверы. Для SaaS Tailscale могут потребоваться соглашения об обработке данных GDPR. Headscale устраняет эту зависимость.
- Тебе нужно больше устройств, чем позволяет бесплатный тариф Tailscale.
- Нужен полный контроль аудита над регистрацией устройств и управлением ключами.
- Строишь инфраструктуру, где зависимость от внешнего SaaS — единая точка отказа.
Когда не подходит:
- Нужна глобальная сеть DERP-релеев Tailscale для надёжного NAT traversal. Headscale может использовать DERP, но придётся поднимать свои релеи или принять использование публичных от Tailscale.
- Хочешь красивый веб-интерфейс администрирования. Headscale ориентирован на CLI.
- Маленькая команда и нулевое желание поддерживать ещё один сервис.
Полный туториал по настройке Headscale запланирован на будущую статью. Пока что смотри документацию Headscale.
WireGuard vs Tailscale vs Headscale: что подходит именно тебе?
Используй WireGuard, если нужен полный контроль, минимальная задержка, изолированные (air-gapped) сети или регуляторные требования, запрещающие сторонние координационные серверы. Используй Tailscale, если управляешь несколькими устройствами, нужен NAT traversal без проброса портов или ACL без ручной настройки. Для команд, которым нужны функции Tailscale с самостоятельным хостингом, рассмотри Headscale.
| Параметр | WireGuard | Tailscale | Headscale |
|---|---|---|---|
| Время настройки | 10-15 мин на пир | 2 мин на устройство | 30-60 мин (сервер + клиенты) |
| Управление ключами | Ручное (генерация, распределение, ротация) | Автоматическое (координационный сервер) | Автоматическое (твой координационный сервер) |
| NAT traversal | Нет. Нужен проброс портов или публичный IP хотя бы с одной стороны | Встроенный (DERP-релеи + STUN) | Частичный (свой DERP или публичные релеи) |
| Обнаружение пиров | Ручная настройка для каждого пира | Автоматический mesh | Автоматический mesh |
| ACL | Правила файрвола (nftables/iptables) | Файл политики в админ-консоли | Файл политики на твоём сервере |
| Макс. устройств | Без ограничений | Бесплатный тариф ограничен (см. страницу тарифов) | Без ограничений |
| Мультиоблачный mesh | Конфиг на каждой ноде, N*(N-1)/2 записей пиров | Присоединение к tailnet, mesh формируется сам | Как Tailscale, самостоятельный хостинг |
| Зависимость от третьих лиц | Нет | Tailscale Inc. (только координация) | Нет |
| GDPR / compliance | Полный контроль, нет стороннего обработчика данных | Tailscale обрабатывает метаданные устройств | Полный контроль |
| DNS | Ручной (Unbound и т.д.) | MagicDNS (автоматический, имена хостов) | MagicDNS (с настройкой) |
| Задержка | Минимальная (WireGuard на уровне ядра) | Минимальная при прямом; +20-50 мс через DERP | Как Tailscale |
| Онбординг команды | Ручная раздача конфигов и ключей | Ссылка-приглашение, SSO-логин | Регистрация через CLI или OIDC |
| Постквантовая защита | PreSharedKey (ручная настройка) | Не настраивается пользователем | Не настраивается пользователем |
Быстрый выбор
Одиночный разработчик, один VPS: WireGuard. Самый простой путь. Ноль зависимостей. Минимально возможная задержка. Генерируешь два ключа и пишешь два конфига.
Команда 3-15 человек, несколько устройств: Tailscale. Координационный сервер экономит часы управления ключами. ACL чище, чем поддержка правил nftables для каждого пира. NAT traversal работает без изменений сети.
Регулируемая среда или обязанность self-hosting: Headscale, если хочешь UX Tailscale без зависимости от третьих лиц. Голый WireGuard, если хочешь ноль движущихся частей и команда справится с конфигами.
Мультиоблачный mesh (5+ нод у разных провайдеров): Tailscale или Headscale. С WireGuard 10 нод требуют 45 записей пиров. При 20 нодах — уже 190. Нагрузка на управление конфигами растёт квадратично.
Доступ к эндпоинту ИИ-инференса: Если делаешь туннель к GPU VPS с ноутбука, оба варианта подходят. Tailscale быстрее настроить. WireGuard не добавляет измеримых накладных расходов для чувствительных к задержке вызовов инференса. Для мульти-GPU конфигураций у разных провайдеров mesh Tailscale оправдывает себя.
Устранение неполадок
Туннель WireGuard поднят, но трафик не идёт:
Проверь IP-форвардинг:
sysctl net.ipv4.ip_forward
Должен вернуть net.ipv4.ip_forward = 1. Проверь, загружены ли правила masquerade:
sudo nft list ruleset | grep masquerade
Если пусто, правила PostUp не выполнились. Перезапусти через sudo systemctl restart wg-quick@wg0 и смотри journalctl -u wg-quick@wg0 на предмет ошибок.
Хендшейк WireGuard никогда не завершается:
sudo wg show
Если latest handshake никогда не появляется для пира, UDP-порт 51820 заблокирован где-то. Убедись, что сервер слушает:
sudo ss -ulnp | grep 51820
UNCONN 0 0 0.0.0.0:51820 0.0.0.0:*
WireGuard использует модуль ядра напрямую, поэтому ss может не показывать имя процесса для сокета.
Затем проверь со стороны клиента. Если клиент за корпоративным файрволом, UDP 51820 может быть заблокирован. Некоторые сети разрешают только TCP 443.
Tailscale показывает «offline» в админ-консоли:
sudo systemctl status tailscaled
Если работает, но показывает offline, переаутентифицируйся:
sudo tailscale up --force-reauth
Если tailscaled не запущен, проверь конфликты портов с другим VPN-софтом.
DNS всё ещё утекает после настройки Unbound:
Проверь, слушает ли Unbound на IP WireGuard:
ss -ulnp | grep :53
Ищи 10.66.66.1:53 в выводе. Если Unbound привязан только к 127.0.0.1, перепроверь строки interface: в /etc/unbound/unbound.conf.d/wireguard.conf.
На Ubuntu также проверь, что systemd-resolved действительно остановлен:
sudo systemctl is-active systemd-resolved
Если возвращает active, он конкурирует с Unbound за порт 53.
Логи сервисов:
journalctl -u wg-quick@wg0 -f
journalctl -u tailscaled -f
journalctl -u unbound -f
Авторское право 2026 Virtua.Cloud. Все права защищены. Данный контент является оригинальным произведением команды Virtua.Cloud. Воспроизведение, повторная публикация или распространение без письменного разрешения запрещены.
Готовы попробовать?
Разверните свой сервер за секунды. Linux, Windows или FreeBSD.
Смотреть тарифы VPS