# Docker: образ mtproxy_checker ## Что внутри образа | Компонент | Описание | |-----------|----------| | **База runtime** | Alpine Linux 3.20 | | **Бинарники** | CLI: `/usr/local/bin/mtproxy_checker`. HTTP-сервис списка: `/usr/local/bin/mtproxy_checkerd` (см. ниже) | | **Сертификаты** | Пакет `ca-certificates` (для TLS к реальным хостам при необходимости) | | **ENTRYPOINT** | По умолчанию **CLI** — аргументы `docker run …` идут в `mtproxy_checker` | | **Порты** | В режиме CLI ничего не слушает (только исходящий TCP). Образ объявляет **EXPOSE 8080** для режима API | Одна команда `docker run` с entrypoint по умолчанию = **одна** проверка одного прокси; процесс завершается с **кодом выхода** (`0`…`4`), что удобно в CI и скриптах. ## HTTP API: `mtproxy_checkerd` Лёгкий сервер на стандартной библиотеке Go: читает файл со списком `tg://` (как в разделе «файл — одна ссылка на строку»), **сразу после старта** выполняет первый цикл проверок, затем повторяет с интервалом. Результаты последнего цикла отдаются по HTTP в JSON. ### Запуск контейнера (смена entrypoint) **Linux / macOS:** ```bash docker run --rm -p 8080:8080 \ -v /path/to/proxies.txt:/data/proxies.txt:ro \ --entrypoint /usr/local/bin/mtproxy_checkerd \ mtproxy_checker:local ``` **Windows (PowerShell):** ```powershell docker run --rm -p 8080:8080 ` -v "${PWD}\proxies.txt:/data/proxies.txt:ro" ` --entrypoint /usr/local/bin/mtproxy_checkerd ` mtproxy_checker:local ``` Готовый пример с переменными окружения: репозиторий **`docker-compose.api.yaml`** — `docker 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, `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](https://docs.docker.com/engine/install/) (Linux) или Docker Desktop (Windows/macOS). - Для `docker pull` из приватного registry — логин и токен. ## Сборка образа локально **Linux / macOS:** ```bash cd /path/to/mtproxy_checker docker build -t mtproxy_checker:local . ``` **Windows (PowerShell):** ```powershell cd C:\path\to\mtproxy_checker docker build -t mtproxy_checker:local . ``` Проверка, что образ собран: ```bash docker run --rm mtproxy_checker:local -timeout 5s 2>&1 | head -1 # ожидается сообщение usage (код выхода 2 — нормально без URL) ``` ## Запуск под Linux ### Один прокси (ссылка `tg://`) ```bash docker run --rm mtproxy_checker:local \ 'tg://proxy?server=example.com&port=443&secret=eeYOURHEX...' ``` С флагами утилиты (таймаут, DC): ```bash docker run --rm mtproxy_checker:local \ -timeout 25s -dc-id 2 \ 'tg://proxy?server=example.com&port=443&secret=eeYOURHEX...' ``` Чтобы не светить секрет в истории shell, прочитайте его из файла и передайте флагами (образ запускает бинарник как `ENTRYPOINT`, отдельный `sh` без смены entrypoint использовать нельзя): ```bash 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. - Если имена не резолвятся: ```bash docker run --rm --dns 8.8.8.8 mtproxy_checker:local 'tg://proxy?...' ``` - Режим сети хоста (как на машине без NAT; используйте осознанно): ```bash docker run --rm --network host mtproxy_checker:local 'tg://proxy?...' ``` На Docker Desktop для Windows/macOS `--network host` ведёт себя иначе, чем на Linux. ## Несколько MTProxy ссылок подряд Утилита принимает **ровно один** прокси за запуск. Чтобы проверить много `tg://` ссылок, обходите их в оболочке. ### Вариант 1: цикл в bash ```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... ``` Скрипт: ```bash 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`) Осторожно: одновременно много контейнеров нагружают сеть и целевые прокси. ```bash 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»: ```bash 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 неудобны; проще двойные: ```powershell docker run --rm mtproxy_checker:local ` "tg://proxy?server=example.com&port=443&secret=eeYOURHEX..." ``` Несколько ссылок: ```powershell $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 ([документация](https://docs.gitea.com/usage/packages/container)). 2. Создайте токен с правом на пакеты. 3. Логин: ```bash docker login git.shts.su # или ваш registry ``` 4. Сборка workflow публикует теги `latest`, имя ветки/тега и `sha-…` — см. `.gitea/workflows/docker.yaml`. ```bash 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`: ```yaml services: mtproxy-check: image: mtproxy_checker:local build: . command: ['tg://proxy?server=example.com&port=443&secret=ee...'] ``` ```bash docker compose run --rm mtproxy-check ``` Для списка прокси удобнее внешний bash-цикл или отдельный `command: ["sh","-c","..."]` с циклом по файлу, смонтированному в volume. ## Использование в CI другого проекта ```bash docker run --rm registry.example.com/owner/mtproxy_checker:latest \ "tg://proxy?server=${MTPROXY_HOST}&port=${MTPROXY_PORT}&secret=${MTPROXY_SECRET}" ``` ## Коды выхода и диагностика | Код | Значение | |-----|----------| | 0 | Проверка прошла | | 1 | Ошибка (сеть, протокол, неверный ответ) | | 2 | Неверные аргументы CLI | | 3 | Прокси закрыл TCP сразу после начального payload | | 4 | Общий таймаут (`-timeout`) | **Не путать с ping:** ICMP не используется. Типичные сообщения: - `connection refused` — порт закрыт или фильтр. - `FAIL: timeout` — нет ответа за `-timeout`. - Ошибки чтения/проверки ServerHello — несовместимый ответ или обрыв соединения. Для отладки без `--rm` можно посмотреть логи контейнера по id; с `--rm` контейнер удаляется сразу после выхода.