Rigel — no-KYC SOCKS5 Proxy Shop
Self-hosted SOCKS5 proxy storefront. Sells access to datacenter / residential / mobile proxies. Bitcoin via BTCPay. No KYC — username + email + password + arithmetic captcha, nothing else.
Status: LIVE — end-to-end verified 2026-09-10. Real BTC payment → NBXplorer match → BTCPay webhook → subscription activated → per-user SOCKS5 credentials issued → authenticated proxy access proven from an external network (off-LAN vantage, correct country exit).
Stack
| Piece | Detail |
|---|---|
| Storefront | Flask SPA — /opt/rigel/app.py (SQLite, no-KYC auth, BTCPay invoicing) |
| Proxy frontend | /opt/rigel/proxy_server.py — authenticated SOCKS5 on :1081 |
| Container | CT 158 rigel @ 10.30.20.116 — Debian 12, nginx :80 → Flask :5000 |
| Services | rigel.service (:5000), rigel-proxy.service (:1081) |
| Payments | BTCPay (store id + keys in Teable → API_Credentials) — webhook → POST /api/btcpay/webhook |
| Public web | https://rigel.thetempleofdoom.com (fleet tunnel 1aeb1ac0, remote-managed) |
| Public SOCKS5 | 76.146.4.178:1081 — WAN port-forward (see below) |
No secrets in this repo. Store IDs, API keys and webhook secrets live in the
rigel.serviceenvironment and in Teable →API_Credentials.
Inventory
| Location | Type | Endpoint |
|---|---|---|
| Tokyo | datacenter (Nord exit) | CT680 10.30.20.154:1080 |
| London | datacenter (Nord exit) | CT681 10.30.20.71:1080 |
| Sydney | datacenter (Nord exit) | CT682 10.30.20.189:1080 |
| Residential | rotating / sticky | IPRoyal geo.iproyal.com:12321 |
| Mobile 4G | rotating | IPRoyal 4g.iproyal.com |
proxy_server.py derives the upstream list from app.py's LOCATIONS (single source of
truth) so the shop and the proxy can never disagree about inventory.
API
| Route | Body | Purpose |
|---|---|---|
GET /api/captcha |
— | arithmetic challenge |
POST /api/register |
{username, email, password, captcha_id, captcha} |
no-KYC signup |
POST /api/login |
{username, password} |
session |
POST /api/buy |
{plan_id} |
creates BTCPay invoice + pending subscription |
GET /api/subscriptions |
— | user's active proxies + issued credentials |
POST /api/btcpay/webhook |
BTCPay payload | activates subscription + issues creds |
Plans: day (8,000 sats) · week (45,000 sats) · month (150,000 sats).
Public SOCKS5 access — the part that isn't obvious
A Cloudflare tunnel cannot carry SOCKS5 (HTTP-only), and Tailscale Funnel's raw-TCP mode
does not actually forward publicly (verified, then reverted). Customers therefore connect to
the home WAN IP directly: the router DNATs tcp 1081 → 10.30.20.116:1081.
⚠️ If SOCKS5 ever stops being reachable from the internet, check in this order:
- Router —
iptables -t nat -L VSERVER -n | grep 1081 - Hook present? —
/jffs/scripts/firewall-startmust exist and be executable (setting thevts_rulelistnvram var alone does not emit the DNAT on this firmware) - Service —
systemctl is-active rigel-proxyinside CT158 - Never trust a LAN test — NAT loopback can pass while the world can't reach it. Verify from an external host.
Auth model
proxy_server.py validates every SOCKS5 username/password against rigel.db:
the subscription must exist, be active, and not expired. The subscription's location
selects the upstream exit. Unknown user, wrong password, expired sub, or wrong auth method →
rejected; no traffic leaves. All time comparisons are UTC.
Deploy
tar czf rigel.tar.gz app.py proxy_server.py
scp rigel.tar.gz root@10.30.20.85:/tmp/
ssh root@10.30.20.85 "pct push 158 /tmp/rigel.tar.gz /tmp/rigel.tar.gz && pct exec 158 -- bash -c '
cd /opt/rigel &&
cp app.py app.py.bak-\$(date +%s) &&
cp proxy_server.py proxy_server.py.bak-\$(date +%s) &&
tar xzf /tmp/rigel.tar.gz &&
systemctl restart rigel rigel-proxy'"
Always back up the running file before overwriting it. CT158 does not accept the standard
fleet root password over SSH — deploy through the Proxmox host with pct exec.
Gotchas
- Fleet tunnel is REMOTE-MANAGED — edit ingress via the Cloudflare API, not the local
config-fleet.yml. Local edits are silently ignored. checkoutLinkcomes back with the LAN host (it's derived from the API call's Host header) —app.pyrewrites the prefix ontoBTCPAY_PUBLIC_URL.- SOCKS5 CONNECT to a domain target must length-prefix the domain (
atyp=3). Omit the prefix and the upstream reads the first character as a length and hangs. rigel.dbis gitignored — never commit the live database.- BTCPay
NetworkFeeMode = Alwaysmakes the exact amount land a few sats short (PaidPartialrather thanSettled); activation still fires. Not settable via the Greenfield API.