leeflouring/easy-proxy-pool

★ 0Forks 0GoGitHub ↗Compare

README

Easy Proxies

简体中文

Easy Proxies is a sing-box based proxy pool manager.

It focuses on turning many upstream nodes into one stable local HTTP proxy entry, while still supporting per-node ports when needed.

What It Does

  • Supports pool, multi-port, and hybrid runtime modes.
  • Supports pool scheduling strategies: sequential, random, balance, and adaptive.
  • Builds upstream outbounds for: vmess, vless, trojan, ss/shadowsocks, hysteria2/hy2, socks5/socks, http/https.
  • Supports node sources:
    • inline nodes: in config.yaml
    • nodes_file (one URI per line)
    • structured subscription_sources (auto / clash / v2ray)
    • legacy subscriptions compatibility
  • Provides automatic health checks, node blacklist recovery, and adaptive selection based on latency, active connections, and recent failures.
  • Provides Web dashboard + API for:
    • runtime node status, search/filter/sort, probe, and export
    • settings update (external_ip, probe_target, skip_cert_verify)
    • config node CRUD + reload
    • subscription source CRUD, preview, status, and manual refresh
  • Adds configurable DNS resolver for outbound domain resolution (important for VMess nodes with domain hosts).
  • Optional GeoIP labeling with auto-update and hot-reload (region/country metadata in dashboard).

Compared With the Original Version

Area Original version This version
Subscription import Mainly relies on basic node sources and compatibility-style subscription loading Adds structured subscription_sources, supports auto / clash / v2ray, and allows create/edit/enable/disable/delete directly in Web UI
Subscription workflow Refresh is available, but source visibility and pre-check are limited Adds subscription preview, source status summary, clearer empty-source feedback, and a faster manual refresh flow
Node management Focuses on runtime proxy pool behavior Adds config node CRUD, batch enable/disable, one-click disable for abnormal nodes, and tighter runtime/config linkage
Web UI Covers basic monitoring and management Improves subscription editing layout, filtering experience, region-based views, and reduces UI lag with debounced search and tab short-cache
Reload and recovery Basic reload and port recovery Optimizes subscription-triggered reload path, preserves port mapping during refresh, and avoids unnecessary health-gate blocking in refresh scenarios
Docker / deployment Can run in container with manual setup Improves start.sh, writable mounted data files, persistent ./data workflow, healthcheck readiness, and clearer deployment guidance

In short: the original version already provided a usable sing-box proxy pool, while this version focuses more on subscription operations, Web management ergonomics, runtime recovery, and Docker deployment experience.

Acknowledgements

  • Thanks to jasonwong1991/easy_proxies for the original Easy Proxies project. This version builds on that foundation and extends it with enhanced subscription management, UI experience, and deployment workflow improvements.

Quick Start

1) Local run

cp config.example.yaml config.yaml
cp nodes.example nodes.txt

Edit config.yaml and configure your node source (nodes.txt, subscription_sources, or inline nodes).

Start locally:

go run ./cmd/easy_proxies -config config.yaml

2) Docker / Compose

Recommended:

./start.sh

It prepares:

  • ./data/config.yaml
  • ./data/nodes.txt
  • ./data/geoip/

Then it runs docker compose up -d --build. Compose mounts ./data:/data, so Web UI changes persist directly to the host.

If you prefer to prepare the data directory manually:

mkdir -p data
cp config.example.yaml data/config.yaml
cp nodes.example data/nodes.txt
docker compose up -d

If you want to access the management panel via host port 9090, change management.listen in ./data/config.yaml to 0.0.0.0:9091 and set a strong password.

Minimal Config (Pool Mode)

mode: pool

listener:
  address: 0.0.0.0
  port: 2323
  username: user
  password: pass

pool:
  mode: adaptive      # recommended; sequential / random / balance / adaptive
  failure_threshold: 3
  blacklist_duration: 24h

management:
  enabled: true
  listen: 127.0.0.1:9091  # change to 0.0.0.0:9091 when publishing Docker ports
  probe_target: http://cp.cloudflare.com/generate_204
  password: ""            # set a strong password before exposing the panel

dns:
  server: 223.5.5.5
  port: 53
  strategy: prefer_ipv4

nodes_file: nodes.txt

# Optional: structured subscription sources
# subscription_sources:
#   - name: Main Clash subscription
#     url: https://example.com/sub?token=xxx
#     type: clash       # auto / clash / v2ray
#     enabled: true

DNS Resolver Config

dns controls domain resolution used by sing-box DNS client and VMess domain dialing:

dns:
  server: 223.5.5.5
  fallback_servers:    # Fallback DNS servers (used when primary fails)
    - 8.8.8.8
    - 1.1.1.1
  port: 53
  strategy: prefer_ipv4

Allowed strategy values:

  • as_is
  • prefer_ipv4
  • prefer_ipv6
  • ipv4_only
  • ipv6_only

If you see logs like lookup <domain>: empty result, set a reachable resolver and an explicit strategy.

Runtime Modes

  • pool: one HTTP entry for all nodes.
  • multi-port: one local HTTP port per node.
  • hybrid: pool + multi-port together.

Node Source Behavior

  • If enabled subscription_sources exist:
    • subscription nodes are fetched and appended to runtime nodes
    • nodes_file is used as the output path for fetched nodes
    • startup skips reading nodes_file
  • Legacy subscriptions is still accepted and normalized into the structured source model.
  • Inline nodes always participate when present.

Protocol Notes

Runtime builder supports:

  • vmess
  • vless
  • trojan
  • ss / shadowsocks
  • hysteria2 / hy2
  • socks5 / socks
  • http / https

Parser may recognize additional URI prefixes in subscription text for compatibility, but unsupported schemes are skipped during build.

Management API

Main endpoints:

  • POST /api/auth
  • GET|PUT /api/settings
  • GET /api/nodes
  • POST /api/nodes/{tag}/probe
  • POST /api/nodes/{tag}/release
  • POST /api/nodes/probe-all (SSE)
  • GET /api/export
  • GET /api/subscription/status
  • POST /api/subscription/refresh
  • GET|POST /api/subscriptions
  • POST /api/subscriptions/preview
  • PUT|DELETE /api/subscriptions/{id}
  • GET|POST|PUT|DELETE /api/nodes/config[...]
  • POST /api/reload
  • GET /api/healthz

When management.password is empty, API/UI auth is bypassed.

Docker Notes

  • The Docker image defaults to /data/config.yaml and /data/nodes.txt.
  • Compose mounts ./data:/data so Web UI changes can persist back to the host together with GeoIP data.
  • The bundled healthcheck probes 127.0.0.1:9091/api/healthz inside the container.
  • Before publishing the panel, change management.listen in ./data/config.yaml to 0.0.0.0:9091 and set management.password.
  • If GeoIP is enabled, prefer database_path: ./geoip/GeoLite2-Country.mmdb so the path resolves correctly relative to config.yaml in both local and Docker workflows.

Troubleshooting

  • If ./data/config.yaml or ./data/nodes.txt was accidentally created as a directory, ./start.sh exits early with a clear error.
  • If the container starts but the Web UI is unreachable through published ports, verify that management.listen in ./data/config.yaml is not still 127.0.0.1:9091.
  • If GeoIP labeling does not appear, confirm that the database path exists and resolves correctly relative to the active config.yaml.

Important Operational Notes

  • Reload (/api/reload or subscription refresh) interrupts active connections.
  • Settings API persists values to config.yaml; some changes require reload to fully take effect.
  • Default normalization values (when omitted) are in internal/config/config.go.

Development

go test ./...

Contributors

leeflouring

Issues