Files
mtproxy_checker/docs/docker.ru.md
T
Denozordec e3049028cd
Publish mtproxy_checker Docker image / test (push) Successful in 6s
Publish mtproxy_checker Docker image / build-and-push (push) Successful in 51s
Update README and Docker documentation to clarify exit codes and error handling. Introduce new error for no data received after MTProxy header in checker logic.
2026-04-11 01:35:37 +07:00

13 KiB
Raw Blame History

Docker: образ mtproxy_checker

Что внутри образа

Компонент Описание
База runtime Alpine Linux 3.20
Бинарники CLI: /usr/local/bin/mtproxy_checker. HTTP-сервис списка: /usr/local/bin/mtproxy_checkerd (см. ниже)
Сертификаты Пакет ca-certificates (для TLS к реальным хостам при необходимости)
ENTRYPOINT Скрипт docker-entrypoint.sh: есть аргументы после имени образа → mtproxy_checker (разовая проверка); нет аргументовmtproxy_checkerd (HTTP API)
Порты В режиме CLI ничего не слушает (только исходящий TCP). В режиме API слушает 8080 (или MTPROXY_HTTP_ADDR). Образ объявляет EXPOSE 8080

docker run … ИМЯ_ОБРАЗА tg://… или с флагами — одна проверка, код выхода 04. docker run … ИМЯ_ОБРАЗА без command — долгоживущий API (нужны volume/env к файлу со списком).

HTTP API: mtproxy_checkerd

Лёгкий сервер на стандартной библиотеке Go: читает файл со списком tg:// (как в разделе «файл — одна ссылка на строку»), сразу после старта выполняет первый цикл проверок, затем повторяет с интервалом. Результаты последнего цикла отдаются по HTTP в JSON.

Запуск контейнера в режиме API

Без command / аргументов после образа entrypoint сам запускает mtproxy_checkerd.

Linux / macOS:

docker run -d --name mtproxy-api --restart unless-stopped -p 8080:8080 \
  -v /path/to/proxies.txt:/data/proxies.txt:ro \
  -e MTPROXY_CHECK_INTERVAL=60m \
  mtproxy_checker:local

Windows (PowerShell):

