luci-app-cloudflarespeedtest ships without the tester and downloads it on first run
A LuCI app for OpenWRT that schedules and runs CloudflareSpeedTest, automatically selecting and applying the fastest Cloudflare IPs to outbound proxy setups
At a glance
- What is it?
- This OpenWrt LuCI app measures Cloudflare IPs by latency and download speed, then writes the fastest ones into SSR+, Passwall and MosDNS. The upstream core binary is not in the package, and the bundled IPv4 list has six ranges removed after validation found them restricted.
- Who is it for?
- luci-app-cloudflarespeedtest fits a router running SSR+, Passwall or MosDNS where you would rather have the Cloudflare address chosen by measurement than by default, and it costs little to try since the package is small and installs from a release tarball. It does not fit building outside an OpenWrt buildroot, because the Makefile includes luci.mk and leaves the BuildPackage call commented out for feed builds.
- Can I use it commercially?
- Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository last received commits 15 days ago.
- What is it written in?
- Mainly Shell, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.
Star history
- stevenjoezhang/luci-app-cloudflarespeedtest49 ★ · +9
| Repository | 2026-08-23 | 2026-11-14 |
|---|---|---|
| stevenjoezhang/luci-app-cloudflarespeedtest | 40 | 49 |
9 Stars in the last 83 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
The core binary is downloaded on first run, not shipped in the package
The package contains no CloudflareSpeedTest binary. On its first run the app fetches the core itself, and the stated reason is package size: keeping a compiled tester out of the archive makes the download small enough to install over a slow router connection.
The trade is the first run. Something has to reach out to fetch the tester before any measurement can happen, so an air-gapped or firewalled router gets an install that looks complete and then fails at the point where you expected results. Everything after that is local.
What you install is a LuCI application, not a standalone program. The README points to LuCI, then Services, then CloudflareSpeedTest as the configuration surface, and the app is a fork of `mingxiaoyu/luci-app-cloudflarespeedtest` that the author describes as significantly refactored, sitting on top of the XIU2 CloudflareSpeedTest core.
Six IPv4 blocks never enter the test, because validation found them restricted
The candidate list is not simply Cloudflare's published address space. It starts from Cloudflare's public IPv4 ranges and removes six blocks that were found to be restricted or unsuitable during validation:
`108.162.192.0/18`, `162.158.0.0/16`, `162.159.0/18`, `172.64.228.0/24`, `172.68.0.0/14` and `198.41.192.0/19`.
That is a real behavioural difference from running the core tool with a raw range list, and it cuts both ways. Addresses that would otherwise win a latency race on paper are never tested, so a router whose best Cloudflare path sits in one of those blocks will not find it.
The rest of the app's job is measurement and delivery. It tests latency and download speed for the candidate addresses, on a schedule or on demand, keeps history charts for both metrics so you can see a trend rather than a single result, and pushes the chosen address into the proxy and DNS tools configured on the router.
opkg install, then LuCI, then Services, then CloudflareSpeedTest
Installation is a release download and a package install:
opkg install luci-app-cloudflarespeedtest_*.ipkThe README points at the repository's Releases page for the latest `.ipk` or `.apk`, and the `opkg` line above is for the ipk form. Configuration happens afterwards in the LuCI interface under Services, then CloudflareSpeedTest, where the schedule, the proxy targets and the status are managed.
Two details in the Makefile explain what the package expects from the router. `LUCI_PKGARCH:=all` marks it architecture independent, so the same package fits any target. `LUCI_DEPENDS:=+!wget&&!curl:curl` installs curl only when neither wget nor curl is already present, which is what the first-run core download relies on. A router with no downloader at all gets curl added; a router with wget already there gets nothing extra.
Settings persist in `/etc/config/cloudflarespeedtest`, the path registered as the package's conffiles so an upgrade keeps them.
The Makefile still credits the original author and tags the package AGPL-3.0
This is a fork, and the build file has not been rewritten from scratch. The header comment still carries the original author's name and email address, and the acknowledgements section credits both CloudflareSpeedTest and `mingxiaoyu/luci-app-cloudflarespeedtest`.
Licensing is where the fork shows a discrepancy worth knowing. The repository is labelled GPL-3.0, the Makefile header says the package is licensed to the public under the GNU General Public License version 3, and the package metadata line reads `PKG_LICENSE:=AGPL-3.0`. Two different identifiers for the same package means you should read the LICENSE file at the root rather than trust a badge, and the difference between GPL and AGPL matters if you redistribute a modified build.
Version numbers follow the OpenWrt convention, with `PKG_VERSION:=1.21.0` and `PKG_RELEASE:=0` in the Makefile matching release v1.21.0, published on 2026-09-10 after v1.20 on 2026-07-09 and v1.19 on 2026-06-23. The last push to the repository landed on 2026-09-16.
Building it means either a package target or a full image with menuconfig
The README gives two build routes, and the difference is whether you want a package or an image:
# Compile package only
make package/luci-app-cloudflarespeedtest/compile V=99
# Compile full image
make menuconfig
#choose LuCI ---> 3. Applications ---> <*> luci-app-cloudflarespeedtest..... for LuCI ----> save
make V=99The package target builds the ipk inside an existing OpenWrt SDK tree. The image route goes through `make menuconfig`, where the entry sits under LuCI, then Applications, and marking it with `<*>` includes it in the firmware build that `make V=99` then produces.
Both assume a buildroot rather than a standalone shell. The Makefile includes `$(TOPDIR)/rules.mk` and then `$(TOPDIR)/feeds/luci/luci.mk`, and the line that would call BuildPackage is present but commented out with the note that it is the OpenWrt buildroot signature, so the package is built through the LuCI feed mechanism. The repository also carries `build.sh`, a `po/` directory for translations, `renovate.json` for dependency updates and a `screenshots/` directory, even though the README's Screenshots section is empty.
Where this stops is DNS resolution and ad filtering
The author points at a boundary rather than claiming the whole problem. If what you want is to use the best Cloudflare addresses for DNS resolution as well as ad filtering, the recommendation is a different project: Astra DNS and its LuCI plugin `luci-app-astra-dns`.
That framing matches what the app does. Its integration list covers proxy and DNS tools, naming SSR+, Passwall, MosDNS and astra-dns among the targets it can update, and the advertised value is the same in both cases: an address chosen by measuring latency and download speed from your own line, re-applied automatically on a schedule, with charts that show how the choice moved over time.
The README also exists in Chinese as `README.CN.md`, and the project's homepage is a blog post rather than a documentation site, so the LuCI page itself is the authoritative description of what a given version exposes.
Editorial conclusion
luci-app-cloudflarespeedtest fits a router running SSR+, Passwall or MosDNS where you would rather have the Cloudflare address chosen by measurement than by default, and it costs little to try since the package is small and installs from a release tarball. It does not fit building outside an OpenWrt buildroot, because the Makefile includes luci.mk and leaves the BuildPackage call commented out for feed builds. Before scheduling a recurring test, read the six excluded IPv4 blocks and check whether any of them is the range your own ISP sends you to.
Frequently asked questions
What does luci-app-cloudflarespeedtest do on OpenWrt?
It tests Cloudflare IP latency and download speed on a schedule or on demand, selects the best addresses for your network, and writes them into proxy plugins such as SSR+, Passwall and MosDNS. Configuration lives in LuCI under Services, then CloudflareSpeedTest.
Why does luci-app-cloudflarespeedtest not ship the CloudflareSpeedTest binary?
The package deliberately leaves the core binary out and downloads it on the first run, which keeps the package small. That makes the first run the one step that needs working outbound network access.
Which Cloudflare IP ranges does luci-app-cloudflarespeedtest skip?
Six blocks are excluded from Cloudflare's public IPv4 list because validation found them restricted or unsuitable: 108.162.192.0/18, 162.158.0.0/16, 162.159.0/18, 172.64.228.0/24, 172.68.0.0/14 and 198.41.192.0/19.
How do I install luci-app-cloudflarespeedtest on a router?
Download the latest .ipk or .apk from the repository releases and run opkg install luci-app-cloudflarespeedtest_*.ipk on the router. Settings are kept in /etc/config/cloudflarespeedtest, registered as the package conffiles so upgrades preserve them.
What license is luci-app-cloudflarespeedtest under?
The sources disagree: the repository is labelled GPL-3.0 while the Makefile header refers to the GNU General Public License version 3 and the package metadata line reads PKG_LICENSE:=AGPL-3.0. Read the LICENSE file at the repository root before redistributing a modified build.
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/stevenjoezhang-luci-app-cloudflarespeedtest)Star history chart for your README
[](https://hysenlabs.com/projects/stevenjoezhang-luci-app-cloudflarespeedtest)Was this useful?