# WhiteDNS on Android: an API 26 native build, an Intel Mac default, and no app store

> A source-available Android DNS tunneling client that compiles two Go engines out of submodules and ships through a Telegram channel rather than a store. Its build defaults assume an Intel Mac, the native clients target API 26 while the app compiles against SDK 36, and one engine records its commit while the other records nothing.

**WhiteDNS/WhiteDNS-Android** — Source-available Android DNS tunneling client with VPN and proxy modes, backed by MasterDNS & StormDNS.

- Repository: https://github.com/WhiteDNS/WhiteDNS-Android
- Website: https://t.me/whitedns
- Stars: 1,338 · Forks: 92
- Language: Kotlin
- License: NOASSERTION
- Published: 2026-09-18 · Updated: 2026-09-18 · Language: en
- Canonical page: https://hysenlabs.com/projects/whitedns-whitedns-android

## The licence field says nothing while the tree carries four legal files

The package metadata records no recognised licence for this repository, which is a different state from naming one. What the tree actually holds is LICENSE.MD, plus TRADEMARK.MD, CLA.md, CONTRIBUTING.md and THIRD_PARTY_NOTICES.md, so the legal surface is broad even though the licence field is blank. The README states the terms in prose instead: WhiteDNS is described as source-available proprietary software, the code is published for transparency, review and contribution to the official project only, and this project is not open-source. The text of LICENSE.MD is not reproduced anywhere on the front page, so the exact grant cannot be confirmed from what the README shows, and the two should be read together rather than assumed to match.

## You may contribute to WhiteDNS and you may not fork it

The stated position is that community contributions are welcome through the official repository while the project is not open-source, and the same paragraph immediately bars forking it into another app, redistributing builds, repackaging APKs, selling modified versions, cloning the project, or reusing the WhiteDNS name, logo, icon, design or branding. Read together with the separate notice at the top, the permission set is narrow in an unusual way: you can read the code and send patches back, and you cannot take the result anywhere else. That is why CLA.md and TRADEMARK.MD sit in the tree at all, and why the build section repeats the same limits for anyone compiling locally. Contributions without a fork right is an arrangement that has to be read as a contract, not as an oversight.

## Two defaults in the Makefile assume an Intel Mac

The first default is the SDK location, where SDK_ROOT falls back to the ANDROID_HOME environment variable and, failing that, to the macOS path under the user's Library folder. On Linux that fallback points nowhere useful, so ANDROID_HOME has to be set. The second default is the native toolchain host, written as darwin-x86_64, which is the Intel Mac layout of the NDK's LLVM prebuilt tree. An Apple Silicon machine has the same directory under a different host triple, so the path does not exist there and the build stops. The Makefile offers the escape hatches, since NDK_ROOT, NDK_HOST, NDK_VERSION, ANDROID_API and GO are all overridable, and it will also take an explicit Go path when the toolchain sits outside PATH:

```bash
git submodule update --init --recursive
./gradlew testDebugUnitTest
make debug
```

```bash
make debug GO=/path/to/go
```

## The app targets SDK 36 while the Go engines compile against API 26

The build requirements ask for two different NDK versions at once. One is needed for the Android side of the app, and a second, newer one is needed specifically to rebuild the StormDNS and CottenDns native clients, which are Go programs compiled through CGO with the NDK's clang cross compiler. Alongside that, the app compiles against compileSdk 36 while the Makefile pins ANDROID_API to 26 for the native toolchain invocation, a ten level gap between the SDK the Kotlin code sees and the API level the engines are built for. The guard that checks the toolchain tests one specific file, the aarch64-linux-android26 clang binary, and prints a fixed error naming the expected NDK root if it is not executable.

## One engine bakes in its commit and the other records nothing

The two Go engines are not treated symmetrically by the build. CottenDns has a version variable taken straight from git, resolved by running rev-parse HEAD inside its submodule directory, and that commit is injected into the binary through a linker flag naming a version variable inside its own internal package. StormDNS, built by four parallel targets of its own with the same external linking flags, has no equivalent variable in the Makefile and no ldflag carrying its submodule commit. So a binary produced by make debug can report which CottenDns revision went into it and cannot report which StormDNS revision did, which is the sort of asymmetry that makes a field bug harder to trace back to a source tree.

## Eight native builds, 16 KB pages, and a stripped symbol table

One make debug runs four targets for StormDNS and four for CottenDns, covering arm64-v8a, armv7, x86_64 and x86, so a single debug build compiles eight cross targeted Go binaries before Gradle assembles anything. Each target sets CGO_ENABLED and points CC at the NDK clang for its own ABI, and the shared linker flags ask for external linking with the symbol table and debug information stripped. The two page size options in those flags set both the maximum and the common page size to 16384, which is the alignment current Android releases expect rather than a tuning choice local to this project. A Go build cache directory is kept inside the StormDNS submodule rather than in the user's home cache, so the submodule working tree carries build state as well as source.