docker run -d --name mtproxy-api --restart unless-stopped -p 8080:8080 `
  -v "${PWD}/proxies.txt:/data/proxies.txt:ro" `
  -e MTPROXY_CHECK_INTERVAL=60m `
  mtproxy_checker:local

Явно указать демон (редко нужно): --entrypoint /usr/local/bin/mtproxy_checkerd.

Готовый пример: docker-compose.api.yamldocker compose -f docker-compose.api.yaml up --build.

Переменные окружения

Переменная По умолчанию Назначение
MTPROXY_LIST_FILE /data/proxies.txt Путь к файлу: одна tg:// ссылка на строку; пустые строки и строки с # в начале пропускаются
MTPROXY_CHECK_INTERVAL 5m Интервал между циклами (time.ParseDuration, например 5m, 1h)
MTPROXY_HTTP_ADDR :8080 Адрес прослушивания HTTP
MTPROXY_CHECK_TIMEOUT 15s Таймаут одной проверки (аналог -timeout CLI)
MTPROXY_DC_ID 2 DC id (аналог -dc-id CLI)
MTPROXY_ALLOWED_IPS (не задана) Если задана непустая строка — доступ к всем маршрутам только с перечисленных IP/CIDR; остальные получают 403 и JSON {"error":"forbidden"}. Формат: через запятую, пробелы допускаются: 192.168.1.10, 10.0.0.0/8, IPv6 и CIDR вида 2001:db8::/32. Учитывается только RemoteAddr TCP-соединения; заголовок X-Forwarded-For не используется

HTTP

Метод Путь Ответ
GET /health 200, {"status":"ok"}
GET /api/v1/proxies 200, JSON с полями cycle_finished_at, next_check_after, массив proxies

Элемент proxies[]: raw_line, при успешном разборе — url, ok, exit_code (0 OK — после отправки MTProxy-заголовка прочитан хотя бы один байт от сервера; 1 ошибка проверки, в т.ч. если за окно ожидания нет ни одного байта ответа; 2 ошибка разбора URL/секрета; 3 прокси закрыл соединение; 4 таймаут всего запроса), error, при необходимости parse_error, checked_at.

Whitelist IP и Docker

Процесс видит IP источника TCP таким, каким его передал стек в контейнер. При пробросе порта с хоста (-p 8080:8080) на Linux часто это адрес шлюза bridge или userland-proxy, а не «настоящий» IP клиента с хоста. Имеет смысл задавать CIDR подсети Docker (например 172.17.0.0/16), слушать только внутреннюю сеть, использовать --network host (на Linux) или ограничивать доступ на обратном прокси (nginx allow и т.п.).

Требования

  • Docker Engine (Linux) или Docker Desktop (Windows/macOS).
  • Для docker pull из приватного registry — логин и токен.

Сборка образа локально

Linux / macOS:

cd /path/to/mtproxy_checker
docker build -t mtproxy_checker:local .

Windows (PowerShell):

cd C:\path\to\mtproxy_checker
docker build -t mtproxy_checker:local .

Проверка, что образ собран (нужен хотя бы один аргумент, иначе стартует API):

docker run --rm mtproxy_checker:local -timeout 5s 2>&1 | head -1
# ожидается сообщение usage CLI (код выхода 2 — нормально без URL)

Запуск под Linux

Один прокси (ссылка tg://)

docker run --rm mtproxy_checker:local \
  'tg://proxy?server=example.com&port=443&secret=eeYOURHEX...'

С флагами утилиты (таймаут, DC):

docker run --rm mtproxy_checker:local \
  -timeout 25s -dc-id 2 \
  'tg://proxy?server=example.com&port=443&secret=eeYOURHEX...'

Чтобы не светить секрет в истории shell, прочитайте его из файла и передайте флагами (аргументы уходят в CLI через docker-entrypoint.sh):

SECRET=$(tr -d ' \n' < secret.hex)
docker run --rm mtproxy_checker:local \
  --server example.com --port 443 --secret "$SECRET"

Сеть и DNS на Linux

  • По умолчанию контейнер использует bridge Docker; нужен исходящий доступ к server:port и рабочий DNS.
  • Если имена не резолвятся:
docker run --rm --dns 8.8.8.8 mtproxy_checker:local 'tg://proxy?...'
  • Режим сети хоста (как на машине без NAT; используйте осознанно):
docker run --rm --network host mtproxy_checker:local 'tg://proxy?...'

На Docker Desktop для Windows/macOS --network host ведёт себя иначе, чем на Linux.

Несколько MTProxy ссылок подряд

Утилита принимает ровно один прокси за запуск. Чтобы проверить много tg:// ссылок, обходите их в оболочке.

Вариант 1: цикл в bash

IMAGE=mtproxy_checker:local   # или registry/owner/mtproxy_checker:latest

for url in \
  'tg://proxy?server=a.example.com&port=443&secret=ee1111...' \
  'tg://proxy?server=b.example.com&port=8443&secret=ee2222...' \
  'tg://proxy?server=c.example.com&port=443&secret=dd3333...'
do
  echo "=== $url ==="
  if docker run --rm "$IMAGE" -timeout 20s "$url"; then
    echo "OK"
  else
    echo "FAIL (код $?)"
  fi
done

Вариант 2: файл — одна ссылка на строку

proxies.txt (пустые строки и строки с # в начале можно пропускать):

tg://proxy?server=one.example.com&port=443&secret=ee...
tg://proxy?server=two.example.com&port=8443&secret=ee...

Скрипт:

IMAGE=mtproxy_checker:local

while IFS= read -r line || [ -n "$line" ]; do
  line="${line#"${line%%[![:space:]]*}"}"   # trim leading spaces
  [ -z "$line" ] && continue
  case "$line" in \#*) continue ;; esac

  echo "=== $line ==="
  docker run --rm "$IMAGE" -timeout 20s "$line" && echo OK || echo "FAIL ($?)"
done < proxies.txt

Вариант 3: параллельно (xargs)

Осторожно: одновременно много контейнеров нагружают сеть и целевые прокси.

IMAGE=mtproxy_checker:local

grep -v '^\s*$\|^\s*#' proxies.txt | xargs -I{} -P 4 sh -c \
  'echo "=== {}"; docker run --rm '"$IMAGE"' -timeout 20s "{}" || echo FAIL'

-P 4 — не более четырёх проверок одновременно; уменьшите при необходимости.

Вариант 4: итоговый код для CI

Если нужен «провал всего job при любом FAIL»:

set -e
IMAGE=mtproxy_checker:local
while IFS= read -r url; do
  [ -z "$url" ] && continue
  case "$url" in \#*) continue ;; esac
  docker run --rm "$IMAGE" -timeout 25s "$url"
done < proxies.txt

Запуск из PowerShell (Windows)

Одинарные кавычки с tg:// в PowerShell неудобны; проще двойные:

docker run --rm mtproxy_checker:local `
  "tg://proxy?server=example.com&port=443&secret=eeYOURHEX..."

