Актуальный Docker контейнер AmneziaWG.
- Multi-arch:
amd64иarm64 - Один и тот же контейнер работает как клиент, так и сервер: роль определяется содержимым конфига
Как это работает
При старте контейнер поднимает интерфейсы для всех .conf файлов из директории configs (внутри контейнера /etc/amnezia/amneziawg) через awg-quick.
Готовые шаблоны конфигов с плейсхолдерами: examples/client.conf и examples/server.conf. Скопируйте нужный в configs/ под именем интерфейса (например wg0.conf) и подставьте свои ключи.
Возможны два режима работы:
Userspace(по умолчанию): модуль ядра на хосте не нужен, используется реализацияamneziawg-goи требуется проброс устройства/dev/net/tun.Kernel: если на хосте установлен модуль ядраamneziawg, используется он. Проброс/dev/net/tunв этом случае не обязателен, но не будет мешать работе контейнера.
Генерация ключей и пиры
У каждой стороны (сервер и каждый клиент) своя пара ключей. Команда генерирует одну пару - запускайте её по разу на каждую сторону:
docker run --rm --entrypoint sh vernette/amneziawg:v1.0.20260223 -c \
'priv=$(awg genkey); printf "PrivateKey = %s\nPublicKey = %s\n" "$priv" "$(echo "$priv" | awg pubkey)"'
Правило раскладки: свой приватный ключ - в [Interface], публичный ключ пира - в [Peer].
Сервер
Сгенерируйте пару сервера и заполните examples/server.conf:
[Interface]
PrivateKey = <SERVER_PRIVATE_KEY> # приватный ключ сервера
# ...
[Peer]
PublicKey = <CLIENT_PUBLIC_KEY> # публичный ключ клиента (из шага 2)
Клиент
Сгенерируйте пару клиента и заполните examples/client.conf:
[Interface]
PrivateKey = <CLIENT_PRIVATE_KEY> # приватный ключ клиента
# ...
[Peer]
PublicKey = <SERVER_PUBLIC_KEY> # публичный ключ сервера (из шага 1)
Endpoint = your.server.example:51820
Итог:
| Конфиг | [Interface] PrivateKey |
[Peer] PublicKey |
|---|---|---|
server.conf |
приватный сервера | публичный клиента |
client.conf |
приватный клиента | публичный сервера |
Добавление новых клиентов
Для каждого нового клиента:
-
Сгенерируйте отдельную пару ключей.
-
В серверный конфиг добавьте новый блок
[Peer]с публичным ключом клиента и уникальным адресом вAllowedIPs:[Peer] PublicKey = <CLIENT2_PUBLIC_KEY> AllowedIPs = 10.10.0.3/32 -
В конфиг нового клиента впишите его приватный ключ и публичный ключ сервера (как в шаге 2), задав свой
Address(10.10.0.3/24).
Отдельные команды
# приватный ключ
docker run --rm --entrypoint awg vernette/amneziawg:v1.0.20260223 genkey
# публичный ключ из приватного
echo <PRIVATE_KEY> | docker run --rm -i --entrypoint awg vernette/amneziawg:v1.0.20260223 pubkey
# предварительный общий ключ (PSK, опционально)
docker run --rm --entrypoint awg vernette/amneziawg:v1.0.20260223 genpsk
Параметры AmneziaWG
В конфиге клиента можно использовать Jc, Jmin, Jmax и, например, I1 - junk-настройки клиента: добавляют мусор в handshake и нужны только на стороне клиента. Совпадение с сервером не требуется, их можно применять даже к обычному WireGuard серверу. Остальные параметры обязаны совпадать с параметрами сервера.
Более подробно про параметры AmneziaWG в документации и статье.
Генерация параметров обфускации
Параметры обфускации (Jc, Jmin, Jmax, S1-S4, H1-H4, I1) можно сгенерировать командой awg-genparams - тем же алгоритмом, что и в официальном клиенте Amnezia. Один запуск печатает два блока с идентичными S/H: серверный и клиентский.
docker run --rm --entrypoint awg-genparams vernette/amneziawg:v1.0.20260223
Скопируйте серверный блок в [Interface] серверного конфига, клиентский - в [Interface] клиентского. Совпадать на обеих сторонах обязаны только S/H. Jc/Jmin/Jmax (junk-пакеты хэндшейка) и I1 (special junk) - только клиентские параметры, поэтому есть только в клиентском блоке; I1 рекомендуется заменить на своё уникальное значение.
Работа в режиме клиента
-
Создайте директорию
configs:mkdir configs -
Поместите конфиг в
./configs/wg0.conf(имя файла = имя интерфейса), указав необходимые параметры AmneziaWG (Jc,Jmin,Jmax,I1, etc). -
Запустите контейнер:
docker compose up -d
Базовый compose.yaml для клиента в userspace-режиме:
services:
amneziawg:
image: vernette/amneziawg:v1.0.20260223
container_name: amneziawg-client
restart: always
volumes:
- ./configs:/etc/amnezia/amneziawg:ro
devices:
- /dev/net/tun:/dev/net/tun # только userspace-режим
cap_add:
- NET_ADMIN
volumes: каталог с конфигами (монтируется только для чтения)devices: проброс/dev/net/tun, нужен только в userspace-режиме- По умолчанию интерфейс доступен только внутри контейнера. При необходимости раскомментируйте одну из опций
network_modeвcompose.yaml:network_mode: "host": контейнер будет использовать сетевой стек хоста и интерфейс будет доступен в системе хостаnetwork_mode: "service:some_service": контейнер будет использовать namespace указанного контейнера и второй сможет использовать интерфейс первого будто это его собственный интерфейс
Split-tunnel vs full-tunnel
Поведение зависит от AllowedIPs в [Peer] клиентского конфига.
-
Split-tunnel:
AllowedIPsперечисляет только нужные сети (например10.10.0.0/24). В туннель идёт лишь трафик к этим адресам, остальное - напрямую. Базовыйcompose.yamlвыше работает как есть. -
Full-tunnel:
AllowedIPs = 0.0.0.0/0, ::/0, весь трафик в туннель.awg-quickдобавляет policy-routing (fwmark, отдельная таблица маршрутизации) и пишетnet.ipv4.conf.all.src_valid_mark=1. Этот sysctl нужно предзадать на уровне Docker:services: amneziawg: image: vernette/amneziawg:v1.0.20260223 container_name: amneziawg-client restart: always volumes: - ./configs:/etc/amnezia/amneziawg:ro devices: - /dev/net/tun:/dev/net/tun # только userspace-режим cap_add: - NET_ADMIN sysctls: - net.ipv4.conf.all.src_valid_mark=1 # нужно для full-tunnel
Note
Альтернатива -
Table = offв[Interface]клиентского конфига. Полностью отключает авто-маршрутизациюawg-quick. Подходит, когда маршрутизацией управляете сами или делите интерфейс черезnetwork_mode: "service:..."для одного приложения. При этом full-tunnel сам не заработает - маршруты добавляете вручную (PostUp/ip route).
Warning
Режим
network_mode: host. БлокsysctlsDocker отклонит - namespacednet.*sysctls при host-сети задавать нельзя (src_valid_markберётся с хоста). Дополнительно: host + full-tunnel (0.0.0.0/0) безTable = offставит policy-routing на самом хосте и захватывает его дефолтный маршрут - весь egress хоста уйдёт в VPN, а удалённая SSH-сессия (не из LAN) оборвётся. В bridge-режиме всё это изолировано в namespace контейнера и хосту не вредит.
Работа в режиме сервера
Для сервера нужно пробросить UDP-порт из ListenPort и включить форвардинг. NAT и маршрутизация задаются через PostUp/PostDown в .conf - точно так же, как в обычном WireGuard-сервере (awg-quick - форк wg-quick). Образ уже содержит iptables и ip6tables.
services:
amneziawg:
image: vernette/amneziawg:v1.0.20260223
container_name: amneziawg-server
restart: always
volumes:
- ./configs:/etc/amnezia/amneziawg:ro
ports:
- "51820:51820/udp" # должен совпадать с ListenPort в .conf
devices:
- /dev/net/tun:/dev/net/tun # только userspace-режим
cap_add:
- NET_ADMIN
sysctls:
- net.ipv4.ip_forward=1
- net.ipv6.conf.all.forwarding=1 # только если нужен IPv6
Пример NAT в серверном .conf:
PostUp = iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
eth0 - исходящий интерфейс внутри контейнера (в дефолтной bridge-сети чаще всего именно он). Отдельные правила FORWARD не нужны: в собственном сетевом namespace контейнера политика FORWARD по умолчанию ACCEPT, достаточно MASQUERADE.
Для IPv6 NAT по аналогии (если нужен):
PostUp = ip6tables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = ip6tables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
Note
Режим
network_mode: host. Конфигурация выше рассчитана на bridge-сеть. Если запускать контейнер сnetwork_mode: host, есть отличия:
- Блок
sysctlsDocker отклонит - задавать namespacednet.*sysctls при host-сети нельзя. Форвардинг нужно включать на самом хосте (например, в/etc/sysctl.d/); на хосте с Dockernet.ipv4.ip_forwardобычно уже= 1.- Проброс
portsне нужен - контейнер слушаетListenPortпрямо на хосте.- Правила из
PostUp/PostDownпишутся в firewall хоста, а не в изолированный namespace, и смешиваются с правилами хоста (включая цепочки Docker). Имя egress-интерфейса вMASQUERADEтоже будет хостовым (часто неeth0)./dev/net/tunиNET_ADMINпо-прежнему нужны для userspace-режима.
Модуль ядра (kernel-режим)
Userspace-режим работает из коробки, но модуль ядра даёт более высокую производительность и меньшую нагрузку.
Установить его можно из официального репозитория amneziawg-linux-kernel-module для своего дистрибутива:
-
Установите модуль на хост - через DKMS из готовых пакетов для вашего дистрибутива или сборкой из исходников (инструкции в README репозитория модуля). Пример для Debian:
sudo apt install -y software-properties-common python3-launchpadlib gnupg2 linux-headers-$(uname -r) sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 57290828 echo "deb https://ppa.launchpadcontent.net/amnezia/ppa/ubuntu focal main" | sudo tee -a /etc/apt/sources.list echo "deb-src https://ppa.launchpadcontent.net/amnezia/ppa/ubuntu focal main" | sudo tee -a /etc/apt/sources.list sudo apt update sudo apt install -y amneziawg -
Загрузите модуль:
sudo modprobe amneziawg -
После этого из
compose.yamlможно убрать блокdevices: /dev/net/tun- в kernel-режиме он не требуется. Если контейнер уже работал в userspace-режиме, необходимо перезапустить его:docker compose down docker compose up -d
Теги образа
vernette/amneziawg:latest: последний собранный образvernette/amneziawg:<версия>: привязка к тегу amneziawg-tools
Ссылки
- Документация AmneziaWG
- amneziawg-go - userspace-реализация
- amneziawg-tools -
awg/awg-quick - amneziawg-linux-kernel-module - модуль ядра
