From e05e658d817ae263804a0f6a6184c1bfca00b1bf Mon Sep 17 00:00:00 2001 From: jze9 Date: Wed, 26 Aug 2026 17:37:26 +0500 Subject: [PATCH] =?UTF-8?q?feat(proxy):=20sing-box=20=D0=B4=D0=BB=D1=8F=20?= =?UTF-8?q?=D0=BE=D0=B1=D1=85=D0=BE=D0=B4=D0=B0=20=D0=B1=D0=BB=D0=BE=D0=BA?= =?UTF-8?q?=D0=B8=D1=80=D0=BE=D0=B2=D0=BA=D0=B8=20OpenRouter=20=D0=B8?= =?UTF-8?q?=D0=B7=20=D0=A0=D0=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit OpenRouter отдаёт 403 с российских IP (подтверждено вживую). Добавлен sing-box как отдельный сервис (VLESS+WS+TLS до ноды вне РФ) — только для исходящих запросов к OpenRouter из ollama_client.py, остальной трафик (Postgres/RabbitMQ/MinIO/Ollama) идёт напрямую. Реальный конфиг с UUID — только на проде (см. config.json.example), в git не попадает. --- .gitignore | 3 ++ docker-compose.prod.yml | 15 +++++++++ infra/singbox/config.json.example | 39 ++++++++++++++++++++++++ services/worker-gpu/app/config.py | 3 ++ services/worker-gpu/app/ollama_client.py | 1 + services/worker-gpu/requirements.txt | 1 + 6 files changed, 62 insertions(+) create mode 100644 infra/singbox/config.json.example diff --git a/.gitignore b/.gitignore index 6580af5..11927f5 100644 --- a/.gitignore +++ b/.gitignore @@ -106,3 +106,6 @@ services/**/app/models/**/*.py[cod] tmp/ temp/ CREDENTIALS.md + +# Прокси-конфиг с реальными credentials (UUID) — только на проде, не в git +infra/singbox/config.json diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index da596cb..ec1c30c 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -109,6 +109,19 @@ services: elasticsearch: condition: service_healthy + # SOCKS5-прокси (sing-box → VLESS-нода вне РФ) — OpenRouter недоступен + # напрямую из России, только для этого и нужен. Остальной трафик + # worker-gpu (Postgres/RabbitMQ/MinIO/Ollama) идёт напрямую, не через него. + singbox-proxy: + image: ghcr.io/sagernet/sing-box:v1.10.0 + container_name: antiplagiator-singbox-proxy + command: run -c /etc/sing-box/config.json + volumes: + - ./infra/singbox/config.json:/etc/sing-box/config.json:ro + networks: + - antiplagiator + restart: unless-stopped + worker-gpu: build: context: ./services/worker-gpu @@ -120,6 +133,8 @@ services: depends_on: elasticsearch: condition: service_healthy + singbox-proxy: + condition: service_started worker-indexer: build: diff --git a/infra/singbox/config.json.example b/infra/singbox/config.json.example new file mode 100644 index 0000000..f00d60a --- /dev/null +++ b/infra/singbox/config.json.example @@ -0,0 +1,39 @@ +{ + "log": { + "level": "warn" + }, + "inbounds": [ + { + "type": "socks", + "tag": "socks-in", + "listen": "0.0.0.0", + "listen_port": 1080 + } + ], + "outbounds": [ + { + "type": "vless", + "tag": "proxy-out", + "server": "CHANGE_ME.example.com", + "server_port": 443, + "uuid": "CHANGE_ME-uuid", + "packet_encoding": "xudp", + "tls": { + "enabled": true, + "server_name": "CHANGE_ME.example.com", + "alpn": ["http/1.1"], + "utls": { + "enabled": true, + "fingerprint": "chrome" + } + }, + "transport": { + "type": "ws", + "path": "/api/stream" + } + } + ], + "route": { + "final": "proxy-out" + } +} diff --git a/services/worker-gpu/app/config.py b/services/worker-gpu/app/config.py index 53bf0aa..1406834 100644 --- a/services/worker-gpu/app/config.py +++ b/services/worker-gpu/app/config.py @@ -45,6 +45,9 @@ class Settings(BaseSettings): OPENROUTER_API_KEY: str = "" OPENROUTER_MODEL: str = "deepseek/deepseek-chat" OPENROUTER_URL: str = "https://openrouter.ai/api/v1/chat/completions" + # OpenRouter блокирует запросы из РФ — заворачиваем именно эти запросы + # через sing-box (docker-compose сервис singbox-proxy). Пусто = без прокси. + OPENROUTER_PROXY_URL: str = "socks5://singbox-proxy:1080" # FAISS / ML FAISS_INDEX_PATH: str = "/data/index/faiss.index" diff --git a/services/worker-gpu/app/ollama_client.py b/services/worker-gpu/app/ollama_client.py index 569d6c6..760beee 100644 --- a/services/worker-gpu/app/ollama_client.py +++ b/services/worker-gpu/app/ollama_client.py @@ -67,6 +67,7 @@ class OllamaClient: json=payload, headers={"Authorization": f"Bearer {settings.OPENROUTER_API_KEY}"}, timeout=self.timeout, + proxy=settings.OPENROUTER_PROXY_URL or None, ) response.raise_for_status() return response.json()["choices"][0]["message"]["content"] diff --git a/services/worker-gpu/requirements.txt b/services/worker-gpu/requirements.txt index 86bef1c..e78c954 100644 --- a/services/worker-gpu/requirements.txt +++ b/services/worker-gpu/requirements.txt @@ -8,6 +8,7 @@ qdrant-client==1.19.0 # альтернативный векторный бэк torch==2.3.0 numpy==1.26.4 httpx==0.27.0 +socksio==1.0.0 # SOCKS5-прокси для httpx (нужен для OpenRouter из РФ, см. app.ollama_client) minio==7.2.7 datasketch==1.6.5 pydantic-settings==2.2.1