warp-masque-actions: 57 MASQUE entries, one Cloudflare account, one exit IP
GitHub Actions 自动生成 Cloudflare WARP (MASQUE) 密钥与 mihomo 配置,产物只存 artifact
At a glance
- What is it?
- A GitHub Actions repository that registers Cloudflare WARP accounts and writes mihomo configurations into a downloadable artifact. The node count is a failover story, not a country list, and the whole thing only imports into a client running mihomo's Alpha core.
- Who is it for?
- warp-masque-actions fits someone who wants a Cloudflare WARP MASQUE configuration without installing anything locally, is willing to run a client on an Alpha core, and treats the artifact as a throwaway credential rather than a long-lived key. It does not fit anyone who needs a chosen exit country, since that requires WARP+ or ZeroTrust, and it does not fit a client that is not mihomo based.
- Can I use it commercially?
- Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
- Is it still maintained?
- Yes. The repository last received commits 26 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 3, 2026, and from our analysis. They are not legal advice.
Editorial analysis
57 nodes are one account with 57 doorways
The number is the first thing the README puts in front of you, and it means less than it looks. All 57 nodes are different access addresses for the same WARP account, and the exit IP is identical for every one of them. Multiple nodes exist so that when a single access address stops working, the client can switch to another automatically. It is redundancy, not geography.
Country selection is explicitly out of scope. A free WARP account lands wherever Cloudflare anycast puts you, nearest first, and picking a specific country needs WARP+ or ZeroTrust, neither of which this repository handles.
Inside the 57, 28 are IPv6 entries. On a network without IPv6 they will fail to connect, and the client skips them on its own, so they cost nothing but a line in the file.
That design also explains the latency question the FAQ answers. Different access addresses sit at different distances from you, so ping times vary, but every one of them terminates at the same Cloudflare machine, so throughput tests come out close together. The advice given is to pick the lowest latency entry rather than speed-test all 57, which is the right call when the destination is fixed.
Nothing imports unless the client core is mihomo Alpha
The whole repository rests on one prerequisite, and getting it wrong is the most common failure. The masque proxy type exists only in mihomo's Alpha branch. Import the config into a stable core and it refuses outright:
订阅配置校验失败,请检查订阅配置文件,变更已撤销
level=error msg="proxy 0: unsupport proxy type: masque"Switching the core is a separate action from updating the client, which is the trap. In Clash Verge Rev it is Settings, then Clash 内核, choose Alpha, and the core restarts by itself after downloading. Updating Verge to the newest version does not turn the core into Alpha; you have to switch on that page. On Android, ClashMetaForAndroid works only from the Prerelease-alpha tag. ClashMi ships the mihomo core built in and takes the yaml directly, on iOS and on the other platforms too. FlClash switches core versions in its settings, and the headless path is a mihomo Alpha binary started with mihomo -d and your config directory.
Shadowrocket takes a different route: it does not read yaml, so the artifact ships warp-masque-shadowrocket.txt with one masque:// link per line for you to paste in.
Three clients are named as unusable because they are not mihomo based and do not know masque: Surge, Quantumult X and Karing.
Artifacts live seven days and the private key travels with them
The output of a run is an artifact called warp-masque-config holding three files: warp-masque.yaml for mihomo clients, warp-masque-shadowrocket.txt with the masque:// links, and usque-config.json with the raw keys. Artifacts are kept seven days by default, and the retention period can be raised from the Run workflow dialog before you start.
The security note is short and unambiguous. The private-key field in the generated configuration is equivalent to a password, so it should not be shared. On a public fork, artifacts are downloadable by anyone, which is the project's own argument for making your fork private if that matters to you.
Credentials are disposable by design. Re-running the workflow registers a brand new account each time, so an expired artifact is solved by running it again rather than by renewing anything.
What you should not do is schedule it. The README states plainly that turning the workflow into a frequent scheduled task gets the account risk-controlled and banned by WARP, and the failure shows up as:
Failed to connect tunnel: login failed!That message means the account was flagged, and the documented response is the same as an expired artifact: run it once more for a new account.
A fresh fork starts with Actions disabled and a Node 20 warning
The setup path is five steps, and two of them are traps. Forks arrive with GitHub Actions turned off, so the Actions page shows a notice you have to accept before any workflow can run. Then you pick the 生成 WARP MASQUE 配置 workflow, click Run workflow twice through the confirmation, and wait about a minute for the artifact to appear at the bottom of the run page.
The second trap is a yellow warning on the Actions page reading that Node.js 20 is deprecated and that some actions target it. The README calls this harmless: the configuration is generated regardless, and the repository has already moved to the node24 versions of its actions. Re-forking or syncing with upstream clears it. Forks made earlier can fix it by hand with two lines in .github/workflows/warp-masque.yml:
uses: actions/checkout@v6
uses: actions/upload-artifact@v6Two more facts about the repository itself. There are no GitHub releases, so nothing to install and no version to pin, and the last commit on main is dated 2026-09-07. The root holds .github/, configs/, scripts/ and worker/, and no LICENSE file appears there, while the license field carries no recognised identifier. Nothing in the repository states reuse terms, which matters if you intend to fork it into something of your own.
Three constants at the top of the script decide the node pool
Both pipelines are generated by Python scripts rather than by the workflow itself, and both keep their configuration in three names at the top of the file. For the plain WARP pipeline that is scripts/gen_masque.py:
V4 = [...] # IPv4 接入地址
V6 = [...] # IPv6 接入地址
PORTS = (...) # 端口V4 and V6 are the access address lists and PORTS is the port tuple, so changing where traffic lands is a matter of editing three Python literals rather than a YAML file. Routing rules come from ACL4SSR and are controlled through the RULESETS list, which means the routing policy is inherited rather than written here.
The nested pipeline has its own generator at scripts/gen_opera_masque.py, and it deliberately reuses the same V4, V6 and PORTS values so both pipelines point at one set of access points. Its extra knob is REGIONS, which selects which Opera landing regions get combined.
That split explains a detail in the nested pipeline's output: because the access points are shared, the direct WARP group is already present inside the nested configuration as the set of dialer-proxy targets. Exposing it as a selectable line is described in the repository as a side effect rather than an extra feature.
The nested pipeline multiplies 57 access points into about 400 nodes
The second workflow layers Opera's free browser VPN on top of WARP, purely to change the exit. Opera's offering is a standard HTTPS proxy from SurfEasy underneath, registers anonymously, has no traffic cap and needs no account.
The reason for nesting rather than using Opera alone is reachability, and the explanation is concrete. On its own, Opera connects you straight to an address in the 77.111.x.x range, and that range identifies itself. Behind MASQUE your machine only talks to Cloudflare addresses such as 162.159.198.x, with the Opera address sealed inside the QUIC tunnel. The repository reports a packet capture comparison in which the direct connection shows Opera servers and the nested one shows nothing.
The combination matrix is every MASQUE access point times every Opera landing. Landings usually number nine to eleven, and the resulting file holds roughly 400 nodes. The redundancy argument is stated plainly: if one access point is blocked, change port or range, and if one landing dies, the same region usually has another.
Node names encode the chain, so 欧洲[email protected] means the first European landing reached through 162.159.198.1 on port 443. Four hundred entries cannot be presented flat, so they are folded into three url-test groups for Asia, Europe and the Americas, each picking the fastest within its region, with lazy enabled so the client does not test all 400 on connect.
Opera credentials expire and the API will not say when
The nested pipeline has an expiry problem that cannot be scheduled around. Opera credentials from anonymous registration stop working, and the helper refreshes them every four hours by default, but the API does not return a real expiry time, so no accurate deadline can be given to a user. The stated remedy is to re-run the workflow and get new ones when a connection fails.
Geography is limited by the upstream service rather than by this repository. Opera offers Asia, Europe and the Americas with no country level option, and the measured landings are Singapore, Amsterdam and the US east coast. Anything more specific is not available upstream.
There is a second Alpha dependency here. The nested configuration uses dialer-proxy, which like masque exists only on the Alpha branch. Shadowrocket and Stash do not recognise dialer-proxy, so they cannot use the nested configuration at all, though they can still use the plain WARP one.
Output goes to two places: the pipeline commits configs/opera-masque.yaml back into the repository, and the same file is in the run's artifacts. Unchecking commit before starting keeps the generated file out of your history, which matters because a committed config contains the credentials.
The Worker trades a cron for a cache check at request time
The worker/ directory is the automated sibling of the Actions pipeline, deployed to Cloudflare with a status page and updating itself every four hours. It serves one aggregated subscription with four switchable line types: the regional nested lines, a WARP direct line that is faster but lands on Cloudflare's own IP, Proton lines grouped by country once Proton is configured, and Windscribe lines across 13 regions where Asia offers only Hong Kong. If a nested line times out or a landing dies, the direct line takes over, since both share the same access points.
The scheduling design is the interesting part. Opera credentials last four hours, so the Worker checks expiry when the subscription is actually fetched: still valid means serving the cache, expired means registering again. Nobody using it means nothing happens, and no cron is configured. WARP registration data is kept in KV and reused rather than re-registering a device on every request.
Deployment needs one KV binding and no environment variables, because the admin password and the subscription path are set in the interface on first visit. The dashboard route pastes the whole of worker/dist/worker.js over the Hello World Worker; the command line route is:
cd worker
npm install
npx wrangler login
npx wrangler kv namespace create KV
npx wrangler deployThe binding variable must be named exactly KV in uppercase, an unbound Worker explains how to bind rather than throwing a stack trace, and the first subscription request can take ten seconds while it registers WARP and Opera on the fly. Access control is deliberate: PBKDF2 hash with a random salt instead of a plaintext password, HMAC signed session tokens, constant time comparison, a lockout of 15 minutes after 8 failures from one address, and a plain 404 for a wrong path or bad token instead of a message that confirms which part was wrong. Changing the password once invalidates every subscription link, because tokens are signed with the password hash.
Editorial conclusion
warp-masque-actions fits someone who wants a Cloudflare WARP MASQUE configuration without installing anything locally, is willing to run a client on an Alpha core, and treats the artifact as a throwaway credential rather than a long-lived key. It does not fit anyone who needs a chosen exit country, since that requires WARP+ or ZeroTrust, and it does not fit a client that is not mihomo based. Verify four things first. Confirm your core can be switched to mihomo Alpha, because masque exists only on that branch and updating the client application does not change its core. Decide about artifact visibility before you run it: artifacts are kept seven days by default and anyone can download from a public fork, and the config contains a private key that behaves like a password. Read the failure message before you automate anything, since a login failed error means Cloudflare risk-controlled the account and the documented advice is to re-run rather than retry. And check the licensing, because no LICENSE file appears at the repository root and the license metadata carries no recognised identifier, so reuse terms are unstated. The last commit on main is dated 2026-09-07 and there are no GitHub releases.
Frequently asked questions
What does warp-masque-actions put in the artifact?
Three files inside an artifact named warp-masque-config: warp-masque.yaml as a mihomo configuration with 57 nodes, warp-masque-shadowrocket.txt holding one masque:// link per line for Shadowrocket, and usque-config.json with the raw keys. The workflow takes about a minute and needs nothing installed locally.
Why does a warp-masque-actions config fail with unsupport proxy type?
The masque proxy type exists only in mihomo's Alpha branch, so the client core has to be switched to Alpha. In Clash Verge Rev that is Settings, then Clash 内核, choose Alpha and let it restart; updating the application itself does not change the core. Surge, Quantumult X and Karing do not work at all because they are not mihomo based.
Can warp-masque-actions give me a different exit country?
No. All 57 nodes are access addresses for one WARP account and share the same exit IP, and a free account lands wherever Cloudflare anycast puts it. 28 of the entries are IPv6 and are skipped automatically without IPv6. Choosing a country requires WARP+ or ZeroTrust.
Is it safe to run warp-masque-actions on a schedule?
The README advises against high frequency scheduled runs because WARP risk-controls and bans the account, and a blocked account shows as Failed to connect tunnel: login failed!. Each run registers a fresh account, artifacts are kept seven days by default, and anyone can download them from a public fork, which is the argument for making your fork private.
How do I deploy the warp-masque-actions Worker?
Paste the whole of worker/dist/worker.js over the Hello World Worker in the Cloudflare dashboard, or run npm install, npx wrangler login, npx wrangler kv namespace create KV and npx wrangler deploy from the worker directory. Bind a KV namespace with the variable name exactly KV, then set an admin password on your first visit to the workers.dev URL.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/byjoey-warp-masque-actions)