{"id":50714611,"url":"https://github.com/roman-png/vpnpool","last_synced_at":"2026-06-09T18:00:41.425Z","repository":{"id":363286542,"uuid":"1261027874","full_name":"roman-png/VPNpool","owner":"roman-png","description":"OpenWrt app: auto-updating VLESS/Reality subscription with automatic ping \u0026 failover (sing-box) — like v2RayTun/Happ for your router. Selective \u0026 per-client routing, community SRS lists, LuCI dashboard (RU/EN).","archived":false,"fork":false,"pushed_at":"2026-06-08T09:22:52.000Z","size":434,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-08T09:24:34.637Z","etag":null,"topics":["anti-censorship","failover","luci","luci-app","openwrt","opkg","podkop","proxy","reality","router","shadowsocks","sing-box","subscription","tproxy","trojan","vless","vless-reality","vmess","vpn","xray"],"latest_commit_sha":null,"homepage":"https://github.com/roman-png/VPNpool","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/roman-png.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-06T06:31:57.000Z","updated_at":"2026-06-08T09:22:56.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/roman-png/VPNpool","commit_stats":null,"previous_names":["roman-png/vpnpool"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/roman-png/VPNpool","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/roman-png%2FVPNpool","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/roman-png%2FVPNpool/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/roman-png%2FVPNpool/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/roman-png%2FVPNpool/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/roman-png","download_url":"https://codeload.github.com/roman-png/VPNpool/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/roman-png%2FVPNpool/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34118757,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-09T02:00:06.510Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["anti-censorship","failover","luci","luci-app","openwrt","opkg","podkop","proxy","reality","router","shadowsocks","sing-box","subscription","tproxy","trojan","vless","vless-reality","vmess","vpn","xray"],"created_at":"2026-06-09T18:00:31.211Z","updated_at":"2026-06-09T18:00:41.417Z","avatar_url":"https://github.com/roman-png.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# VPN Pool (vpnpool) — VLESS subscription manager with auto‑failover for OpenWrt\n\n\u003cp align=\"right\"\u003e\u003cb\u003eEnglish\u003c/b\u003e · \u003ca href=\"README.ru.md\"\u003eРусский 🇷🇺\u003c/a\u003e\u003c/p\u003e\n\n\u003e **OpenWrt app that turns an auto‑updating VLESS/Reality subscription into an\n\u003e always‑working VPN** — like **v2RayTun / Happ, but on your router**. It pings\n\u003e all nodes, **automatically switches to a working VLESS server** when the current\n\u003e one dies, and routes your LAN (whole‑network or per‑device, selected sites or\n\u003e everything) through **sing‑box**. Manage everything from a clean LuCI dashboard.\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/roman-png/VPNpool/actions/workflows/build.yml\"\u003e\u003cimg alt=\"Build .ipk\" src=\"https://github.com/roman-png/VPNpool/actions/workflows/build.yml/badge.svg\"\u003e\u003c/a\u003e\n  \u003cimg alt=\"License: GPL-3.0\" src=\"https://img.shields.io/badge/License-GPL--3.0-blue.svg\"\u003e\n  \u003cimg alt=\"OpenWrt\" src=\"https://img.shields.io/badge/OpenWrt-23.05%20%7C%2024.10-blue\"\u003e\n  \u003cimg alt=\"Engine\" src=\"https://img.shields.io/badge/engine-sing--box-success\"\u003e\n\u003c/p\u003e\n\n**Keywords:** OpenWrt VLESS, VLESS Reality OpenWrt, sing-box subscription, sing-box\nfailover, auto switch VPN router, v2RayTun for router, Happ for router, podkop\nalternative, passwall alternative, vless vmess trojan shadowsocks subscription,\nxtls-rprx-vision reality, urltest auto failover, обход блокировок роутер OpenWrt,\nавтопереключение VLESS, подписка VLESS на роутер, антизапрет sing-box.\n\n---\n\n## What it does\n\n- 📡 **Auto‑updating subscription** — paste a subscription URL (base64 list **or**\n  sing‑box JSON). Multiple sources supported (e.g. auto‑updating raw config files\n  from a repo). **Multi‑client User‑Agent probing**: tries several client UAs and\n  keeps the response with the most nodes, so it keeps working if the provider\n  changes format.\n- 🔀 **Automatic ping + failover** — sing‑box `urltest` health‑checks every node and\n  **switches to a working VLESS server automatically** when the active one stops\n  responding. Manual override and manual \"ping all\" too.\n- ⭐ **Preferred node with switch‑back** — pin a favourite node: it's used while it's\n  reachable, control is handed to auto if it dies, and it **switches back** when it\n  recovers (anti‑flap hysteresis on top of urltest tolerance).\n- 📊 **Subscription data quota** — parses the panel's `subscription‑userinfo` header\n  and shows **used / total GB** with a progress bar (plus a Telegram alert when\n  \u003c10% remains), alongside the expiry date.\n- 💾 **Saved nodes** — promote any subscription node into a **separate persistent\n  store** (⭐) so it stays usable **after the subscription expires**. Optional\n  **auto‑snapshot** keeps a bounded fallback set of currently‑reachable nodes\n  saved automatically (manual ⭐ picks are never evicted).\n- 🔎 **Search / filter / sort nodes** — find a node by name/server, show only\n  reachable ones, sort by ping/name/traffic — handy with hundreds of nodes.\n- ⚡ **Per‑node real speed test** — on‑demand throughput (Mbit/s), not just ping.\n- 📈 **Live per‑node \u0026 per‑client traffic** — see how much goes through each node\n  and **each LAN device** (with DHCP hostnames).\n- ⏰ **Scheduler** — turn the VPN on/off and refresh the subscription on a daily\n  timetable (cron), e.g. off overnight, refresh every morning.\n- 🔗 **Share / export nodes** — per‑node **share link + offline QR** (move a node to\n  your phone), and **export** saved/manual/all nodes as a base64 subscription. QR is\n  generated **client‑side** so node secrets never leave the router.\n- 🧩 **Multiple subscriptions** — add extra full subscriptions that are bulk‑merged\n  into the pool alongside the main one.\n- 🤖 **Two‑way Telegram bot** — `/status /nodes /switch /speedtest /quota /saved\n  /clients /on /off /refresh`, locked to your chat id, tunnelled through the VPN.\n- 🧠 **Adaptive routing** — auto‑detects domains that are **blocked for a direct\n  connection** (RST/timeout) and routes just those through the VPN, so the proxy\n  list maintains itself for *your* ISP. Plus a one‑click “this site is blocked”.\n- 🎬 **Per‑node unlock test** — check what each node opens (YouTube / ChatGPT /\n  Netflix / Instagram / Telegram / Google) and see badges right in the dashboard.\n- 🛡️ **Anti‑DPI** — one toggle to fragment the TLS ClientHello (sing‑box\n  `tls_fragment`) and defeat SNI‑based DPI.\n- 🎛️ **Configurable auto‑pool** — on the Dashboard, click **⚙ Configure** next to the\n  AUTO row to pick **exactly which nodes take part in automatic switching**.\n  Unchecked nodes stay available for manual selection but are never auto‑picked.\n- 🧭 **Selective routing** — proxy **only chosen lists/domains** (rest direct) **or\n  everything except them** (full‑VPN with exceptions). Community domain lists from\n  [itdoginfo/allow‑domains](https://github.com/itdoginfo/allow-domains) as auto‑updating\n  **sing‑box SRS rule‑sets** (Telegram, Russia‑inside, YouTube, Meta, Twitter/X,\n  Discord, …) plus your own domains.\n- 👥 **Per‑client routing** — route the whole LAN, **exclude** specific devices\n  (they bypass the VPN), or allow **only** specific devices.\n- 🧩 **Protocols** — VLESS (Reality + `xtls‑rprx‑vision`), VMess, Trojan, Shadowsocks,\n  plus sing‑box JSON configs.\n- 🛡️ **Leak protection** — **IPv6 leak guard** (fail‑closed), opt‑in **kill‑switch**\n  (fail‑closed IPv4 in full‑tunnel mode, so nothing leaks if the VPN drops) and\n  opt‑in **DNS‑leak guard** (routes LAN DNS through the tunnel). **Clash API bound\n  to loopback** (not exposed on the LAN).\n- 🤝 **Coexists** with [podkop](https://github.com/itdoginfo/podkop) and zapret\n  (auto‑detected, non‑colliding marks/tables/ports) — or runs **standalone**.\n- 🔔 **Telegram alerts + two‑way control bot** — alerts on failover, subscription\n  expiry/quota and start/stop; an optional bot accepts **/status, /nodes, /switch,\n  /on, /off, /refresh** (locked to your chat id). Telegram traffic is **tunnelled\n  through the VPN**, so the bot works even where `api.telegram.org` is blocked.\n- 🖥️ **LuCI dashboard** (5 tabs, auto **RU/EN**): live node pings, traffic \u0026 connection\n  stats, on/off, manual select, sources, routing, settings, diagnostics (incl. a real\n  **\"test exit via VPN\"** check), backup/restore.\n\n---\n\n## 📸 Screenshots\n\n| Dashboard | Sources |\n|---|---|\n| ![Dashboard](docs/screenshots/dashboard.jpg) | ![Sources](docs/screenshots/sources.jpg) |\n| **Routing** | **Settings** |\n| ![Routing](docs/screenshots/routing.jpg) | ![Settings](docs/screenshots/settings.jpg) |\n\n---\n\n## 🧰 Supported \u0026 recommended hardware\n\nvpnpool itself is tiny and **architecture‑independent**. The real requirement is\n**sing‑box**, which is a ~38 MB binary.\n\n- **Minimum:** any router on **OpenWrt 23.05 / 24.10** with **≥ 128 MB RAM**. For\n  storage you need room for sing‑box (~38 MB). Routers with **16 MB flash** can still\n  run it — see [Routers with small flash (16 MB)](#-routers-with-small-flash-16-mb)\n  to install sing‑box into RAM.\n- **Recommended:** **≥ 256 MB flash** (or USB/extroot) and **≥ 512 MB RAM**, e.g.:\n  - **Cudy TR3000**, **GL.iNet** Flint/Beryl, any **MediaTek Filogic** (MT7981/MT7986),\n  - **Qualcomm IPQ807x** boards,\n  - **x86 / x86_64** mini‑PC or VM,\n  - **Raspberry Pi 4** running OpenWrt.\n\n\u003e **Architecture note:** our two packages ship as `_all` (one file works on **every**\n\u003e CPU). Architecture only matters for the *dependencies* (sing‑box, kmods), which\n\u003e opkg pulls from the standard OpenWrt feeds for **your** device automatically.\n\u003e Check your arch with `opkg print-architecture` if you ever need it.\n\n### 💾 Footprint\n\n| Component | Installed size |\n|---|---|\n| `vpnpool` + `luci-app-vpnpool` (our code) | **~128 KB** |\n| `sing-box` (the engine) | **~38 MB** (ipk ~14 MB) |\n| `jq` / `curl` / `ucode` / kmods | a few hundred KB |\n| **Total with all dependencies** | **~40 MB** |\n\n---\n\n## 🚀 Install\n\n### Option A — one line (recommended)\n\nInstalls (or upgrades) the latest release. Downloads the prebuilt packages from\nGitHub Releases and pulls dependencies from the standard OpenWrt feeds. Your\n`/etc/config/vpnpool` (subscription, Telegram, routing) is preserved on upgrade.\n\n```sh\nsh \u003c(wget -O - https://raw.githubusercontent.com/roman-png/VPNpool/main/install.sh)\n```\n\nIf your BusyBox `wget` doesn't support `\u003c(...)`:\n\n```sh\nwget -O /tmp/vpnpool-install.sh https://raw.githubusercontent.com/roman-png/VPNpool/main/install.sh\nsh /tmp/vpnpool-install.sh\n```\n\n### Option B — prebuilt `.ipk` from Releases\n\nOur packages are arch‑independent `_all` files — **download the same two files for\nany router**:\n\n1. Grab `vpnpool_*_all.ipk` and `luci-app-vpnpool_*_all.ipk` from the\n   [latest release](https://github.com/roman-png/VPNpool/releases/latest).\n2. Copy them to the router and install:\n\n```sh\nopkg update\nopkg install ./vpnpool_*_all.ipk ./luci-app-vpnpool_*_all.ipk\n```\n\n`sing-box`, `jq`, `curl`, `ucode` and the needed kernel modules are pulled in as\ndependencies. Then open **LuCI → Services → VPN Pool**.\n\n### Option C — opkg feed (update with `opkg update`)\n\nThe [GitHub Pages opkg feed](https://roman-png.github.io/VPNpool) is **signed**\nwith our usign key (fingerprint `807479500e0ce219`). Install the public key once\nso opkg can verify the feed, then add it and install/upgrade like any package —\n**signature checking stays on**:\n\n```sh\n# 1. install our public key (keeps opkg signature verification enabled)\nwget -O /etc/opkg/keys/807479500e0ce219 https://roman-png.github.io/VPNpool/vpnpool-feed.pub\n# 2. add the feed and install\necho \"src/gz vpnpool https://roman-png.github.io/VPNpool\" \u003e\u003e /etc/opkg/customfeeds.conf\nopkg update\nopkg install luci-app-vpnpool\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eFallback: install without the key (disables signature checking globally)\u003c/summary\u003e\n\nIf you don't install the key, opkg rejects the unsigned-to-it feed and drops the\npackage list. You can instead disable opkg's signature check — but note this turns\nverification **off for every feed, including the official OpenWrt ones**, so the\nkey method above is preferred.\n\n```sh\n# comment out the check_signature line (NOTE: setting it to 0 is NOT enough)\nsed -i '/^[[:space:]]*option[[:space:]]\\+check_signature/s/^/# /' /etc/opkg.conf\nopkg update\n# ...later, to re-enable verification:\nsed -i 's/^#[[:space:]]*\\(option[[:space:]]\\+check_signature\\)/\\1/' /etc/opkg.conf\n```\n\n\u003c/details\u003e\n\n### Option D — build from source (OpenWrt SDK)\n\n```sh\n# inside an OpenWrt SDK for your target\ngit clone https://github.com/roman-png/VPNpool package/vpnpool-src\n./scripts/feeds update -a \u0026\u0026 ./scripts/feeds install -a\nmake package/vpnpool/compile V=s\nmake package/luci-app-vpnpool/compile V=s\n# .ipk appear under bin/packages/\u003carch\u003e/...\n```\n\n---\n\n## 📟 Routers with small flash (16 MB)\n\nsing‑box (~38 MB) does not fit in 16 MB of flash, but our packages do (~128 KB).\nThe trick (same idea podkop uses): keep vpnpool in flash and **(re)install sing‑box\ninto RAM (`/tmp`) on every boot**, triggered when the WAN interface comes up.\n\nOpenWrt already defines a RAM install destination in `/etc/opkg.conf`\n(`dest ram /tmp`), so `opkg install -d ram …` lands the binary under `/tmp`.\n\n### One‑liner (16 MB flash)\n\nSame installer as above, with `VPNPOOL_RAM_SINGBOX=1`:\n\n```sh\nVPNPOOL_RAM_SINGBOX=1 sh \u003c(wget -O - https://raw.githubusercontent.com/roman-png/VPNpool/main/install.sh)\n```\n\n…or, if your `wget` lacks process substitution:\n\n```sh\nwget -O /tmp/vpnpool-install.sh https://raw.githubusercontent.com/roman-png/VPNpool/main/install.sh \u0026\u0026 VPNPOOL_RAM_SINGBOX=1 sh /tmp/vpnpool-install.sh\n```\n\nIt installs zram‑swap, the lightweight deps and our packages into flash\n(`--nodeps`, no sing‑box), writes the WAN‑up boot hook, and installs sing‑box into\nRAM right away. Then set your subscription in **LuCI → Services → VPN Pool** and run\n`/etc/init.d/vpnpool start`. On every reboot the hook reinstalls sing‑box into RAM\nand starts vpnpool automatically. If your WAN isn't named `wan`, edit `INTERFACE`\nin `/etc/hotplug.d/iface/99-vpnpool-singbox-ram`.\n\n\u003e **Updating on small flash:** re‑run the same one‑liner. Do **not** use `opkg upgrade`\n\u003e here — it resolves the `sing-box` dependency against flash and would try to pull the\n\u003e ~38 MB binary into ROM (the install deliberately uses `--nodeps` to avoid that).\n\n\u003cdetails\u003e\n\u003csummary\u003eManual steps (what the one‑liner does under the hood)\u003c/summary\u003e\n\n**1. Install zram‑swap** (gives the small router more usable memory for `opkg`):\n\n```sh\nopkg update\nopkg install zram-swap\n/etc/init.d/zram enable\n/etc/init.d/zram start\n```\n\n**2. Install vpnpool itself, but WITHOUT sing‑box** (it won't fit in flash). Install\nthe small dependencies normally, then our packages with `--nodeps`:\n\n```sh\nopkg update\nopkg install jq curl ucode ucode-mod-fs ucode-mod-uci kmod-nft-tproxy ip-full ca-bundle\n# get the two _all .ipk (e.g. via the release page or install.sh's download step), then:\nopkg install --nodeps ./vpnpool_*_all.ipk ./luci-app-vpnpool_*_all.ipk\n```\n\n**3. Do NOT autostart vpnpool at boot** — sing‑box won't exist yet. The hotplug hook\nbelow starts it after sing‑box is in place:\n\n```sh\n/etc/init.d/vpnpool disable\n```\n\n**4. Create the boot hook** that installs sing‑box into RAM and starts vpnpool when\nthe WAN comes up (runs on every reboot, needs internet):\n\n```sh\ncat \u003e /etc/hotplug.d/iface/99-vpnpool-singbox-ram \u003c\u003c'EOF'\n#!/bin/sh\n[ \"$ACTION\" = \"ifup\" -a \"$INTERFACE\" = \"wan\" ] \u0026\u0026 {\n    logger -t vpnpool \"WAN up: installing sing-box into RAM\"\n    opkg update\n    opkg install -d ram --force-reinstall --force-overwrite sing-box\n    ln -sf /tmp/usr/bin/sing-box /usr/bin/sing-box\n    /etc/init.d/vpnpool start\n    logger -t vpnpool \"sing-box installed in RAM, vpnpool started\"\n}\nEOF\nchmod +x /etc/hotplug.d/iface/99-vpnpool-singbox-ram\n```\n\n**5. Reboot (or replug WAN) and verify:**\n\n```sh\nlogread -e vpnpool        # should show \"sing-box installed in RAM, vpnpool started\"\nsing-box version          # confirms the RAM symlink resolves\n```\n\n\u003c/details\u003e\n\n\u003e **Trade‑offs:** sing‑box (~14 MB ipk) is re‑downloaded into RAM on every boot, so\n\u003e the router needs working internet at startup and enough free RAM (~128 MB+). If\n\u003e your WAN is named differently (e.g. `wan6`, `wwan`), adjust the `INTERFACE` check.\n\u003e\n\u003e **Tested on:** Xiaomi Mi Router 4A Gigabit (MediaTek MT7621, 16 MB flash / 128 MB\n\u003e RAM, OpenWrt 24.10) — fresh one‑liner install, reboot, and live VPN exit all OK.\n\u003e\n\u003e **Keep a single boot hook.** Only one WAN‑up hook may install sing‑box into RAM.\n\u003e Two hooks racing `opkg install -d ram sing-box` on a 128 MB router OOM each other\n\u003e and corrupt the binary (symptom: `sing-box: Bus error` / `Permission denied`). The\n\u003e one‑liner removes stale `*vpnpool*` iface hooks before writing its own, so just\n\u003e don't add a second one by hand.\n\n---\n\n## ⚙️ Quick start\n\n1. **Sources** tab → paste your subscription URL → **Update now**.\n2. **Routing** tab → pick mode (proxy selected / proxy all‑except) → choose community\n   lists and/or add domains.\n3. **Dashboard** → **Turn ON**. Watch live pings; the green ★ is the active node.\n   Use **⚙ Configure** on the AUTO row to choose which nodes auto‑switch.\n4. **Diagnostics** → **Test exit via VPN** to confirm your real exit IP/country.\n\nCLI equivalent:\n\n```sh\nuci set vpnpool.main.subscription_url='https://example.com/sub'\nuci set vpnpool.main.enabled='1'; uci commit vpnpool\n/etc/init.d/vpnpool enable; /etc/init.d/vpnpool restart\n```\n\n---\n\n## 🧠 How it works\n\n```\nLuCI (5 tabs) ── ubus/rpcd ── vpnpoold (ucode + shell, procd)\n                                  │ fetch (multi-UA) → parse → generate → sing-box check\n                                  ▼\n                          sing-box (the engine)\n   inbound: tproxy 127.0.0.1:1603  +  local mixed SOCKS/HTTP :1605 (test/apps)\n   outbound: urltest \"auto\" (ping + failover) + selector + nodes + direct\n   route: sniff SNI → community SRS / domains → proxy (or direct in exclude mode)\n                                  ▲\n   nftables (table inet vpnpool): mark LAN 80/443 → fwmark 0x400000 → table 142 →\n   tproxy; yields to podkop; IPv6 fail-closed; per-client include/exclude\n```\n\nThe control plane (subscription, parsing, config generation, watchdog, UI) is ours;\nthe data plane is **sing‑box**, exactly like v2RayTun/Happ wrap an engine.\n\n---\n\n## 🆚 Compared to podkop / passwall / homeproxy\n\n| | **vpnpool** | podkop | passwall2 | homeproxy |\n|---|---|---|---|---|\n| Engine | sing‑box | sing‑box | xray/sing‑box | sing‑box |\n| Auto‑updating subscription | ✅ multi‑source, multi‑UA | partial | ✅ | ✅ |\n| **Auto ping + failover** | ✅ urltest + watchdog | manual select | ✅ | ✅ |\n| **Preferred node + switch‑back** | ✅ | — | — | — |\n| **Pick which nodes auto‑switch** | ✅ | — | — | — |\n| **Subscription data quota** | ✅ used/total + bar | — | — | — |\n| **Saved nodes (survive expiry)** | ✅ | — | — | — |\n| **Per‑node speed test** | ✅ throughput | — | — | — |\n| **Per‑node \u0026 per‑client stats** | ✅ live | — | partial | partial |\n| **On/off + refresh scheduler** | ✅ | — | — | — |\n| **Share link + offline QR / export** | ✅ | — | — | — |\n| **Multiple full subscriptions** | ✅ | — | partial | ✅ |\n| **Two‑way Telegram control bot** | ✅ | — | — | — |\n| **Adaptive routing (auto‑detect blocks)** | ✅ | — | — | — |\n| **Per‑node unlock test (YT/AI/NF…)** | ✅ | — | — | — |\n| **Anti‑DPI TLS fragmentation** | ✅ toggle | — | — | — |\n| **Kill‑switch + DNS‑leak guard** | ✅ opt‑in | partial | ✅ | partial |\n| Community SRS lists | ✅ (itdoginfo) | ✅ | own | own |\n| Per‑client routing | ✅ | — | ✅ | partial |\n| VPN‑exit self‑test | ✅ | ✅ | partial | — |\n| Telegram alerts | ✅ | — | — | — |\n| **Two‑way Telegram control bot** | ✅ (tunnelled) | — | — | — |\n| Coexists with podkop | ✅ (by design) | n/a | — | — |\n| Auto RU/EN UI | ✅ | RU/EN | RU/EN | EN/ZH |\n\n---\n\n## 🔐 Notes\n\n- **DNS:** routing is done by **SNI sniffing**, so DNS games aren't required. On a\n  fresh OpenWrt this just works with the system resolver. If you previously ran\n  podkop and remove it, restore dnsmasq's normal upstream (podkop points it at its\n  own `127.0.0.42` fake‑IP resolver).\n- **GitHub reachability:** community SRS rule‑sets are downloaded from GitHub\n  releases; if blocked, route GitHub through the proxy first.\n- **Security:** the Clash API is bound to `127.0.0.1` only.\n\n## 🗺️ Roadmap\n\n- Near‑instant active‑probe failover (below the urltest interval)\n- Full sing‑box DNS/FakeIP with DoH‑over‑proxy for fully leak‑free selective routing\n  (current DNS guard covers LAN clients that query public resolvers directly)\n- Full IPv6 tproxy (proxy mode, not just block)\n- Clash YAML subscription parsing\n- Multi‑hop / chain proxy (entry in one country, exit in another)\n\n## 🤝 Contributing\n\nIssues and PRs welcome. The whole thing is ucode + shell + a little LuCI JS — no\ncompilation needed.\n\n## 📄 License\n\n[GPL‑3.0‑only](LICENSE) © 2026 roman‑png\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Froman-png%2Fvpnpool","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Froman-png%2Fvpnpool","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Froman-png%2Fvpnpool/lists"}