Skip to content

Commit f51e4aa

Browse files
committed
v5.0.0: Core engine upgrades — serve-stale DNS, hash set fast path, offline GeoIP
- Serve-stale DNS cache (RFC 8767): returns expired entries during WiFi/cellular transitions with 3-day stale window and background refresh - Negative caching with SOA TTL (RFC 2308) and SERVFAIL caching (RFC 9520) - DNS cache prefetching (Unbound algorithm): background refresh at <10% TTL remaining for domains queried 3+ times - Hash set fast path for exact domain matches (~2x faster for 90% of lookups) - Filter decision LRU cache (8K entries) to skip trie on repeated queries - CNAME cloak databases from AdGuard + NextDNS, auto-updated via CnameCloakUpdater - SVCB/HTTPS record parsing (TYPE 64/65) for SVCB-based cloaking detection - Offline GeoIP via MaxMind GeoLite2 (Country + ASN, ~14MB, zero-latency) - Configurable TTL caps (60s floor, 24h ceiling) - ProGuard rules for new classes and MaxMind/Jackson dependencies - Updated README with comprehensive feature tables and architecture diagram
1 parent c1ad2aa commit f51e4aa

18 files changed

Lines changed: 2207 additions & 189 deletions

CLAUDE.md

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# HostShield
22

33
## Overview
4-
Modern, AMOLED-dark hosts-based ad blocker app for Android. Inspired by AdAway. v4.6.0.
4+
Modern, AMOLED-dark hosts-based ad blocker app for Android. Inspired by AdAway. v5.0.0. Roadmap through v6.0 in `docs/RESEARCH.md`.
55

66
## Tech Stack
77
- Kotlin, Jetpack Compose, Material 3
@@ -11,7 +11,7 @@ Modern, AMOLED-dark hosts-based ad blocker app for Android. Inspired by AdAway.
1111
- OkHttp for source downloads + DoH resolver, libsu for root access
1212

1313
## Key Architecture
14-
- **BlocklistHolder** - Trie-based O(m) domain lookup, 200K+ domains, volatile root for thread safety. Regex rules capped at 500 chars with nested quantifier rejection (ReDoS prevention).
14+
- **BlocklistHolder** - v5.0: Hash set fast path (O(1) exact match before trie, ~2x faster for 90% of lookups) + filter decision LRU cache (8K entries, invalidated on update). Trie-based O(m) domain lookup, 200K+ domains, volatile root for thread safety. Regex rules capped at 500 chars with nested quantifier rejection (ReDoS prevention).
1515
- **DnsVpnService** - Local VPN DNS interception, TUN interface, dual-stack (IPv4+IPv6), DNS trap, DoH/DoT blocking, TCP DNS RST for both IPv4 and IPv6. Bounded log buffer (LinkedBlockingQueue 5000) with overflow detection. Context-aware firewall checks (screen off/background/metered). VPN stability tracking (uptime, rebuilds, fd errors, dropped queries). Publishes cache stats + dropped count via companion object for UI.
1616
- **DohResolver** - RFC 8484 POST+GET, certificate pinning, smart latency-based failover (EMA per provider, auto-selects fastest), unpinned fallback as last resort.
1717
- **RootDnsLogger** - Root-mode DNS proxy on 127.0.0.1:5454, iptables NAT redirect, UID attribution.
@@ -32,10 +32,12 @@ Modern, AMOLED-dark hosts-based ad blocker app for Android. Inspired by AdAway.
3232
- `app/app/src/main/java/com/hostshield/service/DnsVpnService.kt` - VPN packet loop (~1850 lines)
3333
- `app/app/src/main/java/com/hostshield/domain/BlocklistHolder.kt` - Trie + regex + wildcard engine
3434
- `app/app/src/main/java/com/hostshield/service/DohResolver.kt` - DoH with smart latency failover
35-
- `app/app/src/main/java/com/hostshield/service/DnsCache.kt` - LRU DNS cache with TTL
36-
- `app/app/src/main/java/com/hostshield/service/DnsPacketBuilder.kt` - DNS wire format builder/parser
35+
- `app/app/src/main/java/com/hostshield/service/DnsCache.kt` - v5.0: LRU DNS cache with serve-stale (RFC 8767), negative caching (RFC 2308), SERVFAIL caching (RFC 9520), prefetching (Unbound algorithm), configurable TTL caps (60s-24h)
36+
- `app/app/src/main/java/com/hostshield/service/CnameCloakUpdater.kt` - v5.0: Fetches AdGuard + NextDNS CNAME cloak databases
37+
- `app/app/src/main/java/com/hostshield/service/DnsPacketBuilder.kt` - v5.0: DNS wire format builder/parser + SVCB/HTTPS type constants + queryTypeLabel()
3738
- `app/app/src/main/java/com/hostshield/util/TrackerSignatureDb.kt` - APK tracker SDK scanner (Room-cached)
38-
- `app/app/src/main/java/com/hostshield/util/GeoIpLookup.kt` - GeoIP/ASN lookup (rate limited)
39+
- `app/app/src/main/java/com/hostshield/util/GeoIpLookup.kt` - GeoIP/ASN lookup via ip-api.com (rate limited, legacy — use OfflineGeoIp for new code)
40+
- `app/app/src/main/java/com/hostshield/util/OfflineGeoIp.kt` - v5.0: MaxMind GeoLite2 offline lookups (Country+ASN), unlimited, zero-latency
3941
- `app/app/src/main/java/com/hostshield/util/AppPrivacyScorer.kt` - Per-app A-F privacy grades
4042
- `app/app/src/main/java/com/hostshield/util/ImportExportUtil.kt` - Multi-format import/export + firewall rules
4143
- `app/app/src/main/java/com/hostshield/service/AutomationReceiver.kt` - Rate-limited automation API
@@ -70,6 +72,7 @@ cd app
7072
- Secrets configured: `KEYSTORE_BASE64`, `KEY_ALIAS`, `KEY_PASSWORD`, `STORE_PASSWORD`
7173

