Что вы изучите
- Как собрать WireGuard mesh для безопасной сетевой зоны (WireGuard 1.1, релиз 2025).
- Как настроить mTLS для сервисов на стороне сервера и клиента (Envoy 1.30, релиз 2026 или Nginx 1.26, релиз 2024).
- Как привязать сертификаты и полномочия к идентичности через SPIRE 1.2 (релиз 2026) или HashiCorp Vault 1.15 (релиз 2025).
- Как автоматизировать выдачу и ротацию сертификатов, контроль доступа и аудит.
- Практические команды, ожидаемый вывод, типичные ошибки и способы их исправления.
Требования
- Операционная система: Ubuntu 22.04 LTS или 24.04 LTS / Debian 12 (x86_64). Поддержка systemd обязательна.
- Минимальные ресурсы: 2 vCPU, 4 ГБ RAM для базовой связки (headscale + 2 агента + Envoy). Рекомендуется 4 vCPU, 8 ГБ RAM для прод окружения.
- Базовые версии инструментов: WireGuard 1.1 (2025), headscale 1.4 (2025), Envoy 1.30 (2026), Nginx 1.26 (2024), SPIRE 1.2 (2026), HashiCorp Vault 1.15 (2025), OpenSSL 3.1 (2025).
- Порты: WireGuard UDP 51820 по умолчанию (можно менять), headscale API 8080, Envoy управляющий порт 9901, mTLS сервера 443/8443.
Что такое zero-trust?
Zero-trust — модель безопасности, где ничему и никому не доверяют по умолчанию: каждая сессия, соединение и запрос проверяются на основе контекста, идентичности и минимально необходимого уровня доступа. Для self-hosted это значит: изолированная сетка, взаимная аутентификация сервисов (mTLS), и централизованная система выдачи идентичностей и политик.
Практическая цель — обеспечить, чтобы любой запрос к сервису подтверждался не только сетевым маршрутом, но и цифровой идентичностью клиента и политикой доступа. Это уменьшает риск боковых перемещений при компрометации одного узла и позволяет аудировать все запросы.
Шаг 1: WireGuard mesh
Задача: создать приватную сетку между вашими хостами с использованием WireGuard 1.1 (релиз 2025) и headscale 1.4 (релиз 2025) как self-hosted контроллера вместо коммерческого сервиса. В результате у вас будет L3-сеть с прямыми маршрутами между инстансами и минимальным количеством пробросов портов.
Команда: развернуть headscale в Docker Compose
version: '3.7'
services:
headscale:
image: headscale/headscale:1.4.0
container_name: headscale
restart: always
ports:
- "8080:8080" # headscale API
volumes:
- ./headscale.yaml:/etc/headscale/configuration.yaml
- ./data:/var/lib/headscale
environment:
- HEADSCALE_LOG_LEVEL=info
Пояснение: headscale управляет регистрацией клиентов WireGuard, генерирует ключи и выдаёт конфигурации. Образ headscale 1.4 примерно 20–30 МБ.
Ожидаемый вывод
$ docker compose up -d
Creating network "default" with the default driver
Creating headscale ... done
$ docker logs headscale
INFO 2026-02-10T10:12:01Z headscale: starting headscale server on :8080
Типичная ошибка и её фикс
Error: failed to create TUN device: permission denied
Fix: модуль TUN не доступен в контейнере. Запустите контейнер с опцией --cap-add=NET_ADMIN и --device /dev/net/tun, или установите headscale напрямую на хост.
Пример: docker run --cap-add=NET_ADMIN --device /dev/net/tun headscale/headscale:1.4.0
Дальше создайте пару клиентских нод и подключите их к mesh. На клиенте используйте wireguard-tools (wg-quick). Пример генерации ключа:
$ wg genkey | tee privatekey | wg pubkey > publickey
$ cat privatekey
# приватный ключ (32 байта base64)
Ожидаемый вывод (проверка интерфейса):
$ sudo wg show
interface: wg0
public key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXX
private key: (hidden)
listening port: 51820
peer: YYYYYYYYYYYYYYYYYYYYYYYYYYYYY
endpoint: 203.0.113.5:51820
allowed ips: 10.10.0.0/24
Типичная ошибка и её фикс:
Ошибка: RTNETLINK answers: File exists
Fix: конфликт интерфейсов — удалите старую запись: sudo ip link delete wg0 или остановите wg-quick@wg0.service и повторите создание.
Подсказка по производительности: WireGuard сам по себе лёгок: сетевой оверхед ~6–12% при шифровании AES-256, на CPU 2 vCPU при 1 Gbps шифрование может быть узким местом. Для крупных сетей используйте выделенные CPU и проверяйте MTU (рекомендуемый MTU 1420 для туннелирования).

Скриншот конфигурации WireGuard mesh и headscale UI
Шаг 2: mTLS
Задача: обеспечить взаимную TLS-аутентификацию между сервисами внутри mesh. Для примера используем Envoy 1.30 (релиз 2026) как обратный прокси, который требует сертификаты от клиентов и предъявляет сертификат сервера.
Команда: сгенерировать CA и server/client сертификаты с OpenSSL 3.1 (2025)
# создать CA
$ openssl genpkey -algorithm RSA -out ca.key -pkeyopt rsa_keygen_bits:4096
$ openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 -subj "/CN=ZeroTrust-CA" -out ca.crt
# серверный ключ и CSR
$ openssl genpkey -algorithm RSA -out server.key -pkeyopt rsa_keygen_bits:2048
$ openssl req -new -key server.key -subj "/CN=svc.example.local" -out server.csr
$ openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 825 -sha256
# клиентский сертификат
$ openssl genpkey -algorithm RSA -out client.key -pkeyopt rsa_keygen_bits:2048
$ openssl req -new -key client.key -subj "/CN=client-01" -out client.csr
$ openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days 365 -sha256
Пояснение: CA подписывает серверные и клиентские сертификаты. Для production используйте автоматическую выдачу (см. Шаг 3) и короткий срок жизни сертификатов (например, 90–365 дней).
Пример конфигурации Envoy (фрагмент) — требовать client certificate
transport_socket:
name: envoy.transport_sockets.tls
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
common_tls_context:
tls_certificates:
- certificate_chain: { filename: "/etc/envoy/server.crt" }
private_key: { filename: "/etc/envoy/server.key" }
validation_context:
trusted_ca:
filename: "/etc/envoy/ca.crt"
require_tls: true
Тест подключения с curl (mTLS)
$ curl --cacert ca.crt --cert client.crt --key client.key https://svc.example.local:8443/health
{"status":"ok\
Комментарии (0)
Войдите или зарегистрируйтесь, чтобы оставить комментарий
Загрузка комментариев…