[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-95138":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":8,"htmlUrl":8,"language":9,"languages":8,"totalLinesOfCode":8,"stars":10,"forks":11,"watchers":12,"openIssues":13,"contributorsCount":13,"subscribersCount":13,"size":13,"stars1d":14,"stars7d":15,"stars30d":15,"stars90d":13,"forks30d":13,"starsTrendScore":16,"compositeScore":17,"rankGlobal":8,"rankLanguage":8,"license":8,"archived":18,"fork":18,"defaultBranch":19,"hasWiki":20,"hasPages":18,"topics":21,"createdAt":8,"pushedAt":8,"updatedAt":22,"readmeContent":23,"aiSummary":24,"trendingCount":13,"starSnapshotCount":13,"syncStatus":25,"lastSyncTime":26,"discoverSource":27},95138,"SpiderPanel","amirh00sain\u002FSpiderPanel","amirh00sain",null,"Python",603,1965,181,0,119,250,488,97.82,false,"main",true,[],"2026-08-24 04:01:23","\u003Cdiv align=\"center\">\n\n# 🕷️ Spider Panel\n\n**VLESS \u002F XHTTP \u002F WS‑TLS subscription & proxy‑relay panel**\nFastAPI panel for Railway + Cloudflare Workers. Manage users, inbounds, Reality \u002F WS‑TLS configs, browser‑side IP scanning and a multi‑location Cloudflare Worker proxy — all from one dashboard.\n\n> فارسی: پنل مدیریتی و فروش سرویس VLESS با قابلیت ساخت سابسکریپشن، مدیریت کاربران و اینباندها، اسکنر آیپی (سمت مرورگر) و مدیریت Worker کلادفلر برای پروکسی چندمنطقهای.\n\n\u003C\u002Fdiv>\n\n---\n\n## ✨ Features\n\n- **VLESS Reality** — keys (x25519 + ML‑DSA‑65 post‑quantum) generated by the **Xray binary itself**, never by Python crypto. Fresh `pbk` \u002F `sid` \u002F `spx` per inbound.\n- **VLESS + WS + TLS** — the config always points `address` \u002F `host` \u002F `sni` at the **real panel domain** automatically (no manual domain entry, no `localhost`).\n- **XHTTP (packet‑up \u002F stream‑up \u002F stream‑one)** — 3x‑UI style XHTTP transports.\n- **Multi‑inbound per user** — one user can belong to several inbounds → each produces its own config in the subscription.\n- **Sub page** — clean black + teal page, iOS system font, status config always first, **main configs on top and custom‑IP configs below** with a labeled separator.\n- **Custom‑IP (scanner) configs** — up to 10 extra WS‑TLS configs whose `address` is a scanned CF\u002FRailway IP, while `host`\u002F`sni` stay on the real domain.\n- **Browser‑side IP scanner** — Cloudflare \u002F Railway \u002F TCP. Pings run from **the user's own internet** via `fetch(..., { mode: 'no-cors' })` — no server bandwidth, works on mobile. Cleared results **stay cleared** (seq‑guarded writes).\n- **Cloudflare Worker manager** — connect the panel to your Cloudflare account, deploy a proxy worker, manage a country → proxy‑IP pool, and route only the users who opt in through `Worker Domain + \u002Froute\u002F{code}`. **Railway is never in the VPN data path.**\n- **Map + proxy IP selector** — pick up to 3 proxy IPs per user with live ping.\n- **Full dashboard** — users, inbounds, groups, live traffic\u002FCPU\u002FRAM, panel music, light\u002Fdark mode, FA\u002FEN (sidebar stays put on language switch), SVG‑only icons.\n\n---\n\n## 🧭 Architecture\n\n```\n            ┌─────────────────────────┐\n            │   Railway (this panel)  │   Panel \u002F API \u002F user mgmt \u002F config generator \u002F worker manager\n            └────────────┬────────────┘\n                         │  (only management + config serving — NOT in the VPN path)\n                         │\n   ┌─────────┐      ┌────▼──────────┐      ┌──────────────────┐      ┌───────────┐\n   │ Client  │ ───▶ │ Worker Domain │ ───▶ │ Cloudflare Worker │ ───▶ │ Proxy IP  │ ──▶ Internet\n   └─────────┘      └───────────────┘      └──────────────────┘      └───────────┘\n            (users with proxy_ip_enabled=true)\n```\n\n- **Normal users** connect straight to the panel's Reality \u002F WS inbounds.\n- **Worker users** (`proxy_ip_enabled = true`) get a config addressed to the **Worker domain** with path `\u002Froute\u002F{country-code}`. The Worker looks up the country → proxy IP and forwards the connection. Traffic never crosses Railway.\n\n---\n\n## 🚀 Deploy on Railway\n\n1. **Push this repo** to GitHub (or use the template directly).\n2. On Railway: **New Project → Deploy from GitHub → select the repo**.\n3. Railway auto‑detects the Python app (`python main.py`) and reads `PORT`.\n4. Add the environment variables below.\n5. Open the generated `*.up.railway.app` URL → sign in with the default password (`admin`) → **change it immediately**.\n\n### Environment variables\n\n| Variable | Default | Purpose |\n|---|---|---|\n| `PORT` | `8080` | HTTP port Railway forwards to |\n| `ADMIN_PASSWORD` | `admin` | Initial dashboard password (change after first login) |\n| `SECRET_KEY` | `spider-panel-secret-key-v2` | Session \u002F hashing secret — **set a strong random one** |\n| `RAILWAY_PUBLIC_DOMAIN` | — | Auto‑set by Railway; used as the real panel domain in configs |\n| `DATA_DIR` | `\u002Fdata` | Persistence dir for `spider_state.json` |\n| `WORKER_SYNC_INTERVAL` | `3600` | Seconds between auto proxy-source syncs (default: hourly) |\n\n> `RAILWAY_PUBLIC_DOMAIN` is provided automatically. The WS‑TLS config generator uses it (or an optional manually set domain) for `address`\u002F`host`\u002F`sni` — **no manual domain typing required**.\n\n---\n\n## ⚡ Cloudflare Worker setup (optional, for multi-location proxy)\n\nThe **Worker** tab in the sidebar walks you through connecting the panel to a Cloudflare Worker. The deployed Worker is a **VLESS WS relay** (edgetunnel-style): it accepts WebSocket connections from VLESS clients, authenticates them via UUID in its KV store, and forwards traffic through a TCP proxy to the target.\n\n**Supported auth:** Global API Key (`cfk_...` + email) or Bearer token.\n\n1. Open **Worker** in the sidebar → Setup form.\n2. **Cloudflare API Token** — create a Global API Key at \u003Chttps:\u002F\u002Fdash.cloudflare.com\u002Fprofile\u002Fapi-tokens> or a scoped token with `Workers Scripts: Edit` + `KV Storage: Edit` permissions.\n3. **Email** — your Cloudflare account email (required for Global API Key auth).\n4. **Account ID** — your Cloudflare account UUID (dashboard overview \u002F right sidebar).\n5. Click **Connect & Deploy**. The panel:\n   - Verifies the token\u002Femail\n   - Auto-discovers your Worker subdomain from the Cloudflare API\n   - Creates a KV namespace (`spider-worker-kv`) and binds it to the Worker\n   - Deploys the VLESS WS relay script (from `worker\u002F_worker.js` in this repo)\n   - Pushes all active panel users (uuid + traffic limit + expiry) to the Worker's KV\n6. In the **Worker tab**, the **Proxy IP Pool** shows all available country proxies (fetched daily from the GitHub source). Use the dropdown to manage them.\n\n> **How it works:** When a user picks a Worker inbound, the panel syncs their `config_uuid` → `limit_bytes` + `expire` to the Worker's KV. The Worker authenticates by checking `user:{uuid}` in KV. Users whose quota is exceeded or whose expiry has passed get a 403.\n\n> **Traffic flow:** Client → Worker Domain (wss:\u002F\u002F) → Cloudflare Worker → target IP → Internet. Railway is only the control plane (panel \u002F API \u002F config generation \u002F user management).\n\n### Worker source lives in the repo\n\n`worker\u002F_worker.js` is the deployed script. The panel reads it at deploy time and injects `__PANEL_DOMAIN__` and `__PANEL_TOKEN__` before uploading. You can edit the Worker logic with a normal git push — no need to touch Python code.\n\n### Daily proxy auto-sync\n\nThe panel can pull a fresh **country → proxy list** from a daily GitHub source and push it to the deployed Worker automatically:\n\n- **Every hour** (configurable via `WORKER_SYNC_INTERVAL`, default `3600`), if the worker is connected and auto-sync is on, the panel fetches the source, parses it and re-deploys the worker with the updated map.\n- **Source** defaults to the [NiREvil `ProxyIP-Daily.md`](https:\u002F\u002Fgithub.com\u002FNiREvil\u002Fvless\u002Fblob\u002Fmain\u002Fsub\u002FProxyIP-Daily.md) list (62 countries, best-risk IPs first). You can change the URL in the Worker tab.\n- The parser decodes each section's **flag emoji → ISO country code**, keeps the first 3 IPs per country, and the Worker **round-robins** across them per request.\n- Manual entries you add\u002Fedit in the panel carry a `manual` flag and **survive** source refreshes (your overrides are never wiped).\n- In the **Worker** tab you get: auto-update toggle, source URL, a **\"Update Now\"** button, and a country\u002FIP preview that works even before the worker is connected.\n\n**Update flow:** `Worker tab → set source → Save → Update Now` (or just wait for the hourly sync).\n\n---\n\n## 📦 Supported config types\n\n| Type | Security | Transport | Notes |\n|---|---|---|---|\n| VLESS Reality | `reality` | tcp \u002F xhttp | x25519 + ML‑DSA‑65 keys from the Xray binary |\n| VLESS WS TLS | `tls` | ws | auto panel domain for address\u002Fhost\u002Fsni |\n| VLESS XHTTP | `tls` | xhttp | packet‑up \u002F stream‑up \u002F stream‑one |\n| VMess \u002F Trojan \u002F Shadowsocks | tls | ws\u002Fgrpc\u002Ftcp | legacy protocols |\n| Custom‑IP WS TLS | `tls` | ws | address = scanned IP, host\u002Fsni = panel domain |\n\n**Sub page layout** (per user):\n\n```\n[Status config]      ← always first (shows days left + traffic %)\n[Main config #1]     ← one per selected inbound\n[Main config #2]\n─────────────────────\n[Custom IP (Railway) + 10 configs]\n[Custom #1] [Custom #2] …\n```\n\n---\n\n## 🖱 IP scanner\n\nRuns entirely from the **visitor's browser** using the fastest, simplest method:\n\n```js\nconst start = performance.now();\nawait fetch(\"https:\u002F\u002F1.2.3.4\u002F\", { mode: \"no-cors\", cache: \"no-store\" });\nconst ping = performance.now() - start;\n```\n\n- Pings 16 targets at a time with `Promise.all`, sorts by latency, live‑saves the best 10.\n- **Cloudflare** \u002F **Railway** tabs generate random candidate IPs from known ranges.\n- **TCP** tab resolves a domain to its IPs and reports connect latency.\n- Uses the user's own network & IP — no server bandwidth, works on phones and computers.\n- **Clearing** stops the scan, wipes the list, and the cleared state persists (stale in‑flight writes are dropped server‑side, so results never “come back”).\n\nSaved scanned IPs are consumed when you assign **Custom IP (scanner)** to a user → up to 10 extra WS‑TLS configs in their sub.\n\n---\n\n## 🔌 API reference (main endpoints)\n\nAll `\u002Fapi\u002F*` endpoints (except the public sub\u002Fconfig ones) require the auth cookie.\n\n### Auth\n| Method | Path | Body |\n|---|---|---|\n| POST | `\u002Fapi\u002Flogin` | `{ password }` |\n| POST | `\u002Fapi\u002Flogout` | — |\n| POST | `\u002Fapi\u002Fchange-password` | `{ current_password, new_password }` |\n\n### Users & subscriptions\n| Method | Path | Notes |\n|---|---|---|\n| GET\u002FPOST | `\u002Fapi\u002Fusers` | list \u002F create (`proxy_ip_enabled`, `custom_ip_type`, `proxy_country`, …) |\n| GET\u002FPATCH\u002FDELETE | `\u002Fapi\u002Fusers\u002F{id}` | read \u002F update \u002F delete |\n| GET | `\u002Fapi\u002Fusers\u002F{id}\u002Fconfig` | generated VLESS config |\n| GET | `\u002Fapi\u002Fusers\u002F{id}\u002Fqr` | QR code |\n| GET | `\u002Fapi\u002Fsub\u002F{username}` | **public sub data** — configs + `custom_configs` (split for the sub page) |\n| GET | `\u002Fsub\u002F{identifier}` | user subscription page \u002F raw link |\n\n### Inbounds\n| Method | Path | Notes |\n|---|---|---|\n| GET\u002FPOST | `\u002Fapi\u002Finbounds` | list \u002F create (Reality keys auto‑generated via the Xray binary) |\n| PATCH\u002FDELETE | `\u002Fapi\u002Finbounds\u002F{id}` | update \u002F delete |\n| POST | `\u002Fapi\u002Finbounds\u002F{id}\u002Fgenerate-reality-keys` | fresh pbk\u002Fsid\u002Fspx |\n| POST | `\u002Fapi\u002Finbounds\u002F{id}\u002Fgenerate-short-id` | new short id |\n\n### IP scanner\n| Method | Path | Notes |\n|---|---|---|\n| GET | `\u002Fapi\u002Fscanner\u002Fips\u002F{ctype}` | `cf` or `railway` → saved list + `seq` |\n| POST | `\u002Fapi\u002Fscanner\u002Fsave` | write list; pass current `seq` — stale writes rejected |\n| GET | `\u002Fapi\u002Fscanner\u002Fresolve?host=` | DNS resolve for TCP tab |\n| POST | `\u002Fapi\u002Fscanner\u002Fping-batch` | server‑side TCP latency probe (fallback) |\n\n### Cloudflare Worker\n| Method | Path | Notes |\n|---|---|---|\n| GET | `\u002Fapi\u002Fworker` | status + proxy map (no token) |\n| POST | `\u002Fapi\u002Fworker\u002Fsetup` | verify token, deploy worker, save connection |\n| POST | `\u002Fapi\u002Fworker\u002Fsync` | re‑deploy after proxy changes |\n| POST | `\u002Fapi\u002Fworker\u002Fsync-source` | fetch daily source now, update pool + deploy |\n| POST | `\u002Fapi\u002Fworker\u002Fsettings` | set `source_url` \u002F `auto_sync` |\n| DELETE | `\u002Fapi\u002Fworker` | remove connection |\n| POST | `\u002Fapi\u002Fworker\u002Fproxies` | add\u002Fupdate a country → proxy |\n| DELETE | `\u002Fapi\u002Fworker\u002Fproxies\u002F{code}` | remove a country |\n| GET | `\u002Fapi\u002Fworker\u002Flocations` | location status for the map tab |\n\n### Groups \u002F IP pool \u002F tools\n| Method | Path | Notes |\n|---|---|---|\n| GET\u002FPOST | `\u002Fapi\u002Fgroups` | group management |\n| POST | `\u002Fapi\u002Fips\u002Fassign` | assign IPs to a user |\n| GET | `\u002Fapi\u002Ftools\u002Freality-settings` | Reality presets |\n| POST | `\u002Fapi\u002Ftools\u002Fconfig-generator` | ad‑hoc config builder |\n| GET | `\u002Fapi\u002Fserver\u002Fstats` | live CPU\u002FRAM\u002Fdisk\u002Fnet |\n\n---\n\n## 🗂 Project layout\n\n```\nmain.py            FastAPI app — users, inbounds, config generator, scanner, worker manager, relay\npages.py           public page HTML helpers\nrelay_vless.py     VLESS\u002FWS\u002FXHTTP relay logic\nxhttp_siz10.py     XHTTP streaming helpers\nfetch_proxies.py   legacy proxy‑list fetcher (no longer used by the UI)\nstatic\u002F\n  index.html       dashboard SPA (sidebar: Dashboard \u002F Users \u002F Inbounds \u002F IP Scanner \u002F Worker \u002F Settings)\n  sub.html         per‑user subscription page\n  login.html       login page\nworker\u002F_worker.js   Cloudflare Worker template (deployed by the panel, not under \u002Fstatic)\nxray\u002F              Xray binary + generated config (installed at runtime)\ndata\u002F              spider_state.json, scanned\u002F (gitignored)\n```\n\n---\n\n## 🔒 Security notes\n\n- Never share the dashboard URL with users; change the default password right away.\n- The Cloudflare API token is kept server‑side and stripped from every API response.\n- Use a strong `SECRET_KEY`; it protects sessions and password hashing.\n- Reality private keys are generated by the Xray binary and stored in state; keep `data\u002F` private.\n\n---\n\n## 🧑‍💻 Development\n\n```bash\npip install -r requirements.txt\npython main.py            # http:\u002F\u002Flocalhost:8080  (login: admin \u002F admin)\n```\n\nSet `RAILWAY_PUBLIC_DOMAIN` or an in‑panel domain to see real domains in WS‑TLS configs locally.\n\n---\n\n## 📄 License\n\nMIT — use it, fork it, build on it. For a production deployment you are responsible for your own infrastructure, users and applicable laws.\n","SpiderPanel 是一个基于 FastAPI 的代理服务管理面板，专为 VLESS（含 Reality）、XHTTP 和 WebSocket-TLS 协议设计，支持订阅生成、多入站配置、浏览器端 IP 扫描及 Cloudflare Worker 多地域代理路由。核心特点包括：由 Xray 原生生成后量子密钥（x25519 + ML-DSA-65），自动绑定真实域名（免手动配置 host\u002FSNI），支持单用户多入站、自定义扫描 IP 配置、无服务器侧带宽消耗的客户端 IP 探测，以及通过 Cloudflare Worker 实现地理感知代理分流。适用于个人或小团队部署抗审查代理服务，尤其适合需兼顾安全性、地域灵活性与低运维成本的网络访问场景。",2,"2026-08-22 02:30:03","CREATED_QUERY"]