🌐 HTTP DNS (DoH)

KNETHttpDns to implementacja DNS over HTTPS (DoH), która szyfruje zapytania DNS i chroni przed DNS spoofingiem.

💡 Kiedy używać?
  • Zabezpieczenie przed DNS cache poisoning
  • Prywatność - szyfrowane zapytania DNS
  • Omijanie lokalnego DNS (np. publiczne WiFi)
  • Custom DNS routing dla testów
  • Blokowanie reklam/trackerów (AdGuard)

📦 Import

import rip.nerd.kitsunenet.util.KNETHttpDns
import rip.nerd.kitsunenet.util.createOkHttpClient

🚀 Szybki start

Wbudowane providery

// Cloudflare DoH (zalecane - szybki i prywatny)
val dns = KNETHttpDns.cloudflare()

// Google DoH
val dns = KNETHttpDns.google()

// Quad9 DoH (bezpieczeństwo + prywatność)
val dns = KNETHttpDns.quad9()

// AdGuard DoH (blokuje reklamy i trackery)
val dns = KNETHttpDns.adguard()

Integracja z KNETClient

// Utwórz OkHttpClient z DNS
val okHttpClient = OkHttpClient.Builder()
    .dns(dns)
    .build()

// Użyj z KNETClient
val client = KNETClient(okHttpClient = okHttpClient)

// Lub użyj extension function
val okHttpClient = dns.createOkHttpClient {
    connectTimeout(30, TimeUnit.SECONDS)
    readTimeout(30, TimeUnit.SECONDS)
}

🔧 Konfiguracja

val dns = KNETHttpDns.builder()
    // DoH server URL
    .dohUrl("https://dns.example.com/dns-query")

    // Lub użyj presetów
    .cloudflare()  // Cloudflare
    .google()      // Google
    .quad9()       // Quad9
    .adguard()     // AdGuard

    // Caching
    .enableCache(true)         // Włącz cache DNS
    .cacheTtlSeconds(300)      // 5 minut TTL

    // Fallback
    .fallbackToSystemDns(true) // Użyj system DNS przy błędzie

    // Timeout
    .timeout(5000)             // 5s timeout dla DoH

    .build()
Provider URL Cechy
Cloudflare cloudflare-dns.com Szybki, prywatny, globalny
Google dns.google Niezawodny, wysoka dostępność
Quad9 dns.quad9.net Bezpieczeństwo, blokada malware
AdGuard dns.adguard.com Blokuje reklamy i trackery

⚡ Pre-resolve

Pre-resolve często używanych domen dla szybszego startu aplikacji.

// Pre-resolve przy starcie aplikacji
class MyApplication : Application() {

    private val dns = KNETHttpDns.cloudflare()

    override fun onCreate() {
        super.onCreate()

        // Pre-resolve w tle
        lifecycleScope.launch {
            dns.preResolve(listOf(
                "api.example.com",
                "cdn.example.com",
                "auth.example.com",
                "static.example.com"
            ))
        }
    }
}

// Pojedyncza domena
dns.preResolve("api.critical-service.com")

📊 Statystyki

val stats = dns.getStats()

println("Cache hits: ${stats.cacheHits}")
println("Cache misses: ${stats.cacheMisses}")
println("DoH queries: ${stats.dohQueries}")
println("DoH errors: ${stats.dohErrors}")
println("Fallback queries: ${stats.fallbackQueries}")
println("Cache size: ${stats.cacheSize}")
println("Hit rate: ${stats.hitRate}%")

Monitoring w produkcji

// Loguj statystyki co 5 minut
timer.scheduleAtFixedRate(0, 300_000) {
    val stats = dns.getStats()

    if (stats.dohErrors > 10) {
        analytics.log("dns_issues", mapOf(
            "errors" to stats.dohErrors,
            "fallbacks" to stats.fallbackQueries
        ))
    }

    // Reset dla kolejnego okresu
    dns.resetStats()
}

🗄️ Zarządzanie cache

// Sprawdź czy hostname jest w cache
if (dns.isCached("api.example.com")) {
    println("DNS w cache")
}

// Pobierz z cache (bez rozwiązywania)
val addresses = dns.getCached("api.example.com")
addresses?.forEach { ip ->
    println("IP: ${ip.hostAddress}")
}

// Invaliduj konkretny hostname
dns.invalidate("stale-api.example.com")

// Wyczyść cały cache
dns.clearCache()

🛡️ Bezpieczeństwo

⚠️ Ważne

DoH szyfruje zapytania DNS, ale nie ukrywa ruchu IP. Administrator sieci nadal może widzieć z jakimi serwerami się łączysz. Dla pełnej prywatności rozważ VPN.

Dlaczego DoH?

💡 Praktyczne przykłady

Konfiguracja dla produkcji

class NetworkModule {

    val httpDns = KNETHttpDns.builder()
        .cloudflare()
        .enableCache(true)
        .cacheTtlSeconds(600)  // 10 minut
        .fallbackToSystemDns(true)
        .timeout(3000)  // Szybki timeout
        .build()

    val okHttpClient = OkHttpClient.Builder()
        .dns(httpDns)
        .connectTimeout(30, TimeUnit.SECONDS)
        .readTimeout(30, TimeUnit.SECONDS)
        .build()

    val knetClient = KNETClient(okHttpClient = okHttpClient)
}

Z Dependency Injection (Hilt)

@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {

    @Provides
    @Singleton
    fun provideHttpDns(): KNETHttpDns {
        return KNETHttpDns.builder()
            .cloudflare()
            .enableCache(true)
            .cacheTtlSeconds(300)
            .fallbackToSystemDns(true)
            .build()
    }

    @Provides
    @Singleton
    fun provideOkHttpClient(dns: KNETHttpDns): OkHttpClient {
        return OkHttpClient.Builder()
            .dns(dns)
            .build()
    }

    @Provides
    @Singleton
    fun provideKNETClient(okHttpClient: OkHttpClient): KNETClient {
        return KNETClient(okHttpClient = okHttpClient)
    }
}

AdGuard dla blokowania reklam

// Aplikacja bez reklam w WebView i API calls
val dns = KNETHttpDns.adguard()

// AdGuard automatycznie blokuje:
// - Domeny reklamowe (ads.*, tracking.*)
// - Trackery analityczne
// - Malware/phishing

val client = KNETClient(
    okHttpClient = dns.createOkHttpClient()
)

🔗 API Reference

KNETHttpDns

Metoda Opis
lookup(hostname) Rozwiązuje hostname na IP (implements Dns)
preResolve(hostnames) Pre-resolve listy domen
clearCache() Czyści cache DNS
invalidate(hostname) Usuwa wpis z cache
isCached(hostname) Sprawdza czy jest w cache
getCached(hostname) Pobiera z cache (bez rozwiązywania)
getStats() Statystyki cache i zapytań
resetStats() Resetuje statystyki

Builder

Metoda Opis
dohUrl(url) Custom DoH server URL
cloudflare() Użyj Cloudflare DoH
google() Użyj Google DoH
quad9() Użyj Quad9 DoH
adguard() Użyj AdGuard DoH
enableCache(enabled) Włącz/wyłącz cache
cacheTtlSeconds(ttl) TTL cache w sekundach
fallbackToSystemDns(enabled) Fallback na system DNS
timeout(ms) Timeout dla DoH zapytań

📚 Zobacz też