Open-source project
stevenjoezhang/luci-app-cloudflarespeedtest avatar
stevenjoezhang/luci-app-cloudflarespeedtest

luci-app-cloudflarespeedtest: scheduling Cloudflare IP selection on OpenWrt

A LuCI app for OpenWRT that schedules and runs CloudflareSpeedTest, automatically selecting and applying the fastest Cloudflare IPs to outbound proxy setups

44 stars9 forksShellGPL-3.0

At a glance

What is it?
A LuCI front end that wraps the CloudflareSpeedTest core, picks the fastest Cloudflare IPs on a schedule, and writes the result into SSR+, Passwall, MosDNS or astra-dns. The packaging is the interesting part, and the licence metadata is not.
Who is it for?
Adopt it if you already run OpenWrt with SSR+, Passwall, MosDNS or astra-dns and you are tired of pasting Cloudflare IPs by hand; the conffile at /etc/config/cloudflarespeedtest makes the whole configuration reproducible. Do not adopt it if you want a general throughput benchmark, or if your router has no space for a downloaded core binary.
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 14 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 September 28, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem: Cloudflare IPs go stale and nobody wants to re-pick them

Cloudflare anycast means the IP that is fastest from your line is not a fixed address. It changes with your ISP's routing, the time of day, and which Cloudflare edge your traffic happens to land on. Proxy plugins such as SSR+ and Passwall let you pin an outbound address, which is exactly what makes them fast, and exactly what makes them rot: the address you pasted in three months ago may now be a detour.

luci-app-cloudflarespeedtest exists to close that loop on the router itself. It is a LuCI application for OpenWrt and it is built on the CloudflareSpeedTest core tool, which measures latency and download speed against a pool of Cloudflare IPs. The app runs that measurement, keeps the winners, and pushes them into the proxy or DNS plugin you already use. The README lists SSR+, Passwall, MosDNS and astra-dns as targets.

The audience is narrow and specific: people running OpenWrt as their gateway, with a proxy stack already in place, who want the address selection to happen on a timer instead of in a browser tab. If you do not run one of those plugins, the app has nothing to write to.

How the test, the selection and the plugin write actually fit together

The repository is a packaging and UI layer, not a measurement engine. The top level holds htdocs/ for the LuCI views, root/ for the files that get installed onto the router, po/ for translations, and a Makefile plus build.sh. The measurement itself is delegated to the CloudflareSpeedTest core, which the package deliberately does not ship. According to the README, the core binary is downloaded automatically on the first run, which keeps the package small.

That decision shapes the runtime. On first use the router needs working DNS and outbound HTTP before the app can do anything useful, so a router that is offline, or whose only route out is the proxy the app is supposed to configure, is a chicken-and-egg case. The README does not document an offline install path for the core.

The output side is a write into a plugin's configuration. The app does not tunnel traffic itself and does not sit in the data path; it edits the configuration of something else and lets that something else reconnect. The README also mentions history charts for latency and download speed trends, which implies results are retained between runs rather than discarded after each selection.

One packaging detail is worth flagging because it is easy to misread. The Makefile declares a conffile:

makefile
define Package/$(PKG_NAME)/conffiles
/etc/config/cloudflarespeedtest
endef

That means /etc/config/cloudflarespeedtest survives a package upgrade. It also means a configuration written by an older version is not reset by installing a newer one, so a stale or malformed option persists until you remove the file yourself.

Installing luci-app-cloudflarespeedtest from a release and running the first test

The README gives a release-based install rather than a feed. Download the .ipk or .apk that matches your OpenWrt release from the Releases page, copy it to the router, and install it:

bash
opkg install luci-app-cloudflarespeedtest_*.ipk

After that, the README points to LuCI under Services, then CloudflareSpeedTest, for configuration. The package depends on curl, declared in the Makefile as `+!wget&&!curl:curl`, so on a system that has neither wget nor curl the dependency pulls curl in; on a system that already has wget, curl is not added.

The package is architecture-independent (`LUCI_PKGARCH:=all`), which is why one release file works across router models. What is not architecture-independent is the core binary downloaded on first run, and the README does not state which architectures that download covers.

If you build from source instead of installing a release, the README gives the OpenWrt buildroot commands. For the package alone:

bash
make package/luci-app-cloudflarespeedtest/compile V=99

For a full image, the README describes selecting the package under LuCI, then Applications, then compiling with `make V=99`. Building from source is the route to take if the downloaded core does not match your target.

Where this breaks: offline routers, disk pressure and the wrong kind of benchmark

The first-run core download is the sharpest edge. A router that has just booted with no working resolver cannot fetch the binary, and the app's own purpose, fixing the outbound path, is unavailable until the outbound path works. The README does not document a manual placement step for the core, so recovery means getting the router online by other means first.

Storage is the second constraint. The package is small by design precisely because the core is not inside it, but the core still has to live somewhere on the router, and OpenWrt devices routinely have very little free overlay space. The README does not give a size figure for the downloaded binary, so this is something to check on your own device rather than assume.

