Enhancing AdAway: Engineering Custom Upstream DNS, Wildcard Matching, and Material 3 for Android
The Motivation Behind the Project
AdAway has long stood as one of the most reputable open-source ad blockers on Android, offering dual-engine blocking via root hosts modification or local loopback VPN interception. However, modern mobile privacy landscapes require encrypted upstream DNS selection, wildcard subdomain filtering, and streamlined rule triage without friction. In this fork (@athanasso/AdAway), I engineered high-impact architectural enhancements: injecting custom upstream DNS resolution into Android's VpnService tun0 interface, compiling runtime glob wildcard rules (* and ?) with LRU caching, designing a 1-tap curated blocklist catalog, and adding alarm-backed temporary snooze pauses.
Core Features and Design Goals
- Custom Upstream DNS Resolver: Configurable upstream DNS redirection (Cloudflare 1.1.1.1, Quad9 9.9.9.9, AdGuard DNS, or custom IP) mapping fake interface addresses to selected secure resolvers instead of defaulting to unencrypted ISP network DNS.
- Runtime Wildcard & Glob Matching: High-performance regex transformation of glob patterns (
*.ads.example.com,*tracker*) evaluated on DNS queries and memoized in an in-memory LRU block cache. - Curated Blocklist Preset Catalog: Built-in multi-choice catalog allowing one-tap addition of top community filter subscriptions (Hâgezi Multi Light, OISD Basic, StevenBlack Unified, AdGuard DNS filter, Dan Pollock).
- 5-Minute Snooze & Alarm Resumption: Added quick-pause snooze action in the persistent notification shade backed by Android's
AlarmManagerto auto-resume protection after bypassing temporary site brokenness. - Modern Material 3 Redesign: Clean rounded cards, elevated hierarchy, dynamic status bar tinting, and status-aware notification accents (green active, amber paused) eliminating legacy alarm-red notification discolorations.
- 1-Tap DNS Log Management: Quick dialog and snackbar with undo to instantly block or allow inspected domain queries directly from the real-time request log.
Deep Dive: How It Works Under the Hood
Android's VpnService routes system-wide network packets through a virtual TUN interface (tun0). To filter ad domains, AdAway constructs fake local DNS server aliases inside an RFC5735 subnet. Previously, unblocked queries fell back strictly to system Wi-Fi/Cellular network resolvers. By modifying DnsServerMapper and PreferenceHelper, we intercept tunnel configuration to bind the mapped aliases directly to user-selected secure upstream resolvers like Quad9 or Cloudflare. To avoid performance degradation during rapid DNS lookups, wildcard rules are pre-compiled into Case-Insensitive Pattern objects on service boot and rule mutations, while resolved queries are memoized directly in a 4,096-entry LruCache.
Technical Implementation
- VpnService Tun Interception: Injected custom DNS server addresses directly into the VpnService.Builder configuration, ensuring fake alias IPs route deterministically to secure upstream DNS resolvers.
- Regex Compilation with LRU Memoization: Converted user wildcard glob strings to standard regexes with RegexUtils.wildcardToRegex, compiled them into immutable Pattern objects on background thread, and stored query verdicts in a 4K-entry LruCache.
- Room DAO Reactive Subscriptions: Extended HostListItemDao with specialized SQL queries for wildcard patterns and curated source bulk inserts inside transactional Room database batches.
- AlarmManager Snooze Architecture: Used setAndAllowWhileIdle with PendingIntent broadcasts to CommandReceiver to automatically wake the device and reactivate VPN filtering after 5 minutes of snooze.
- Modern Build & Release Automation: Upgraded Gradle Version Catalogs (libs.versions.toml), automated multi-scheme APK signing (v2/v3), and integrated Obtainium badge linking for instant app-store style updates.
Architecture Overview
AdAway operates via two complementary engines: a traditional Root-mode engine that modifies /system/etc/hosts and a non-root VpnService engine. Our enhancements augment the VpnModel pipeline: incoming DNS queries pass through an LRU block cache check -> explicit allowlist bypass -> compiled wildcard pattern evaluation -> parent domain traversal, resolving in sub-millisecond response times before packets reach the upstream socket.
Challenges I Faced Along the Way
Maintaining strict backward compatibility with upstream AdAway while upgrading legacy preference screens and ensuring thread safety was paramount. Android's background execution limits also required careful handling of snooze timeouts: using AlarmManager with ELAPSED_REALTIME_WAKEUP and immutable PendingIntents guarantees the VPN protection resumes reliably even under deep Android Doze states.
The Technology Stack
Native Android (API 23–34), Java 17, Android VpnService, NDK / C (pcap4j / tcpdump packet capture), Room SQLite persistence, Material Components / Material 3, Gradle Version Catalogs, and GitHub Releases distribution.
Final Reflections
Modernizing mature open-source infrastructure provides immense insight into system-level Android networking, socket plumbing, and production UX. This fork demonstrates how thoughtful architectural extensions can turn a classic utility into a modern, flexible privacy powerhouse.