7274
## Version History
75+
- v5.0.0: Core engine upgrades — serve-stale DNS cache (RFC 8767), negative caching with SOA TTL (RFC 2308), SERVFAIL caching (RFC 9520), DNS cache prefetching (Unbound algorithm), hash set fast path for exact matches (~2x), filter decision LRU cache, CNAME cloak databases (AdGuard+NextDNS), SVCB/HTTPS record parsing, offline GeoIP via MaxMind GeoLite2, configurable TTL caps (60s-24h)
7376
- v4.6.0: DNS latency sparkline on Home (live response time mini-graph), source summary stats on Sources screen (total domains, size, unhealthy count), search history persistence (DataStore, 10 recent, chip display), search history chips on Home
7477
- v4.5.0: Query type distribution chart in Stats (A/AAAA/CNAME/MX bar chart), per-app DNS log drill-down (AppLogsScreen with domains + timeline tabs), permanent block/allow buttons in log detail sheet, log cleanup worker improved (6h interval, battery-not-low constraint)
7578
- v4.4.0: Connection log interface labels (rmnet0=Mobile, wlan0=WiFi, etc), DNS cache management in Settings (clear cache button + live stats), expanded notification (Pause 5m / Pause 30m / Stop), top querying apps mini-card on Home dashboard
@@ -92,9 +95,49 @@ cd app
9295
- v2.1.0: Automation API, iptables firewall, connection logging
9396
- v2.0.0: DoH, DNS trap, batch domain test, network stats
9497