Third, and most often misunderstood: this is not a bandwidth benchmark for your internet connection. It measures candidate Cloudflare IPs against each other and picks a winner. If you want to know what your line actually delivers, you want a throughput test against a speedtest server, which is a different tool with a different measurement target. Running CloudflareSpeedTest results as a statement about your ISP plan will mislead you.

Finally, the write into SSR+, Passwall, MosDNS or astra-dns is an edit to another package's configuration. The README does not document rollback, so if a selected IP turns out to be worse in practice, undoing it means going into the target plugin and changing the value yourself.

Compared with running CloudflareSpeedTest by hand over SSH

The obvious alternative is not another LuCI app. It is the upstream CloudflareSpeedTest binary, run manually or from a cron entry, with the output pasted into your proxy configuration. That approach has real advantages: no LuCI dependency, no package upgrade path to think about, and full visibility into exactly what command produced the result. It also works on routers where LuCI is not installed at all.

The difference is what happens after the measurement. Running the core by hand gives you a list of IPs and stops there. luci-app-cloudflarespeedtest takes the same core and adds three things: a schedule, a mapping from result to plugin configuration, and a history view. The first two are the actual product. If you already have a cron job and a script that rewrites your Passwall config, you have rebuilt most of this app and you should probably keep your script, because you understand it and it is not going to be replaced by a package upgrade.

The other comparison worth making is against the project this one forks. The README states it is a fork of mingxiaoyu/luci-app-cloudflarespeedtest with significant refactoring and improvements, and lists the redesigned status display and log format as part of that. If you were using the original, the reason to switch is the UI and log work plus the auto core download, not a different measurement method, since both wrap the same core.

Maintenance, upgrade cost and what the licence files say

The last push to the repository was on 2026-07-09, the same day as the v1.20 release. v1.19 and v1.18 both landed on 2026-06-23. The repository is not archived. That is a recent cadence of tagged releases, and the version in the Makefile is 1.21.0 with PKG_RELEASE 0, which is ahead of the newest release listed, so the Makefile tracks unreleased work as well.

Upgrade cost is low in the normal case: install a newer .ipk or .apk over the old one. The conffile declaration for /etc/config/cloudflarespeedtest means your settings are preserved across that upgrade, which is convenient and also means you should read release notes rather than assume a new default has taken effect. The README does not describe a migration path for configuration keys that change between versions.

Licensing is where the metadata deserves a second look. The repository is listed as GPL-3.0 and ships a LICENSE file. The Makefile, however, declares `PKG_LICENSE:=AGPL-3.0`, and the file header carries the mingxiaoyu attribution with a GNU General Public License v3 notice. GPL-3.0 and AGPL-3.0 are not the same licence, and AGPL-3.0 adds a network-use condition. Since this is a LuCI app running on hardware you own, the practical difference is small for a home user, but if you redistribute a firmware image containing it, the discrepancy between the repository listing and the Makefile declaration is something to resolve before you rely on either. This is a description of what the files say, not legal advice.

The fork lineage also matters for attribution: the Makefile keeps the original author's name and email, so any redistribution should preserve that header.

Editorial conclusion

Adopt it if you already run OpenWrt with SSR+, Passwall, MosDNS or astra-dns and you are tired of pasting Cloudflare IPs by hand; the conffile at /etc/config/cloudflarespeedtest makes the whole configuration reproducible. Do not adopt it if you want a general throughput benchmark, or if your router has no space for a downloaded core binary. Before flashing anything, check the first-run core download against your router's free overlay space, and confirm the licence file in the repository matches the AGPL-3.0 declaration in the Makefile.

Frequently asked questions

Is CloudflareSpeedTest safe to run on my router?

The app measures latency and download speed against a pool of Cloudflare IPs and writes the winners into a proxy or DNS plugin's configuration. The README does not describe any telemetry or reporting beyond that, but it also does not document what the first-run core download fetches, so the binary's provenance is the thing to verify rather than the test itself.

How does the Cloudflare speed test in this LuCI app work?

It uses the CloudflareSpeedTest core tool to test the latency and download speed of Cloudflare IPs, selects the best ones for your network, and updates them to plugins such as SSR+, Passwall, MosDNS and astra-dns. It can run periodically or on demand.

Does using luci-app-cloudflarespeedtest make my internet faster?

It does not change your line speed. It picks the Cloudflare IP that measures fastest from your network and applies it to your proxy or DNS plugin, so the gain is in routing to a closer or less congested edge, not in raw bandwidth.

How can I test my Cloudflare connection with this app?

Install the package, open LuCI under Services, then CloudflareSpeedTest, and run the test manually or let the scheduled run do it. The app measures latency and download speed across Cloudflare IPs and applies the best result to your proxy or DNS plugin.

Official sources

  1. Official documentation
  2. Official README
  3. Project repository
  4. Release notes
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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/stevenjoezhang-luci-app-cloudflarespeedtest.svg)](https://hysenlabs.com/projects/stevenjoezhang-luci-app-cloudflarespeedtest)