Hermes-1 d74ea6cc69 feat: migrate to sing-box v1.13+ native DNS config
- Replace deprecated dns.servers[] with new format (type + server + server_port)
- Add _make_dns_server() to parse udp://, tls://, https:// and bare IP addresses
- Drop ENABLE_DEPRECATED_* environment variable shims — fully v1.14-ready
- Fix transport block: omit for plain TCP (sing-box default), add httpupgrade support
- Add dns.final fallback and route.default_domain_resolver
- Config file renamed to hidden /tmp/.sub2socks.json (matches README)
- Include test_proxy.py live proxy CONNECT test suite
2026-07-03 19:52:43 +00:00

Sub2SOCKS — minimal subscription-to-SOCKS container

One env var, SOCKS proxy. Pulls a subscription URL at startup, picks the first VLESS node from it, generates a sing-box JSON config on the fly and starts sing-box with a SOCKS5 inbound → VLESS outbound.

Quick start

docker run -d --name sub2socks \
  -p 1080:1080 \
  -e SUB_URL="https://your-sub-endpoint.example.com/link/xxxxxxx" \
  sub2socks:latest

Connect to socks5://localhost:1080.

Environment variables

Variable Required? Default Description
SUB_URL yes Subscription group URL (any format with VLESS nodes)
SOCKS_PORT no 1080 SOCKS5 listen port
SOCKS_USER no "" Auth username (leave empty to skip auth)
SOCKS_PASS no "" Auth password
DNS_SERVER no tls://8.8.8.8 Upstream DNS resolver address
PICK_STRATEGY no first Node selection: first (default) or random
LOG_LEVEL no info sing-box log level (debug, warn, error)

With auth + local DNS

docker run -d --name sub2socks \
  -p 1080:1080 \
  -e SUB_URL="https://..." \
  -e SOCKS_USER=myuser \
  -e SOCKS_PASS=secret \
  -e DNS_SERVER=tls://192.168.1.53   # local AdGuard Home, etc.
  sub2socks:latest

With random node selection

docker run -d --name sub2socks \
  -p 1080:1080 \
  -e SUB_URL="https://..." \
  -e PICK_STRATEGY=random \
  sub2socks:latest

In Docker Compose

services:
  sub2socks:
    image: sub2socks:latest
    container_name: sub2socks
    ports:
      - "1080:1080"
    environment:
      SUB_URL: "https://your-sub-endpoint.example.com/sub/xxxxxxx"
      DNS_SERVER: "tls://192.168.1.53"   # your local AdGuard Home

How it works

  1. Entrypoint runs python3 entrypoint.py
  2. Downloads the subscription content & handles base64-encoded payloads automatically
  3. Extracts all VLESS nodes, picks one (first or random)
  4. Writes /tmp/.sub2socks.json — a full sing-box config with that node as outbound
  5. Execs sing-box run -c /tmp/.sub2socks.json (process replacement — no Python in the runtime tree)

Testing connection

docker exec sub2socks python3 -c "
import socket, struct
s = socket.create_connection(('127.0.0.1', 1080), timeout=15)
s.sendall(b'\x05\x01\x00')            # handshake (no auth)
resp = s.recv(2); assert resp[1] == 0 # no auth needed

# CONNECT request to httpbin.org:443
target = b'httpbin.org'
req = b'\x05\x01\x00\x03' + bytes([len(target)]) + target + struct.pack('!H', 443)
s.sendall(req)
resp = s.recv(5)
print('OK!' if resp[1] == 0 else 'FAILED')
"

Build from source

docker build -t sub2socks /path/to/sub2socks/

The final image is ~180 MB (python:3.13-slim + sing-box binary).

S
Description
No description provided
Readme 49 KiB
Languages
Python 97.6%
Dockerfile 2.4%