Files
wikipedia/VPN/amneziavpn-docker-guide.md
T

406 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# AmneziaVPN в Docker: полный гайд
**Цель:** поднять в Docker контейнере клиент AmneziaVPN (AmneziaWG 3.1), подключить его по пользовательскому `.conf` от Amnezia Premium и сделать его VPN-шлюзом для домашней сети.
**Автор:** Hermes Agent • Среда: LXC-контейнер (Docker 29.4.1, ядро Proxmox 6.17.13-2-pve)
---
## 1. Что потребуется
| Компонент | Значение |
|-----------|----------|
| Хост | Linux с Docker 20.10+ (тестировалось: LXC 29.4.1) |
| `/dev/net/tun` | Должен существовать и быть открыт |
| `ip_forward` | `1` |
| `.conf` файл | Amnezia Premium / AmneziaWG 3.1 конфиг |
| Версии | `amneziawg-go` v3.1.20260828, `amneziawg-tools` v3.1.20260812 |
Пример `.conf` (Amnezia Premium, конфиг 3.1):
```ini
[Interface]
Address = 100.85.175.118/32
DNS = 100.64.0.1, 8.8.4.4
PrivateKey = fSdjHMi8tAzL2wbNxsylQW1FAIXdn2/ODPGWr569J/w=
Jc = 5
Jmin = 10
Jmax = 80
H1 = 1
H2 = 2
H3 = 3
H4 = 4
HeaderProtectionKey = 8H1SggRhZ8iT8ZYZlS/RPf6SItoxb8OeXX2rNwMgc3M=
RekeyAfterTime = 100-120
RekeyTimeout = 3-8
RejectAfterTime = 150-180
KeepaliveTimeout = 7-13
MaxHandshakeAttempts = 15-20
ContentPaddingAddition = 10-100
[Peer]
PublicKey = FfgUO6z0plGUntTW3T8fsFsZ250GcQZEKlCgj1fkRFc=
PresharedKey = +Is1eWUUQ5UXYD8E7zigG32KaThcGC/YolOVS7LeDGU=
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = 78.17.149.78:8344
PersistentKeepalive = 25-35
```
> ⚠️ **НЕ** выкладывай `.conf` ни в чат, ни на сторонние сайты. Его приватный ключ — твой доступ. Файл копируется только на сервер.
---
## 2. Подготовка хоста
```bash
# Проверить Tun-устройство и форвардинг
ls -la /dev/net/tun
cat /proc/sys/net/ipv4/ip_forward # должно быть 1
# Включить форвардинг (если 0)
echo 1 > /proc/sys/net/ipv4/ip_forward
# Проверить Docker
docker --version
```
**На LXC (виртуальном контейнере Proxmox)** убедись, что:
- `/dev/net/tun` существует (создаётся через настройки LXC)
- `net.ipv4.ip_forward=1` установлен (в Proxmox: LXC → Options → Features)
---
## 3. Скачивание репозиториев
> ⚠️ Сборку ведём из **локальных** копий репозиториев (COPY в Dockerfile), так как DNS внутри build-контейнера нестабилен.
```bash
mkdir -p /root/awg-src
cd /root/awg-src
# Правильный DNS на хосте LXC
echo "nameserver 8.8.8.8" > /etc/resolv.conf
git clone --depth 1 --branch v3.1.20260828 https://github.com/amnezia-vpn/amneziawg-go.git
git clone --depth 1 --branch v3.1.20260812 https://github.com/amnezia-vpn/amneziawg-tools.git
```
**Проверка тегов** (актуальные на момент сборки):
```bash
git ls-remote --tags https://github.com/amnezia-vpn/amneziawg-go.git | tail
# v3.1.20260813, v3.1.20260814, v3.1.20260828
git ls-remote --tags https://github.com/amnezia-vpn/amneziawg-tools.git | tail
# v3.0.20260805, v3.1.20260812
```
> Найдите **последний** тег v3.1.* — они выходят часто и содержат исправления DPI-обхода.
---
## 4. Директория сборки
```bash
mkdir -p /root/awg-builder
cp -r /root/awg-src/amneziawg-go /root/awg-builder/
cp -r /root/awg-src/amneziawg-tools /root/awg-builder/
```
---
## 5. Dockerfile
**`/root/awg-builder/Dockerfile`**
```dockerfile
# syntax=docker/dockerfile:1
FROM golang:alpine AS go-build
RUN apk add --no-cache make gcc musl-dev linux-headers
COPY amneziawg-go /src/amneziawg-go
RUN cd /src/amneziawg-go && make && cp amneziawg-go /go/bin/
COPY amneziawg-tools /src/amneziawg-tools
RUN cd /src/amneziawg-tools/src && make && cp wg /go/bin/awg
FROM alpine:3.21
RUN apk add --no-cache iptables ip6tables iproute2 bash openresolv
COPY --from=go-build /go/bin/amneziawg-go /usr/bin/
COPY --from=go-build /go/bin/awg /usr/bin/
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
```
> **Почему `cp wg /go/bin/awg`**: в `amneziawg-tools` бинарь надёжнее назвать `awg`. Это клиентская утилита управления интерфейсом.
**Healthcheck** (необязателен): добавить в Dockerfile ```HEALTHCHECK``` — можно пропустить, статус смотрим через `awg show`.
---
## 6. entrypoint.sh
Скрипт: поднимает интерфейс, загружает конфиг (с фолбэком на минимальный), настраивает policy routing и NAT.
**`/root/awg-builder/entrypoint.sh`**
```bash
#!/bin/bash
CONFIG_DIR=/config
for f in "${CONFIG_DIR}"/*.conf; do
[ -f "$f" ] || continue
IFACE=$(basename "$f" .conf)
echo "Starting AmneziaWG interface: ${IFACE}"
modprobe amneziawg 2>/dev/null || true
if ! ip link show "${IFACE}" 2>/dev/null | grep -q UP; then
ip link add "${IFACE}" type amneziawg 2>/dev/null || {
echo "[*] Using userspace amneziawg-go"
amneziawg-go "${IFACE}" 2>/dev/null || true
sleep 1
}
fi
TMPF=$(mktemp)
grep -v -E '^(Address|DNS)' "$f" > "$TMPF"
if ! awg setconf "${IFACE}" "$TMPF" 2>/dev/null; then
echo "[!] Trying minimal config"
{
echo "[Interface]"
grep -E '^PrivateKey' "$f"
echo "ListenPort = 51820"
echo ""
echo "[Peer]"
grep -E '^(PublicKey|PresharedKey|AllowedIPs|Endpoint|PersistentKeepalive)' "$f"
} | awg setconf "${IFACE}" /dev/stdin 2>/dev/null || {
echo "[!] FATAL: cannot parse config"
rm -f "$TMPF"
continue
}
fi
rm -f "$TMPF"
IP=$(grep ^Address "$f" | head -1 | cut -d= -f2 | tr -d ' ' | cut -d, -f1)
[ -n "$IP" ] && ip addr add "$IP" dev "${IFACE}" 2>/dev/null || true
ip link set "${IFACE}" up
echo "[*] ${IFACE} UP: ${IP}"
done
# --- Policy routing: только forwarded LAN-трафик через VPN ---
mkdir -p /etc/iproute2
if ! grep -q "awg-vpn" /etc/iproute2/rt_tables 2>/dev/null; then
echo "100 awg-vpn" >> /etc/iproute2/rt_tables 2>/dev/null || true
fi
ip route add 0.0.0.0/0 dev awg0 table 100 2>/dev/null || true
# Пометить forwarded LAN-трафик (не на LAN) меткой 100
iptables -t mangle -C PREROUTING -s 192.168.1.0/24 ! -d 192.168.1.0/24 -j MARK --set-mark 100 2>/dev/null || \
iptables -t mangle -A PREROUTING -s 192.168.1.0/24 ! -d 192.168.1.0/24 -j MARK --set-mark 100 2>/dev/null || true
# Пакеты с меткой 100 → таблица awg-vpn (через awg0)
ip rule add fwmark 100 lookup 100 priority 5000 2>/dev/null || true
# NAT для LAN через туннель
iptables -t nat -C POSTROUTING -s 192.168.1.0/24 -o awg0 -j MASQUERADE 2>/dev/null || \
iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o awg0 -j MASQUERADE 2>/dev/null || true
echo 1 > /proc/sys/net/ipv4/ip_forward 2>/dev/null || true
echo "[*] AmneziaWG client running"
awg show 2>/dev/null || true
sleep infinity
```
> **Как работает policy routing**:
> - Локальный (исходящий) трафик **самого LXC** (SSH и т.д.) → идёт напрямую через `eth0`
> - Только **forwarded** трафик из LAN → помечается меткой → направляется в таблицу `awg-vpn` → уходит через `awg0`
> - Это сохраняет доступ к управлению LXC, не ломая VPN-шлюз
---
## 7. Редактирование сети под свою подсеть
В скрипте выше я использовал `192.168.1.0/24` — это **основной LAN сегмент**, который пойдёт через VPN.
**Если нужна отдельная VPN-подсеть** (например `192.168.2.0/24`), замени в двух местах:
- `iptables -t mangle ... -s 192.168.1.0/24` → `-s 192.168.2.0/24`
- `iptables -t nat ... -s 192.168.1.0/24 ... -o awg0` → `-s 192.168.2.0/24`
Подробнее про отдельную подсеть см. раздел «Расширенный сценарий» ниже.
---
## 8. Запуск
1. **Создай директорию конфига** и положи туда `.conf`:
```bash
mkdir -p /root/awg-config
cp /путь/к/de.conf /root/awg-config/awg0.conf
# ↑ имя файла = имя интерфейса (awg0)
```
2. **Собери образ:**
```bash
cd /root/awg-builder
docker build -t amneziawg-client:latest .
```
3. **Запусти контейнер:**
```bash
docker run -dit \
--name=amneziawg-client \
-v /root/awg-config:/config \
--network=host \
--device=/dev/net/tun:/dev/net/tun \
--cap-add=NET_ADMIN \
--cap-add=SYS_MODULE \
--restart always \
amneziawg-client:latest
```
4. **Проверь:**
```bash
docker ps --filter name=amneziawg-client # Up, restart always
docker logs amneziawg-client # интерфейс UP, handshake
docker exec amneziawg-client awg show # самый наглядный статус
```
---
## 9. Проверка работоспособности
```bash
# Статус интерфейса и handshake (главное)
docker exec amneziawg-client awg show
# Должно быть: "latest handshake: N seconds ago" и ненулевые transfer
# Внешний IP с самого LXC (через awg0):
curl -s ifconfig.me
# Это будет IP VPN-провайдера
# Статус NAT/маршрутизации
docker exec amneziawg-client iptables -t mangle -L PREROUTING -n -v
docker exec amneziawg-client iptables -t nat -L POSTROUTING -n -v
# Проверка forwarded трафика из LAN:
# с устройства в 192.168.1.0/24, у которого шлюз = 192.168.1.147
curl -s ifconfig.me
# Тоже IP VPN-провайдера
```
**Полезный признак нормальной работы:**
```
peer: FfgUO6z0plGUntTW3T8fsFsZ250GcQZEKlCgj1fkRFc=
latest handshake: 42 seconds ago ← периодически обновляется
transfer: 1.24 MiB received, 3.2 MiB sent ← данные идут
```
Если `latest handshake` отсутствует и `received = 0` — пакеты не доходят до сервера. Причины: файрвол роутера блокирует UDP, неверный Endpoint в `.conf`, фильтрация DPI.
---
## 10. Включение шлюза для LAN
Когда туннель поднят, чтобы устройства LAN пошли через VPN, на **роутере** меняют шлюз по умолчанию или статический маршрут:
**Keenetic (веб-интерфейс):**
1. `Интернет-центр → Маршрутизация → Статические маршруты`
2. Добавить:
- Сеть назначения: `0.0.0.0`
- Маска: `0.0.0.0`
- Шлюз: `192.168.1.147`
- (или конкретная VPN-подсеть, если не вся LAN)
**На телефоне (временная проверка):**
- Wi-Fi → IP-настройки → Статический → Маршрутизатор = `192.168.1.147`
---
## 11. Питфоллы и их решение
| Проблема | Причина | Решение |
|----------|---------|---------|
| `Unknown device type. Falling back to userspace` | Нет модуля ядра amneziawg | Нормально; userspace (amneziawg-go) работает |
| `Line unrecognized: S3=145` | Старая версия `awg`, не знает v3.1 параметры | Собрать свежую amneziawg-tools v3.1.x (п.3) |
| `Address=/DNS=` line error | `awg setconf` не понимает `wg-quick` директивы | Убрать `Address`/`DNS` из `setconf` (см. entrypoint) |
| `/proc/sys/...ip_forward: Read-only` | Ограничение LXC / контейнера | Включить заранее на хосте (п.2) |
| Диск забит (`no space left on device`) | Сборки и образы жрут место | `docker system prune`, расширить диск |
| `gcc not found` при сборке tools | Нет компилятора | `apk add gcc musl-dev` в Dockerfile |
| `linux/types.h` нет | Нужны linux-headers | `apk add linux-headers` |
| `cockpit`/быстрые списки GitHub таймаут | DNS внутри build-контейнера | Клонировать на хосте, `COPY` в Dockerfile |
---
## 12. Расширенный сценарий: отдельная VPN-подсеть (вариант B)
Нужно, чтобы не вся LAN уходила в VPN, а только отдельные устройства в своей подсети (`192.168.2.0/24`).
**На LXC добавить alias-IP шлюза:**
```bash
ip addr add 192.168.2.1/32 dev eth0
# persistence: netplan / LXC interface
```
**entrypoint.sh — расширить маршрутизацию:**
```bash
# Вторая подсеть → тоже через VPN
iptables -t mangle -A PREROUTING -s 192.168.2.0/24 ! -d 192.168.2.0/24 -j MARK --set-mark 100
iptables -t nat -A POSTROUTING -s 192.168.2.0/24 -o awg0 -j MASQUERADE
```
**DHCP сервер для 192.168.2.0/24** (dnsmasq на LXC или Docker):
```
interface=eth0
dhcp-range=192.168.2.100,192.168.2.200,255.255.255.0,24h
dhcp-option=3,192.168.2.1
dhcp-option=6,100.64.0.1,8.8.8.8
```
**Keenetic — статический маршрут:**
- Сеть: `192.168.2.0`, маска `255.255.255.0`, шлюз `192.168.1.147`
**Keenetic — гостевая сеть с другой подсетью:**
- Создать вторую SSID, IP `192.168.2.1/24`, DHCP `192.168.2.x`
---
## 13. Обновление версий AWG
Поскольку AmneziaWG 3.x развивается быстро (новые теги), при проблемах с DPI-блокировками:
```bash
# Узнать свежие теги
git ls-remote --tags https://github.com/amnezia-vpn/amneziawg-go.git | tail
git ls-remote --tags https://github.com/amnezia-vpn/amneziawg-tools.git | tail
# Пересобрать из свежих копий
cd /root/awg-src/amneziawg-go && git fetch --tags && git checkout v3.1.XXXXXXX
cd /root/awg-src/amneziawg-tools && git fetch --tags && git checkout v3.1.XXXXXXX
cp -r /root/awg-src/amneziawg-*/* /root/awg-builder/
docker build -t amneziawg-client:latest /root/awg-builder/
```
---
## 14. Безопасность и данные
- **Приватный ключ** в `.conf` не попадает в логи/память ассистента — только в файл на сервере.
- Не выкладывай `.conf` в чат, репозитории, скриншоты.
- `.conf` читается из `/root/awg-config/awg0.conf` только контейнером.
- Права: `chmod 600 /root/awg-config/awg0.conf`.
---
## Итоговая структура файлов
```
/root/awg-config/awg0.conf ← твой .conf (private)
/root/awg-builder/Dockerfile
/root/awg-builder/entrypoint.sh
/root/awg-builder/amneziawg-go/ ← исходники (3.1.20260828)
/root/awg-builder/amneziawg-tools/ ← исходники (3.1.20260812)
/root/awg-src/ ← свежие клоны (для апдейтов)
```
**Контейнер:** `amneziawg-client` = полностью автономный AWG-шлюз, ставится как `--restart always`, не зависит от остальных Docker-сервисов.