You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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
Copy file name to clipboardExpand all lines: CLAUDE.md
+49-6Lines changed: 49 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,7 +1,7 @@
1
1
# HostShield
2
2
3
3
## 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`.
5
5
6
6
## Tech Stack
7
7
- Kotlin, Jetpack Compose, Material 3
@@ -11,7 +11,7 @@ Modern, AMOLED-dark hosts-based ad blocker app for Android. Inspired by AdAway.
11
11
- OkHttp for source downloads + DoH resolver, libsu for root access
12
12
13
13
## 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).
15
15
-**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.
16
16
-**DohResolver** - RFC 8484 POST+GET, certificate pinning, smart latency-based failover (EMA per provider, auto-selects fastest), unpinned fallback as last resort.
17
17
-**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.
-`app/app/src/main/java/com/hostshield/service/DnsPacketBuilder.kt` - v5.0: DNS wire format builder/parser + SVCB/HTTPS type constants + queryTypeLabel()
- 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)
73
76
- 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
74
77
- 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)
75
78
- 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
- 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`)
96
139
- 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
98
141
- OverlapAnalysisScreen downloads sources with `forceDownload=true` to bypass ETag caching
99
142
- Regex rules limited to 500 chars with nested quantifier rejection (ReDoS prevention)
100
143
- Log buffer is LinkedBlockingQueue(5000) — uses `offer()` instead of `add()`, tracks dropped count
0 commit comments