From 2adc02cb3f5f320b5354bee6fb6db78787056e40 Mon Sep 17 00:00:00 2001 From: embeddevio Date: Wed, 21 Oct 2026 23:30:57 +0300 Subject: [PATCH 1/9] feat(#18): multi-stage Dockerfile (awg-tools + runtime alpine) --- deploy/Dockerfile | 77 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 deploy/Dockerfile diff --git a/deploy/Dockerfile b/deploy/Dockerfile new file mode 100644 index 0000000..e70e00c --- /dev/null +++ b/deploy/Dockerfile @@ -0,0 +1,77 @@ +# syntax=docker/dockerfile:1.7 +# +# awg-dash — единый образ: AmneziaWG gateway + policy routing + REST API + Web UI. +# Задача: #18 (эпик #15). ADR: docs/adr/002-single-image-modular-monolith.md +# +# ВАЖНО: AMNEZIAWG_GO_REF / AMNEZIAWG_TOOLS_REF по умолчанию указывают на master +# и должны быть запинены на проверенный тег/коммит перед релизом (см. #45). + +ARG GO_IMAGE=golang:1.23-alpine + +# --- stage 1: сборка awg-утилит (Go) ----------------------------------------- +FROM ${GO_IMAGE} AS go-build + +ARG AMNEZIAWG_GO_REPO=https://github.com/amnezia-vpn/amneziawg-go.git +ARG AMNEZIAWG_GO_REF=master +ARG AMNEZIAWG_TOOLS_REPO=https://github.com/amnezia-vpn/amneziawg-tools.git +ARG AMNEZIAWG_TOOLS_REF=master + +RUN apk add --no-cache git make gcc musl-dev linux-headers + +WORKDIR /src +RUN git clone --depth 1 --branch "${AMNEZIAWG_GO_REF}" "${AMNEZIAWG_GO_REPO}" amneziawg-go \ + && cd amneziawg-go && make && cp amneziawg-go /usr/local/bin/amneziawg-go + +RUN git clone --depth 1 --branch "${AMNEZIAWG_TOOLS_REF}" "${AMNEZIAWG_TOOLS_REPO}" amneziawg-tools \ + && cd amneziawg-tools/src && make && cp awg /usr/local/bin/awg + +# --- stage 2: runtime ------------------------------------------------------- +FROM alpine:3.21 AS runtime + +LABEL org.opencontainers.image.title="awg-dash" \ + org.opencontainers.image.description="AmneziaWG gateway with intelligent routing: REST API + Web UI + split-tunnel" \ + org.opencontainers.image.source="http://192.168.1.111:3000/embeddevio/awg-dash" + +# Сетевые утилиты: iptables/ip6tables, ipset, iproute2 (policy routing), dnsmasq (ADR-005), +# curl (HEALTHCHECK), tini (PID 1), su-exec (запуск API под непривилегированным пользователем). +RUN apk add --no-cache \ + bash curl iproute2 ipset iptables ip6tables dnsmasq \ + python3 py3-pip tini su-exec \ + && addgroup -S awg \ + && adduser -S -G awg -h /app awg + +ENV PATH=/opt/venv/bin:$PATH \ + PYTHONUNBUFFERED=1 \ + PYTHONDONTWRITEBYTECODE=1 \ + PYTHONPATH=/app/backend \ + AWG_CONFIG_DIR=/config \ + AWG_DATA_DIR=/data \ + AWG_RUN_DIR=/run/awg \ + AWG_API_HOST=0.0.0.0 \ + AWG_API_PORT=8080 + +WORKDIR /app +COPY requirements.txt /app/requirements.txt +RUN apk add --no-cache --virtual .build-deps gcc musl-dev python3-dev libffi-dev \ + && python3 -m venv /opt/venv \ + && /opt/venv/bin/pip install --no-cache-dir --upgrade pip \ + && /opt/venv/bin/pip install --no-cache-dir -r /app/requirements.txt \ + && apk del .build-deps + +COPY backend/ /app/backend/ +COPY --from=go-build /usr/local/bin/awg /usr/local/bin/awg +COPY --from=go-build /usr/local/bin/amneziawg-go /usr/local/bin/amneziawg-go +COPY deploy/entrypoint.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh \ + && mkdir -p /config /data /run/awg \ + && chown -R awg:awg /app /config /data /run/awg + +VOLUME ["/config", "/data"] +EXPOSE 8080 + +# healthcheck ходит в /api/v1/health (задача #31). До реализации API контейнер +# будет помечаться как unhealthy — это ожидаемое состояние до #31. +HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \ + CMD curl -fsS "http://127.0.0.1:${AWG_API_PORT}/api/v1/health" >/dev/null || exit 1 + +ENTRYPOINT ["/sbin/tini", "--", "/entrypoint.sh"] -- 2.47.3 From 71e98912470b0b8d39858825e053919a2edbd705 Mon Sep 17 00:00:00 2001 From: embeddevio Date: Wed, 21 Oct 2026 23:31:04 +0300 Subject: [PATCH 2/9] =?UTF-8?q?feat(#18):=20=D1=81=D1=83=D0=BF=D0=B5=D1=80?= =?UTF-8?q?=D0=B2=D0=B8=D0=B7=D0=BE=D1=80=20entrypoint.sh=20=D0=B8=20?= =?UTF-8?q?=D0=BF=D1=80=D0=B8=D0=BC=D0=B5=D1=80=20.conf?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- deploy/awg0.conf.example | 32 +++++++++++++++++ deploy/entrypoint.sh | 75 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 deploy/awg0.conf.example create mode 100644 deploy/entrypoint.sh diff --git a/deploy/awg0.conf.example b/deploy/awg0.conf.example new file mode 100644 index 0000000..5538ee0 --- /dev/null +++ b/deploy/awg0.conf.example @@ -0,0 +1,32 @@ +# Пример клиентского конфига AmneziaWG для awg-dash. +# +# Скопируйте в том /config как awg0.conf (имя файла = имя интерфейса) или +# загрузите через Web UI (задача #38). Значения ниже — заглушки, замените своими. +# Файл в репозитории не является рабочим конфигом и не содержит реальных ключей. + +[Interface] +# Адрес внутри туннеля (из панели провайдера AmneziaWG) +Address = 10.8.1.2/32 + +# DNS: адрес должен указывать на этот шлюз, иначе не сработает DNS-split (ADR-005) +DNS = 10.8.1.1 + +PrivateKey = + +# Обфускация AmneziaWG (Amnezia VPN: экспорт -> AmneziaWG) +Jc = 4 +Jmin = 40 +Jmax = 70 +S1 = 0 +S2 = 0 +H1 = 1 +H2 = 2 +H3 = 3 +H4 = 4 + +[Peer] +PublicKey = +PresharedKey = +AllowedIPs = 0.0.0.0/0, ::/0 +Endpoint = : +PersistentKeepalive = 25 diff --git a/deploy/entrypoint.sh b/deploy/entrypoint.sh new file mode 100644 index 0000000..5fd7dbb --- /dev/null +++ b/deploy/entrypoint.sh @@ -0,0 +1,75 @@ +#!/bin/sh +# Супервизор контейнера awg-dash (задача #18, ADR-002). +# Последовательность: preflight -> подготовка -> запуск awg-api под awg. +# Привилегированный агент awg-agent стартует отсюда же после реализации (#22). +# +# Роль процесса: все сетевые операции выполняет агент под root; здесь только +# проверяем, что нужные возможности и устройства проброшены, и падаем явной +# ошибкой, если контейнер запущен без них (а не тихо деградируем). +set -eu + +CONFIG_DIR="${AWG_CONFIG_DIR:-/config}" +DATA_DIR="${AWG_DATA_DIR:-/data}" +RUN_DIR="${AWG_RUN_DIR:-/run/awg}" +API_HOST="${AWG_API_HOST:-0.0.0.0}" +API_PORT="${AWG_API_PORT:-8080}" +ROUTING_TABLE_ID=100 +ROUTING_TABLE_NAME=awg-vpn + +log() { printf '[entrypoint] %s\n' "$*"; } +fail() { printf '[entrypoint] FATAL: %s\n' "$*" >&2; exit 1; } + +log 'preflight' +[ -e /dev/net/tun ] || fail '/dev/net/tun не проброшен: добавьте --device=/dev/net/tun:/dev/net/tun' +iptables -t mangle -L -n >/dev/null 2>&1 || fail 'iptables недоступен: нужен --cap-add=NET_ADMIN (и/или --privileged)' +command -v awg >/dev/null 2>&1 || fail 'бинарь awg не найден в образе' +command -v amneziawg-go >/dev/null 2>&1 || log 'WARN: amneziawg-go не найден — остаётся только kernel-модуль' +command -v ipset >/dev/null 2>&1 || fail 'ipset не найден в образе' + +log 'подготовка каталогов состояния' +mkdir -p "$CONFIG_DIR" "$DATA_DIR" "$RUN_DIR" +chown -R awg:awg "$CONFIG_DIR" "$DATA_DIR" "$RUN_DIR" 2>/dev/null || true +chmod 700 "$CONFIG_DIR" "$DATA_DIR" 2>/dev/null || true + +if ! grep -q "^${ROUTING_TABLE_ID} ${ROUTING_TABLE_NAME}" /etc/iproute2/rt_tables 2>/dev/null; then + printf '%s %s\n' "$ROUTING_TABLE_ID" "$ROUTING_TABLE_NAME" >> /etc/iproute2/rt_tables \ + || log 'WARN: не удалось записать таблицу маршрутизации в /etc/iproute2/rt_tables' +fi + +sysctl -w net.ipv4.ip_forward=1 >/dev/null 2>&1 \ + || log 'WARN: не удалось включить net.ipv4.ip_forward (нужен SYS_MODULE или --privileged)' + +log "awg: $(awg --version 2>/dev/null | head -n 1 || echo 'version unknown')" + +api_pid='' +if [ -f /app/backend/awg_api/app.py ]; then + log "запуск awg-api на ${API_HOST}:${API_PORT}" + su-exec awg /opt/venv/bin/uvicorn awg_api.app:app --host "$API_HOST" --port "$API_PORT" & + api_pid=$! +else + log 'WARN: awg_api/app.py ещё не реализован (задача #31) — API не запущен, контейнер работает только как агент' +fi + +stop() { + if [ -n "$api_pid" ] && kill -0 "$api_pid" 2>/dev/null; then + log 'остановка awg-api' + kill -TERM "$api_pid" 2>/dev/null || true + fi +} +trap stop INT TERM + +if [ -n "$api_pid" ]; then + # ждём завершения API и прокидываем его код возврата в Docker + set +e + wait "$api_pid" + rc=$? + set -e + log "awg-api завершился с кодом $rc" + exit "$rc" +fi + +log 'активных процессов нет (agent #22 и api #31 ещё не реализованы) — ожидание сигнала' +while :; do + sleep 3600 & + wait $! +done -- 2.47.3 From ec44dcca4e15df8fecd8a82df906e3d5a60f6275 Mon Sep 17 00:00:00 2001 From: embeddevio Date: Wed, 21 Oct 2026 23:38:47 +0300 Subject: [PATCH 3/9] =?UTF-8?q?fix(#18):=20builder=20=D0=BD=D0=B0=20golang?= =?UTF-8?q?:1.25=20=E2=80=94=20amneziawg-go=20=D1=82=D1=80=D0=B5=D0=B1?= =?UTF-8?q?=D1=83=D0=B5=D1=82=20go=20>=3D=201.25=20(=D0=BF=D0=B0=D0=B4?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=81=D0=B1=D0=BE=D1=80=D0=BA=D0=B8?= =?UTF-8?q?=20=D0=BD=D0=B0=201.23)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- deploy/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/Dockerfile b/deploy/Dockerfile index e70e00c..77ed41e 100644 --- a/deploy/Dockerfile +++ b/deploy/Dockerfile @@ -6,7 +6,7 @@ # ВАЖНО: AMNEZIAWG_GO_REF / AMNEZIAWG_TOOLS_REF по умолчанию указывают на master # и должны быть запинены на проверенный тег/коммит перед релизом (см. #45). -ARG GO_IMAGE=golang:1.23-alpine +ARG GO_IMAGE=golang:1.25-alpine # --- stage 1: сборка awg-утилит (Go) ----------------------------------------- FROM ${GO_IMAGE} AS go-build -- 2.47.3 From 789c1854fef76b955a4e6da750e33e4d281ce545 Mon Sep 17 00:00:00 2001 From: embeddevio Date: Wed, 21 Oct 2026 23:42:43 +0300 Subject: [PATCH 4/9] =?UTF-8?q?fix(#18):=20amneziawg-tools/src=20=D1=81?= =?UTF-8?q?=D0=BE=D0=B1=D0=B8=D1=80=D0=B0=D0=B5=D1=82=20=D0=B1=D0=B8=D0=BD?= =?UTF-8?q?=D0=B0=D1=80=D1=8C=20wg=20=E2=80=94=20=D0=BA=D0=BE=D0=BF=D0=B8?= =?UTF-8?q?=D1=80=D1=83=D0=B5=D0=BC=20=D0=B5=D0=B3=D0=BE=20=D0=BA=D0=B0?= =?UTF-8?q?=D0=BA=20awg=20(+awg-quick)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- deploy/Dockerfile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/deploy/Dockerfile b/deploy/Dockerfile index 77ed41e..9f02af9 100644 --- a/deploy/Dockerfile +++ b/deploy/Dockerfile @@ -23,7 +23,9 @@ RUN git clone --depth 1 --branch "${AMNEZIAWG_GO_REF}" "${AMNEZIAWG_GO_REPO}" am && cd amneziawg-go && make && cp amneziawg-go /usr/local/bin/amneziawg-go RUN git clone --depth 1 --branch "${AMNEZIAWG_TOOLS_REF}" "${AMNEZIAWG_TOOLS_REPO}" amneziawg-tools \ - && cd amneziawg-tools/src && make && cp awg /usr/local/bin/awg + && cd amneziawg-tools/src && make \ + && cp wg /usr/local/bin/awg \ + && if [ -f wg-quick ]; then cp wg-quick /usr/local/bin/awg-quick; fi # --- stage 2: runtime ------------------------------------------------------- FROM alpine:3.21 AS runtime -- 2.47.3 From d2f6e89d58e48e38c685e95dfccb347e761970c1 Mon Sep 17 00:00:00 2001 From: embeddevio Date: Wed, 21 Oct 2026 23:47:15 +0300 Subject: [PATCH 5/9] =?UTF-8?q?fix(#18):=20=D1=81=D0=BE=D0=B7=D0=B4=D0=B0?= =?UTF-8?q?=D0=B2=D0=B0=D1=82=D1=8C=20/etc/iproute2/rt=5Ftables=20(=D0=B2?= =?UTF-8?q?=20alpine=20=D0=B5=D0=B3=D0=BE=20=D0=BD=D0=B5=D1=82)=20+=20?= =?UTF-8?q?=D0=BF=D0=BE=D0=BD=D1=8F=D1=82=D0=BD=D0=BE=D0=B5=20=D0=BF=D1=80?= =?UTF-8?q?=D0=B5=D0=B4=D1=83=D0=BF=D1=80=D0=B5=D0=B6=D0=B4=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20=D0=BF=D1=80=D0=BE=20ip=5Fforward?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- deploy/entrypoint.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/deploy/entrypoint.sh b/deploy/entrypoint.sh index 5fd7dbb..fc8fd84 100644 --- a/deploy/entrypoint.sh +++ b/deploy/entrypoint.sh @@ -31,13 +31,15 @@ mkdir -p "$CONFIG_DIR" "$DATA_DIR" "$RUN_DIR" chown -R awg:awg "$CONFIG_DIR" "$DATA_DIR" "$RUN_DIR" 2>/dev/null || true chmod 700 "$CONFIG_DIR" "$DATA_DIR" 2>/dev/null || true +mkdir -p /etc/iproute2 +touch /etc/iproute2/rt_tables 2>/dev/null || true if ! grep -q "^${ROUTING_TABLE_ID} ${ROUTING_TABLE_NAME}" /etc/iproute2/rt_tables 2>/dev/null; then printf '%s %s\n' "$ROUTING_TABLE_ID" "$ROUTING_TABLE_NAME" >> /etc/iproute2/rt_tables \ || log 'WARN: не удалось записать таблицу маршрутизации в /etc/iproute2/rt_tables' fi sysctl -w net.ipv4.ip_forward=1 >/dev/null 2>&1 \ - || log 'WARN: не удалось включить net.ipv4.ip_forward (нужен SYS_MODULE или --privileged)' + || log 'WARN: net.ipv4.ip_forward не включён — задайте --sysctl net.ipv4.ip_forward=1 или --privileged (см. runbook #45)' log "awg: $(awg --version 2>/dev/null | head -n 1 || echo 'version unknown')" -- 2.47.3 From 20db51b7a2cacc9e73f4ce775af88d17c6b3e42a Mon Sep 17 00:00:00 2001 From: embeddevio Date: Thu, 29 Oct 2026 21:09:52 +0300 Subject: [PATCH 6/9] =?UTF-8?q?fix(#61):=20=D0=B1=D0=B0=D0=BC=D0=BF=20?= =?UTF-8?q?=D0=B1=D0=B0=D0=B7=D0=BE=D0=B2=D1=8B=D1=85=20=D0=BE=D0=B1=D1=80?= =?UTF-8?q?=D0=B0=D0=B7=D0=BE=D0=B2=20=D0=B8=20x/crypto=20=D0=BF=D0=BE?= =?UTF-8?q?=D0=B4=20=D0=B3=D0=B5=D0=B9=D1=82=20image-scan?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - GO_IMAGE golang:1.25-alpine → golang:1.26-alpine (CVE Go stdlib 1.25.14: CVE-2026-56857 CRITICAL, CVE-2026-111943/78667/97031 HIGH) - golang.org/x/crypto → v0.43.0 в amneziawg-go (CVE-2025-47913 HIGH) - runtime alpine:3.21 → alpine:3.23 + apk upgrade (HIGH в пакетах базы) Refs #61, Refs #18, Refs #17 --- deploy/Dockerfile | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/deploy/Dockerfile b/deploy/Dockerfile index 9f02af9..cc7fa49 100644 --- a/deploy/Dockerfile +++ b/deploy/Dockerfile @@ -6,7 +6,12 @@ # ВАЖНО: AMNEZIAWG_GO_REF / AMNEZIAWG_TOOLS_REF по умолчанию указывают на master # и должны быть запинены на проверенный тег/коммит перед релизом (см. #45). -ARG GO_IMAGE=golang:1.25-alpine +# Базовые образы и зависимости подняты под гейт image-scan (issue #61): +# golang:1.26-alpine — закрывает CVE Go stdlib 1.25.14 (CRITICAL CVE-2026-56857 + HIGH) +# golang.org/x/crypto >= v0.43.0 — закрывает CVE-2025-47913 (ssh/agent) +# alpine:3.23 — закрывает HIGH в пакетах alpine 3.21 +ARG GO_IMAGE=golang:1.26-alpine +ARG X_CRYPTO_VERSION=v0.43.0 # --- stage 1: сборка awg-утилит (Go) ----------------------------------------- FROM ${GO_IMAGE} AS go-build @@ -15,12 +20,18 @@ ARG AMNEZIAWG_GO_REPO=https://github.com/amnezia-vpn/amneziawg-go.git ARG AMNEZIAWG_GO_REF=master ARG AMNEZIAWG_TOOLS_REPO=https://github.com/amnezia-vpn/amneziawg-tools.git ARG AMNEZIAWG_TOOLS_REF=master +ARG X_CRYPTO_VERSION RUN apk add --no-cache git make gcc musl-dev linux-headers WORKDIR /src RUN git clone --depth 1 --branch "${AMNEZIAWG_GO_REF}" "${AMNEZIAWG_GO_REPO}" amneziawg-go \ - && cd amneziawg-go && make && cp amneziawg-go /usr/local/bin/amneziawg-go + && cd amneziawg-go \ + && go get "golang.org/x/crypto@${X_CRYPTO_VERSION}" \ + && go mod tidy \ + && go list -m golang.org/x/crypto \ + && make \ + && cp amneziawg-go /usr/local/bin/amneziawg-go RUN git clone --depth 1 --branch "${AMNEZIAWG_TOOLS_REF}" "${AMNEZIAWG_TOOLS_REPO}" amneziawg-tools \ && cd amneziawg-tools/src && make \ @@ -28,7 +39,10 @@ RUN git clone --depth 1 --branch "${AMNEZIAWG_TOOLS_REF}" "${AMNEZIAWG_TOOLS_REP && if [ -f wg-quick ]; then cp wg-quick /usr/local/bin/awg-quick; fi # --- stage 2: runtime ------------------------------------------------------- -FROM alpine:3.21 AS runtime +FROM alpine:3.23 AS runtime + +# Пакеты базы обновляем на момент сборки: trivy --ignore-unfixed учитывает только исправимые CVE. +RUN apk upgrade --no-cache LABEL org.opencontainers.image.title="awg-dash" \ org.opencontainers.image.description="AmneziaWG gateway with intelligent routing: REST API + Web UI + split-tunnel" \ -- 2.47.3 From ea63e904b4e96e45e8f29b21bbd59b4a9b2292f3 Mon Sep 17 00:00:00 2001 From: embeddevio Date: Thu, 29 Oct 2026 21:51:41 +0300 Subject: [PATCH 7/9] fix(#61): x/crypto v0.58.0 + x/net v0.62.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit После бампа Go 1.26 / alpine 3.23 в образе остались только Go-модули: x/crypto v0.43.0 — 5 HIGH (ssh*, фиксы до v0.55.0) x/net v0.45.0 — 16 HIGH (http2/idna/dnsmessage, фиксы до v0.60.0) Оба подняты на актуальные версии из proxy.golang.org (v0.58.0 / v0.62.0). В alpine 3.23.7 находок нет (66 пакетов). Refs #61 --- deploy/Dockerfile | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/deploy/Dockerfile b/deploy/Dockerfile index cc7fa49..f5860ea 100644 --- a/deploy/Dockerfile +++ b/deploy/Dockerfile @@ -8,10 +8,11 @@ # Базовые образы и зависимости подняты под гейт image-scan (issue #61): # golang:1.26-alpine — закрывает CVE Go stdlib 1.25.14 (CRITICAL CVE-2026-56857 + HIGH) -# golang.org/x/crypto >= v0.43.0 — закрывает CVE-2025-47913 (ssh/agent) +# golang.org/x/crypto v0.58.0 + golang.org/x/net v0.62.0 — закрывают CVE в ssh/* и http2/idna # alpine:3.23 — закрывает HIGH в пакетах alpine 3.21 ARG GO_IMAGE=golang:1.26-alpine -ARG X_CRYPTO_VERSION=v0.43.0 +ARG X_CRYPTO_VERSION=v0.58.0 +ARG X_NET_VERSION=v0.62.0 # --- stage 1: сборка awg-утилит (Go) ----------------------------------------- FROM ${GO_IMAGE} AS go-build @@ -21,15 +22,16 @@ ARG AMNEZIAWG_GO_REF=master ARG AMNEZIAWG_TOOLS_REPO=https://github.com/amnezia-vpn/amneziawg-tools.git ARG AMNEZIAWG_TOOLS_REF=master ARG X_CRYPTO_VERSION +ARG X_NET_VERSION RUN apk add --no-cache git make gcc musl-dev linux-headers WORKDIR /src RUN git clone --depth 1 --branch "${AMNEZIAWG_GO_REF}" "${AMNEZIAWG_GO_REPO}" amneziawg-go \ && cd amneziawg-go \ - && go get "golang.org/x/crypto@${X_CRYPTO_VERSION}" \ + && go get "golang.org/x/crypto@${X_CRYPTO_VERSION}" "golang.org/x/net@${X_NET_VERSION}" \ && go mod tidy \ - && go list -m golang.org/x/crypto \ + && go list -m golang.org/x/crypto golang.org/x/net \ && make \ && cp amneziawg-go /usr/local/bin/amneziawg-go -- 2.47.3 From cc3621a12b6dcbdb87d9e44b5f630ed0c8c092f5 Mon Sep 17 00:00:00 2001 From: embeddevio Date: Thu, 29 Oct 2026 22:16:53 +0300 Subject: [PATCH 8/9] =?UTF-8?q?fix(#61):=20=D0=BF=D0=B8=D0=BD=D1=8B=20?= =?UTF-8?q?=D1=82=D1=80=D0=B0=D0=BD=D0=B7=D0=B8=D1=82=D0=B8=D0=B2=D0=BD?= =?UTF-8?q?=D1=8B=D1=85=20python-=D0=B7=D0=B0=D0=B2=D0=B8=D1=81=D0=B8?= =?UTF-8?q?=D0=BC=D0=BE=D1=81=D1=82=D0=B5=D0=B9=20=D0=BF=D0=BE=D0=B4=20?= =?UTF-8?q?=D0=B3=D0=B5=D0=B9=D1=82=20image-scan?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit После бампа Go/alpine/x-crypto/x-net в образе остались 5 HIGH — все в venv: urllib3 2.7.0 → 2.8.0, msgpack 1.1.2 → 1.2.3, setuptools 70.3.0 → 78.1.1 Refs #61 --- requirements.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/requirements.txt b/requirements.txt index dd3b550..fc90cca 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,5 +8,13 @@ httpx>=0.27 structlog>=24.4 prometheus-client>=0.21 +# Транзитивные зависимости с открытыми HIGH — пиним снизу под гейт image-scan (issue #61): +# urllib3 2.7.0 → CVE-2026-97687 (MITM через HTTPS-прокси) / CVE-2026-97689 (DoS), fix 2.8.0 +# msgpack 1.1.2 → CVE-2026-114613 / GHSA-6v7p-g79w-8964, fix 1.2.3 +# setuptools 70.3.0 → CVE-2025-47273 (path traversal), fix 78.1.1 +urllib3>=2.8.0 +msgpack>=1.2.3 +setuptools>=78.1.1 + # Сетевой слой вызывается через бинари (awg, iptables, ipset, dnsmasq), # поэтому python-зависимостей для сети не требуется. -- 2.47.3 From b69c3b67e25e3b5a05a4f2340d03e33a352391d0 Mon Sep 17 00:00:00 2001 From: embeddevio Date: Thu, 29 Oct 2026 22:41:58 +0300 Subject: [PATCH 9/9] =?UTF-8?q?fix(#61):=20=D0=BD=D0=B5=20=D0=BE=D1=81?= =?UTF-8?q?=D1=82=D0=B0=D0=B2=D0=BB=D1=8F=D1=82=D1=8C=20pip=20=D0=B2=20run?= =?UTF-8?q?time-=D0=BE=D0=B1=D1=80=D0=B0=D0=B7=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit trivy разбирает pip/_vendor/vendor.txt и репортит вендоренные msgpack 1.1.2 / urllib3 2.7.0 / setuptools 70.3.0 как установленные пакеты — при том что в venv реально стоят 1.2.4 / 2.8.0 / 84.2.1 (проверено pip list внутри образа staging-cc3621a1). py3-pip переведён в .build-deps и удаляется вместе с ними; pip в venv и системный pip вычищаются — runtime не должен содержать инсталлятора. Refs #61 --- deploy/Dockerfile | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/deploy/Dockerfile b/deploy/Dockerfile index f5860ea..4ff478d 100644 --- a/deploy/Dockerfile +++ b/deploy/Dockerfile @@ -54,7 +54,7 @@ LABEL org.opencontainers.image.title="awg-dash" \ # curl (HEALTHCHECK), tini (PID 1), su-exec (запуск API под непривилегированным пользователем). RUN apk add --no-cache \ bash curl iproute2 ipset iptables ip6tables dnsmasq \ - python3 py3-pip tini su-exec \ + python3 tini su-exec \ && addgroup -S awg \ && adduser -S -G awg -h /app awg @@ -70,11 +70,18 @@ ENV PATH=/opt/venv/bin:$PATH \ WORKDIR /app COPY requirements.txt /app/requirements.txt -RUN apk add --no-cache --virtual .build-deps gcc musl-dev python3-dev libffi-dev \ +# py3-pip нужен только на время сборки venv: в runtime pip не остаётся. Иначе trivy разбирает +# pip/_vendor/vendor.txt и репортит вендоренные версии (msgpack 1.1.2 / urllib3 2.7.0 / +# setuptools 70.3.0) как установленные пакеты — ложные HIGH на образе, где стоят 1.2.4/2.8.0/84.2.1 (issue #61). +RUN apk add --no-cache --virtual .build-deps gcc musl-dev python3-dev libffi-dev py3-pip \ && python3 -m venv /opt/venv \ && /opt/venv/bin/pip install --no-cache-dir --upgrade pip \ && /opt/venv/bin/pip install --no-cache-dir -r /app/requirements.txt \ - && apk del .build-deps + && apk del .build-deps \ + && rm -rf /opt/venv/lib/python3*/site-packages/pip /opt/venv/lib/python3*/site-packages/pip-* \ + && rm -f /opt/venv/bin/pip /opt/venv/bin/pip3 /opt/venv/bin/pip3.* \ + && rm -rf /usr/lib/python3*/site-packages/pip /usr/lib/python3*/site-packages/pip-* \ + && rm -f /usr/bin/pip3 /usr/bin/pip3.* COPY backend/ /app/backend/ COPY --from=go-build /usr/local/bin/awg /usr/local/bin/awg -- 2.47.3