98+
## Research & Roadmap
99+
- Full competitive analysis: `docs/RESEARCH.md` (30+ open-source projects, 52-item roadmap across 6 phases)
100+
- **Next milestone: v5.0** — Core Engine Upgrades:
101+
1. Adblock-syntax parsing (`||domain^`, `@@`, `$important`, `$dnsrewrite`) — unlocks modern blocklists (OISD deprecated hosts format)
102+
2. Serve-stale DNS cache (RFC 8767) — return expired entries when upstream unreachable
103+
3. Negative caching (NXDOMAIN/NODATA per RFC 2308)
104+
4. DNS cache prefetching (refresh at <10% TTL remaining)
105+
5. Hash set fast path for exact matches before trie (~2x faster for 90% of lookups)
106+
6. Bundle GeoLite2-Country + ASN databases (replace ip-api.com rate-limited API)
107+
- **v5.0 also**: Filter decision LRU cache, CNAME cloak databases (AdGuard+NextDNS), HTTPS/SVCB record parsing (ECH prep), two-tier cache (in-memory + persistent disk)
108+
- **v5.1**: Domain-per-app rules, metered/unmetered firewall, screen-off blocking, LAN toggle, category-based app blocking, DNS-only VPN mode (battery optimization)
109+
- **v5.2**: Expanded ETIP tracker DB (400+), network-based tracker detection, threat intel feeds, WebRTC/IPv6 leak tests, captive portal handling
110+
- **v5.3**: Vico charts, Lottie animations, M3 dynamic theming, Glance widget overhaul, onboarding refresh
111+
- **v5.4**: Expanded Tasker intents, Wi-Fi SSID profiles, encrypted backups, WebDAV sync, ACRA crash reporting
112+
- **v6.0**: Content filtering categories, Safe Search, DNS stamps (`sdns://`), split tunneling, DoT/DoQ/DNSCrypt, connection tracker, nDPI/JA3, parental controls, proxy mode (tri-mode: VPN+root+proxy)
113+
114+
## Key Competitor References
115+
- RethinkDNS (4.7k stars): Domain-per-app rules, metered/unmetered, Go firestack, succinct radix-trie (17M domains)
116+
- AdGuard urlfilter: Reference adblock-syntax engine with 6-level priority system, CNAME tracker database
117+
- AdAway (8.9k stars): Hosts-file-as-fallback pattern, local web server for blocked responses, systemless Magisk
118+
- PCAPdroid (3.8k stars): nDPI integration for JA3/JA4 fingerprinting, PCAP-NG streaming
119+
- NetGuard (3.5k stars): Screen on/off rules (most popular feature), native C sinkhole, DNS-only VPN routing
120+
- InviZible Pro (2.5k stars): Tri-mode (VPN/root/proxy), DNSCrypt+Tor+I2P, iptables refresh on connectivity change
121+
- TrackerControl (2.4k stars): Dual static+network tracker detection model
122+
- hagezi (16k stars): 7-format blocklist output, tiered blocking (Light→Ultimate)
123+
- DNS66 (2.2k stars): DNS-only VPN routing (port 53 only) — minimal battery (~0.5%/day)
124+
95125
## Gotchas
126+
- v5.0: DnsCache.get() now returns CacheResult (not ByteArray?) — callers must handle .response, .isStale, .needsPrefetch. Use getSimple() for backward-compat ByteArray? return.
127+
- v5.0: DnsCache.getStale() exists for serve-stale path — call when upstream fails to get expired-but-valid entry
128+
- v5.0: DnsCache.CacheStats has new fields: failureSize, staleHits, prefetchTriggers — update UI consumers
129+
- v5.0: BlocklistHolder.decisionCache is auto-cleared on every update() call — no manual invalidation needed
130+
- v5.0: BlocklistHolder.exactBlockSet is built alongside trie in update() — O(1) for exact matches, trie still needed for wildcards
131+
- v5.0: CnameCloakDetector now checks HTTPS/SVCB records (TYPE 64/65) for SVCB-based cloaking
132+
- v5.0: CnameCloakUpdater must be injected via Hilt and called from HostsUpdateWorker alongside DohBypassUpdater
133+
- v5.0: CnameCloakDetector.cnameCloakDomains is @Volatile set — call updateCloakDatabase() or loadCached() on startup
134+
- v5.0: OfflineGeoIp requires GeoLite2 MMDB files in app assets or internal storage. Falls back gracefully if missing — isReady() returns false
135+
- v5.0: OfflineGeoIp.initialize() copies from assets on first run. Call once in HostShieldApp.onCreate() via appScope
136+
- v5.0: GeoIpLookup (ip-api.com) is legacy — use OfflineGeoIp for new features. GeoIpLookup retained for city-level detail (GeoLite2-City is 70MB, not bundled)
137+
- v5.0: DnsPacketBuilder.queryTypeLabel() maps qtype ints to human labels (A, AAAA, SVCB, HTTPS, etc.)
138+
- v5.0: MaxMind GeoIP2 dependency added to build.gradle.kts (`com.maxmind.geoip2:geoip2:4.2.1`)
96139
- Room stores enums as strings — adding new enum values doesn't need migration
97-
- HostsUpdateWorker has DohBypassUpdater injected — runs on every periodic cycle regardless of blocking state
140+
- HostsUpdateWorker has DohBypassUpdater injected — runs on every periodic cycle regardless of blocking state. v5.0: also inject CnameCloakUpdater
98141
- OverlapAnalysisScreen downloads sources with `forceDownload=true` to bypass ETag caching
99142
- Regex rules limited to 500 chars with nested quantifier rejection (ReDoS prevention)
100143
- Log buffer is LinkedBlockingQueue(5000) — uses `offer()` instead of `add()`, tracks dropped count

0 commit comments

Comments
 (0)