Несколько ссылок:

$urls = @(
  "tg://proxy?server=a.com&port=443&secret=ee...",
  "tg://proxy?server=b.com&port=8443&secret=ee..."
)
foreach ($u in $urls) {
  Write-Host "=== $u ==="
  docker run --rm mtproxy_checker:local -timeout 20s $u
  if ($LASTEXITCODE -ne 0) { Write-Host "FAIL exit $LASTEXITCODE" }
}

Загрузка образа из Container Registry Gitea

  1. Включите Packages / Container Registry на инстансе Gitea (документация).
  2. Создайте токен с правом на пакеты.
  3. Логин:
docker login git.shts.su
# или ваш registry
  1. Сборка workflow публикует теги latest, имя ветки/тега и sha-… — см. .gitea/workflows/docker.yaml.
docker pull git.shts.su/owner/mtproxy_checker:latest
docker run --rm git.shts.su/owner/mtproxy_checker:latest 'tg://proxy?...'

Пример docker-compose

Одна проверка за compose run:

services:
  mtproxy-check:
    image: mtproxy_checker:local
    build: .
    command: ['tg://proxy?server=example.com&port=443&secret=ee...']
docker compose run --rm mtproxy-check

Для списка прокси удобнее внешний bash-цикл или отдельный command: ["sh","-c","..."] с циклом по файлу, смонтированному в volume.

Использование в CI другого проекта

docker run --rm registry.example.com/owner/mtproxy_checker:latest \
  "tg://proxy?server=${MTPROXY_HOST}&port=${MTPROXY_PORT}&secret=${MTPROXY_SECRET}"

Коды выхода и диагностика

Код Значение
0 Проверка прошла: после MTProxy-заголовка получен хотя бы один байт от прокси
1 Ошибка (сеть, протокол, неверный ответ; в т.ч. нет данных от прокси после заголовка за окно ожидания)
2 Неверные аргументы CLI
3 Прокси закрыл TCP сразу после начального payload
4 Общий таймаут (-timeout)

Не путать с ping: ICMP не используется.

Типичные сообщения:

  • connection refused — порт закрыт или фильтр.
  • FAIL: timeout — нет ответа за -timeout.
  • no data from proxy after mtproxy header — рукопожатие прошло, но прокси не прислал ни одного байта в фазе после заголовка (часто совпадает с «Недоступен» в клиенте Telegram).
  • Ошибки чтения/проверки ServerHello — несовместимый ответ или обрыв соединения.

Для отладки без --rm можно посмотреть логи контейнера по id; с --rm контейнер удаляется сразу после выхода.