AegisNet is a high-performance, cross-platform system-wide DNS Privacy Guard & Ad-Blocking Mobile Application for Android & iOS, built with Flutter and powered by a high-speed Rust Core Engine.
Official builds are listed at vannt-dev.github.io/official.html; anything else is not published by vannt-dev. The APK signing certificate fingerprints are listed there too.
┌──────────────────────────────────────────────────────────┐
│ Flutter UI │
│ (Dashboard, Stats, Rules, Live Logs, Analytics, Settings)│
└───────────────────────────┬──────────────────────────────┘
│ Dart FFI (dart:ffi)
▼
┌───────────────────────────────────────────────────────────────────────────────────┐
│ Rust Core Engine │
│ ├── Rule Engine (HashSet domain + subdomain matching; Hosts, EasyList, AdGuard) │
│ ├── DNS Interceptor & DoH Resolver (Sinkhole 0.0.0.0 for Ads, DNS-over-HTTPS) │
│ ├── DNS In-Memory Cache (per (domain, qtype) TTL cache for low latency) │
│ ├── SafeSearch Rewriter (exact-host enforcement for Google & DuckDuckGo) │
│ ├── Packet Parsing (minimal IPv4/UDP parser + checksum, `packet.rs`) │
│ └── Statistics Engine (Real-time counters & ring-buffer query logs) │
└─────────────────────────────────────────▲─────────────────────────────────────────┘
│ File Descriptor / IP Packets
▼
┌───────────────────────────────────────────────────────────────────────────────────┐
│ Native OS Layer (Local VPN) │
│ Android: VpnService (TUN interface & MethodChannel) │
│ iOS: NEPacketTunnelProvider (NetworkExtension framework) │
└───────────────────────────────────────────────────────────────────────────────────┘
- 🚀 Sub-Millisecond DNS Filtering: Powered by Rust
rule_enginewith a memory-optimizedDomainTrie(Prefix Tree) supporting Hosts format, EasyList DNS, and AdGuard domain rules. Matching is exact-domain and subdomain-aware with 50-70% lower memory footprint. - ⚡ DNS In-Memory Cache: Rust TTL cache keyed by
(domain, qtype), stamping each cached reply with the caller's transaction id for correct resolution. - 🗺️ Local DNS Mapping & Custom Hosts: Define custom internal DNS host overrides (
domain->IP, e.g.myrouter.local->192.168.1.1) with real-time UI control. - ⏰ Scheduled Quiet Hours (Parental Controls): Automatic category filter activation during configured quiet hours (e.g. 22:00 - 06:00).
- 🔒 Enforced SafeSearch: Exact-host SafeSearch rewriting for Google & DuckDuckGo (unrelated subdomains such as
mail.google.comare never touched). - 🌐 DNS-over-HTTPS, DNS-over-TLS & DNS-over-QUIC: Encrypted upstream over DoH (RFC 8484,
application/dns-message), DoT (RFC 7858, port 853) or DoQ (RFC 9250, UDP port 853). The built-in providers (Cloudflare, Google, AdGuard, Quad9) use DoH with IP-literal endpoints to avoid resolver bootstrap loops; a custom resolver can be anhttps://URL, atls://host[:port][#name]target or aquic://host[:port][#name]target, where#nameis the certificate name to verify when the host is an address. - 💻 Multi-Platform Desktop Support: Desktop scaffolding for Windows, macOS, and Linux powered by
DesktopDnsProxy. - ⏱️ DNS Latency Benchmark: Interactive built-in benchmark tool to test and automatically select the fastest upstream DNS provider.
- 📱 System-Wide Protection: Intercepts OS-level DNS traffic via local split-tunnel VPN (
VpnServiceon Android,NEPacketTunnelProvideron iOS) without routing web traffic to remote servers. - 📊 Real-time Dashboard & Analytics: Interactive traffic graphs, query counters, ad-block stats, bandwidth savings, and detailed category analytics.
- 🚫 Block an app (Android 10+): Refuse every DNS lookup a chosen app makes, from the Top apps list in Analytics. It stops name lookups, not connections to fixed IP addresses.
- 📱 Per-app statistics (Android 10+): See which apps make the most DNS queries and how many were blocked, and filter the live query log by app.
- 🛡️ Bypass protection: DNS sent straight to public resolvers is filtered too, and their encrypted DNS is refused so apps fall back to the filter.
- 📜 Live Query Log & CSV Export: Real-time query monitoring with status filter chips (
ALL LOGS,BLOCKED,ALLOWED), instant domain search and CSV export. Tap an entry to allow or block that domain on the spot. - ⚡ Custom Whitelist & Blacklist: Flexible custom rule management with instant hot-reloading.
- 🔄 Background Auto-Sync: Automatic blocklist updates and background rule synchronization.
- 🌍 4-Language i18n Support: Full internationalization for English (EN), Vietnamese (VI), Korean (KO), and Japanese (JA).
- 🌙 Dynamic Dark/Light Theme: Seamless theme switching with customizable app settings.
AegisNet blocks by domain name. It sees which host a device asks for and answers or refuses; it never looks inside the encrypted connection. That draws a hard line around what it can do.
Blocked effectively — ads and trackers served from their own domains: banners and interstitials in most free apps and games (AppLovin, Vungle, AdMob and similar networks), analytics and telemetry endpoints, and web ads while browsing.
Not blocked — ads served from the same domains as the content itself:
| App | Why |
|---|---|
| YouTube | Ads and video both come from googlevideo.com. Blocking it blocks the video too. Most YouTube ads are also stitched into the video stream server-side, so there is no separate request to refuse. |
| Facebook / Instagram | In-feed ads arrive over the same hosts as the feed. |
| Spotify, TikTok | Same pattern: ad content shares the delivery infrastructure. |
This is a property of DNS filtering itself, not a gap in the rule list — no blocklist can fix it. Removing YouTube ads specifically requires a different approach, such as an alternative client (ReVanced, NewPipe) or YouTube Premium.
| Platform | Native DNS filtering | Notes |
|---|---|---|
| Android | ✅ Working (verified on emulator) | TUN → Rust → device pipeline, DNS-only routing, DoH upstream. libaegis_core.so is built by a Gradle cargo-ndk task, or fetched already built when the engine's source is absent. |
| iOS | 🚧 App shell builds in CI; filtering not wired up | The Flutter shell compiles on a macOS runner on every PR. Extension provider, NETunnelProviderManager channel, entitlements, App Group state sharing and the Rust framework script are all in the repo, and the Rust core cross-compiles for iOS. Still missing: the PacketTunnel target does not exist in the Xcode project, so none of the extension Swift has ever been compiled. Final assembly needs macOS/Xcode + a paid Apple Developer account — see ios/IOS_SETUP.md. |
| Desktop | ✅ Scaffolding Ready (Windows/macOS/Linux) | Full native desktop project scaffolding with DesktopDnsProxy integration for local DNS resolution. |
| Web | ➖ Fallback Engine / WASM Ready | Runs the pure-Dart fallback engine (simulation) with WASM target scaffolding for browser testing. |
When the native engine is unavailable, the app gracefully falls back to a pure-Dart simulation engine instead of failing — useful for UI work without a native toolchain. See CHANGELOG.md for the full list of changes.
aegis-net/
├── android/ # Native Android VpnService & MethodChannel
│ └── app/
│ ├── build.gradle.kts # cargo-ndk preBuild task -> jniLibs
│ └── src/main/
│ ├── jniLibs/ # libaegis_core.so per ABI (built, git-ignored)
│ └── kotlin/com/aegisnet/app/
│ ├── AegisVpnService.kt
│ └── MainActivity.kt
├── ios/ # Native iOS NEPacketTunnelProvider (WIP)
│ ├── PacketTunnel/ # Extension sources — target NOT created yet, never compiled
│ │ └── PacketTunnelProvider.swift
│ └── Runner/
│ ├── AppDelegate.swift # registers the channel from didInitializeImplicitFlutterEngine
│ ├── SceneDelegate.swift # UIScene lifecycle (Flutter 3.35+)
│ └── VpnManager.swift # com.aegisnet/vpn MethodChannel <-> NETunnelProviderManager
├── rust/ # Rust Core Engine Crate
│ └── aegis_core/
│ ├── Cargo.toml
│ └── src/
│ ├── api.rs # FFI exported functions & bridge interface
│ ├── cache.rs # DNS In-Memory (domain, qtype) TTL cache
│ ├── dns_filter.rs # DNS parser, sinkhole, SafeSearch & DoH upstream
│ ├── rule_engine.rs # Domain + subdomain HashSet matcher
│ ├── packet.rs # IPv4/UDP parse, reply reassembly & checksum
│ ├── jni_bridge.rs # JNI entry point for the Android VpnService
│ ├── shared_state.rs # Snapshots crossing the iOS app <-> extension boundary
│ ├── statistics.rs # Ring buffer logs & real-time counter statistics
│ └── lib.rs
├── lib/ # Flutter Application (Dart)
│ ├── main.dart
│ └── src/
│ ├── bridge/ # Flutter-Rust FFI & Native VPN Channel
│ ├── i18n/ # 4-language string localization (EN, VI, KO, JA)
│ ├── providers/ # State management (VpnProvider, ThemeProvider)
│ ├── screens/ # Dashboard, Analytics, Rules, Logs, Settings
│ └── services/ # DNS Benchmark & Rule Downloader Services
├── .githooks/ # Pre-commit & Pre-push Git hooks
├── .github/workflows/ # CI/CD workflows (Build & Test matrix)
├── pubspec.yaml
└── README.md
For detailed setup, building, testing, and deployment instructions, refer to the project documentation:
- 📖 User Guide: USER_GUIDE.md | USER_GUIDE_EN.md
- 🛠️ Build Guide: BUILD_GUIDE.md | BUILD_GUIDE_EN.md
- 🚀 Google Play Store Deployment: GOOGLE_PLAY_DEPLOYMENT_GUIDE.md
- 🍎 Apple App Store Deployment: APP_STORE_DEPLOYMENT_GUIDE.md
- 🗺️ Product Roadmap: ROADMAP.md
- 📓 Changelog: CHANGELOG.md
- 🍎 iOS Packet Tunnel Setup: ios/IOS_SETUP.md
- Flutter SDK (v3.0.0+ for Android/Web; iOS needs 3.35+ — the iOS shell
uses the UIScene lifecycle APIs
FlutterSceneDelegate/FlutterImplicitEngineDelegate, which older SDKs do not have. CI builds on stable 3.44.x, matching.metadata.) - Rust Toolchain (
rustup,cargo) - Google Chrome / MS Edge (for Web local testing) or Android Studio / Visual Studio 2022 (for platform native builds)
flutter pub getNote: If the native engine is not compiled, AegisNet automatically falls back to its built-in Pure Dart Engine, allowing UI testing without native compilation.
The engine's source is not in this repository.
rust/aegis_coreis a git submodule of the private repositoryvannt-dev/aegis-core. With read access to it, fetch it withgit submodule update --init rust/aegis_core(or clone with--recurse-submodules). Without access the directory stays empty, and the build uses the engine already built: see Building without the engine's source below. You can then skip the rest of this step.
cd rust/aegis_core
cargo build --release # host build (desktop/tests)
cd ../..Android: the native library is built automatically. The Gradle preBuild
task runs cargo-ndk and drops libaegis_core.so into jniLibs for every ABI,
so a normal flutter build apk / flutter run produces a filtering-capable
build. It requires the Rust Android targets and cargo-ndk:
rustup target add aarch64-linux-android armv7-linux-androideabi x86_64-linux-android
cargo install cargo-ndkIf cargo-ndk is not on PATH, the task is skipped and the app runs in the
pure-Dart fallback (no crash).
💡 Windows Troubleshooting (
os error 4551): If Windows Smart App Control blockscargo.exe, add an exclusion for~/.cargoand~/.rustupin Windows Security > App & browser control, or switch toolchain to GNU (rustup default stable-x86_64-pc-windows-gnu).
A clone of this repository alone builds a working app. Every release from 1.6.0
on carries the engine as binaries, and the build fetches them when
rust/aegis_core is empty. No Rust toolchain is needed.
- Android: nothing to do.
flutter build apk/flutter runfetchesaegis-engine-android.zip(the threelibaegis_core.soof that release's APK) intoandroid/app/src/main/jniLibsand checks it against the published SHA-256. The release of this checkout's version is tried first, then the latest one.-Paegis.prebuilt=falsebuilds without an engine instead;-Paegis.engineUrl=<url>takes the two files from another place. - iOS (on a Mac):
./ios/fetch_prebuilt_engine.shputsAegisCore.xcframeworkintoios/Frameworks, where./ios/build_rust_ios.shwould have written it. The app shell builds without it too; see the platform table above for what iOS does today. - Desktop and Web run the pure-Dart fallback engine, as they do with the source.
The binaries are the ones the release itself shipped, and they are what the build falls back to whenever the source is missing. Without a network the build still succeeds, in fallback mode: the app installs and runs but filters nothing, and the build log says so.
-
Run Web Debug Mode (Hot Reload):
flutter run -d chrome
(or
flutter run -d edge) -
Run Web Production Server:
flutter build web --release npx serve build/web -l 8080
Then open http://localhost:8080 in your browser.
-
Run on iOS (macOS + Xcode 15+ only):
flutter build ios --no-codesign # verify the shell compiles flutter run -d <simulator-id> # flutter devices to list them
There is no CocoaPods in this project — the only native plugin goes through Swift Package Manager, so
pod installis not a step and will fail with No Podfile found. If you open Xcode, openios/Runner.xcworkspace, notRunner.xcodeproj; opening the project directly leaves Xcode unable to resolve the generated package and it reports Missing package product 'FlutterGeneratedPluginSwiftPackage'.DNS filtering does not work on iOS yet — the
PacketTunneltarget still has to be created in Xcode. Seeios/IOS_SETUP.md.
- Flutter Unit Tests:
flutter test - Rust Core Tests:
cd rust/aegis_core cargo test
# Flutter Analysis & Format
flutter analyze
dart format --output=none --set-exit-if-changed .
# Rust Format & Lints
cd rust/aegis_core
cargo fmt --check
cargo clippy -- -D warningsAegisNet uses GitHub Actions for CI/CD with parallel job execution, Cargo & Gradle caching, and automated verification:
- Git Hooks: Pre-commit formatting & strict pre-push test gate (
.githooks/). - Build & Test (
build.yml): Rustcargo check/test, Flutter analyze/test/web build, and Android debug APK build. Runs on every push tomain/developand every PR. - iOS Build Verification (
ios.yml): cross-compiles the Rust core for iOS targets and builds the Flutter iOS shell (flutter build ios --no-codesign) on a macOS runner. Both jobs gate — a broken iOS shell fails the run. Same triggers as above (push tomain/develop, every PR). - Release (
release.yml): builds, signs and publishes the Android release APK (GitHub Release + Firebase App Distribution). Only runs onmain— a PR intomainbuilds a downloadable artifact without publishing, a push/merge tomainpublishes for real.
Distributed under the MIT License. See LICENSE for more information.