## No app store listing, and three tag naming conventions

The project publishes nothing to Google Play and says so in a warning of its own: any WhiteDNS APK, listing or package found on Google Play or another marketplace is not an official release and may be modified, outdated or unsafe, and the repository plus the official Telegram channel are named as the only sanctioned sources of updates. The release tags do not follow one convention. The two most recent are named 1.6.2 and 1.6.0 with no v prefix, while the one before them is v1.5.1c-rc17 with a prefix and a release candidate suffix, and 1.6.1 does not appear at all. A project asking readers to distrust marketplace copies is asking them to trace releases through a channel and a tag scheme that does not sort the way a package manager would expect.

## MasterDNS is credited in the credits but has no build target

The credits name three separate projects. MasterDNS Client is described as backing WhiteDNS, StormDNS comes from an outside author, and CottenDns lives under the WhiteDNS organisation, with the Android VPN path additionally packaging tun2proxy and deferring to THIRD_PARTY_NOTICES.md for third-party licence details. Only two of those three appear as build inputs. The Makefile has stormdns and cottendns targets and nothing for MasterDNS, and the third_party tree holds the two submodules that get compiled. The debug build also carries its own identity so QA can install it beside the production app, using a debug package name and a separate app label, which is the one packaging concession the build section makes to anyone other than the maintainers.

## Conclusion

Read the licensing before anything else, because it decides whether this is usable for you at all. The metadata field records no recognised licence, the tree carries LICENSE.MD alongside TRADEMARK.MD, CLA.md and CONTRIBUTING.md, and the README calls the project source-available proprietary rather than open source, with an explicit bar on forking, repackaging APKs and reusing the name or branding. Contributions are accepted, so this is not a dead end for contributors, but it is not a dependency you can vendor. Second, the distribution channel deserves the attention the README itself demands: there is no Google Play publication, the project treats any marketplace APK as unofficial, and updates come through a Telegram channel. Third, if you only want to read the code, the build needs a Go toolchain, two different Android NDKs and, on an Apple Silicon machine, an explicit NDK_HOST override, because the default points at an Intel Mac toolchain path. Anyone evaluating this for real use should decide first whether a source-available client with no store listing and a Telegram update path fits their environment.

## FAQ

### Is WhiteDNS on Google Play?

No. The README states the project has no Google Play publication and warns that any WhiteDNS APK or listing found on Google Play or another marketplace is not an official release and may be modified, outdated or unsafe. It names the repository and the official Telegram channel as the only update sources.

### Can I fork or repackage WhiteDNS?

No. The README describes the project as source-available proprietary software that is not open-source, and bars copying it into another product, publishing modified builds, repackaging APKs, redistributing binaries, and reusing the name, logo, icon or design. Contributions back to the official repository are accepted.

### What do I need to build WhiteDNS from source?

Android Studio or the SDK command line tools, JDK 17, a Go version matching the submodule go.mod files, an Android SDK platform for compileSdk 36, and two NDK versions: 26.3.11579264 generally and 29.0.14206865 for rebuilding the StormDNS and CottenDns native clients. The build also needs git submodule update --init --recursive first.

### Why does my WhiteDNS build fail on an Apple Silicon Mac?

The Makefile sets NDK_HOST to darwin-x86_64, which is the Intel Mac layout of the NDK's prebuilt LLVM tree, and SDK_ROOT falls back to the macOS path under Library. On an Apple Silicon machine the NDK lives under a different host triple, so NDK_HOST and NDK_ROOT both need overriding. SDK_ROOT, ANDROID_API and GO are overridable too.

### Does WhiteDNS use VPN mode or proxy mode?

Both. Proxy mode offers a local SOCKS5 listener with an optional HTTP proxy bridge, and VPN mode uses the Android VpnService with packaged tun2proxy native libraries, split tunnel options for routing, and foreground service notifications for long sessions. StormDNS and CottenDns profiles can be imported and exported through stormdns:// links.

## Sources

- [Issues](https://github.com/WhiteDNS/WhiteDNS-Android/issues)
- [Project website](https://t.me/whitedns)
- [README](https://github.com/WhiteDNS/WhiteDNS-Android/blob/main/README.md)
- [Releases](https://github.com/WhiteDNS/WhiteDNS-Android/releases)
- [WhiteDNS/WhiteDNS-Android on GitHub](https://github.com/WhiteDNS/WhiteDNS-Android)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/whitedns-whitedns-android
