{"id":46555420,"url":"https://github.com/faserf/shielddns","last_synced_at":"2026-04-14T12:01:31.123Z","repository":{"id":328912417,"uuid":"1117157323","full_name":"FaserF/ShieldDNS","owner":"FaserF","description":"ShieldDNS is a lightweight, efficient, and privacy-focused DNS over HTTPS (DoH) and DNS-over-TLS (DoT) proxy","archived":false,"fork":false,"pushed_at":"2026-04-10T01:43:15.000Z","size":1556,"stargazers_count":1,"open_issues_count":1,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-10T03:23:49.766Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/FaserF.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-12-15T23:07:44.000Z","updated_at":"2026-04-10T01:43:19.000Z","dependencies_parsed_at":"2026-03-25T18:00:42.172Z","dependency_job_id":null,"html_url":"https://github.com/FaserF/ShieldDNS","commit_stats":null,"previous_names":["faserf/shielddns"],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/FaserF/ShieldDNS","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FaserF%2FShieldDNS","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FaserF%2FShieldDNS/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FaserF%2FShieldDNS/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FaserF%2FShieldDNS/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/FaserF","download_url":"https://codeload.github.com/FaserF/ShieldDNS/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FaserF%2FShieldDNS/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31795334,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-14T11:13:53.975Z","status":"ssl_error","status_checked_at":"2026-04-14T11:13:53.299Z","response_time":153,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-03-07T04:13:33.130Z","updated_at":"2026-04-14T12:01:31.113Z","avatar_url":"https://github.com/FaserF.png","language":"Go","funding_links":["https://github.com/sponsors/FaserF)","https://paypal.me/FaserF"],"categories":[],"sub_categories":[],"readme":"\u003cimg src=\"www/logo.png\" align=\"right\" width=\"128\" height=\"128\"\u003e\n\n# ShieldDNS 🛡️\n\n**ShieldDNS** is a high-performance, hardened, privacy-focused DNS solution supporting **DNS-over-TLS (DoT)**, **DNS-over-HTTPS (DoH)**, **DNS-over-QUIC (DoQ)** and standard DNS.\n\nIt features a premium **Admin Dashboard** with persistent SQLite-backed analytics, custom rule management, and a powerful **Filtering Engine** compatible with AdGuard, Pi-hole, and uBlock origin lists.\n\n## 🚀 Key Features\n\n- 🔒 **Secure DNS**: Native support for **DNS-over-TLS (DoT)** (port 853), **DNS-over-HTTPS (DoH)** (port 443), and **DNS-over-QUIC (DoQ)** — zero extra setup needed.\n- 📊 **Persistent Analytics**: SQLite-backed query history and advanced analytics (Top Blocked Domains, Top Clients, Client Aliasing).\n- 🏳️ **Custom Rules**: Instantly allow or block individual domains via the Admin UI. Input is auto-sanitized — paste a full URL if you like!\n- 🛡️ **DNS Filtering**: Integrated engine for blocklists with automatic updates and deduplication.\n- 🔌 **Protection Kill-Switch**: Instantly disable all filtering via the dashboard or API.\n- ⚡ **Optimized Performance**: Intelligent caching, prefetching, and **Serve Stale** support for instant responses even when upstreams are slow.\n- 🔐 **Secure Admin**: Mandatory password protection (bcrypt) for the Admin UI on port 443.\n- 📱 **Modern Protocols**: Perfect for Android Private DNS and standard system-wide filtering (iOS `.mobileconfig` with DoT/DoH/DoQ support).\n- ⚡ **Live Monitoring**: Real-time query log updates via Server-Sent Events (SSE).\n- 🧠 **Smart DNS**: Automatic upstream selection based on live latency (RTT) with **Broadcast Mode** for ultra-low latency.\n- 🌙 **Dark \u0026 Light Mode**: Full theme support, persisted locally per user.\n- 🔄 **Config Backup \u0026 Restore**: One-click backup download and in-browser JSON configuration restore.\n- ⚡ **1-Click Allow / Block**: Directly allow or block any domain from the live Query Log table.\n- 🔍 **Client IP Diagnostics**: Clickable Client IPs in logs with detailed GeoIP, Reverse DNS, and history preview.\n- 🚫 **Client IP Blocking**: Block any client IP from using your DNS server directly from the Client Details view.\n- 🤖 **Abuse Detection Engine**: Automatically detects and blocks clients exhibiting malicious behaviors (e.g., Domain Floods, Rate Limit abuse, NXDOMAIN floods by DGA bots).\n- 🧹 **Optimized Default Lists**: Ships with a single, curated default (HaGeZi Multi Normal) for maximum protection with minimal RAM usage on any hardware.\n\n## ❤️ Support This Project\n\n\u003e I maintain this Project in my **free time alongside my regular job** — bug hunting, new features, and keeping up with OCI updates. Every donation helps me stay independent and dedicate more time to open-source work.\n\u003e\n\u003e **This project is and will always remain 100% free.**\n\u003e\n\u003e Donations are completely voluntary — but the more support I receive, the more time I can realistically invest into these projects. 💪\n\n\u003cdiv align=\"center\"\u003e\n\n[![GitHub Sponsors](https://img.shields.io/badge/Sponsor%20on-GitHub-%23EA4AAA?style=for-the-badge\u0026logo=github-sponsors\u0026logoColor=white)](https://github.com/sponsors/FaserF)\u0026nbsp;\u0026nbsp;\n[![PayPal](https://img.shields.io/badge/Donate%20via-PayPal-%2300457C?style=for-the-badge\u0026logo=paypal\u0026logoColor=white)](https://paypal.me/FaserF)\n\n\u003c/div\u003e\n\n## 🧐 ShieldDNS vs. AdGuard Home vs. Pi-hole\n\nShieldDNS is a modern, lightweight alternative to established solutions like AdGuard Home or Pi-hole. It was built with a focus on performance (CoreDNS-based) and native support for encrypted DNS (DoT/DoH).\n\n### 🛡️ Comparison Table\n\n| Feature | ShieldDNS 🛡️ | AdGuard Home | Pi-hole |\n| :--- | :--- | :--- | :--- |\n| **Base** | CoreDNS (Go) | Cloudflare Go | dnsmasq (C) |\n| **DoT (Port 853)** | Native ✅ | Native ✅ | Requires Unbound ❌ |\n| **DoH (Port 443)** | Native ✅ | Native ✅ | Requires cloudflared ❌ |\n| **DoQ (QUIC)** | Native ✅ | Native ✅ | ❌ |\n| **Performance** | Ultra-High (Go/WAL) | High | Moderate (dnsmasq) |\n| **Analytics** | SQLite (WAL/Batching) | Internal (Local) | FTL (C/Stats) |\n| **Hardening** | AEAD-only Ciphers  | Standard | Upstream Dependent |\n| **Home Assistant** | [HA App Available](https://github.com/FaserF/hassio-addons/tree/master/ShieldDNS) | HA App Available | HA App Available |\n\n### 🛠️ Pros and Cons\n\n#### **ShieldDNS**\n- **Pros**: Incredibly performant thanks to the CoreDNS core; native DoT/DoH/DoQ support; modern security stack; transaction-safe logging via SQLite WAL; real-time SSE updates.\n- **Cons**: Focused feature set designed for efficiency.\n\n#### **AdGuard Home**\n- **Pros**: Very comprehensive user interface; supports DNS-over-QUIC; integrated parental controls.\n- **Cons**: Can be more resource-intensive with many clients; more closed architecture.\n\n#### **Pi-hole**\n- **Pros**: Massive community support; runs on almost any hardware; very detailed statistics.\n- **Cons**: Based on `dnsmasq`; lacks native DoT/DoH support (often requires additional Docker containers like `unbound`).\n\n## 🛠️ Usage\n\n### Docker Compose\n\n```yaml\nservices:\n  shielddns:\n    image: ghcr.io/faserf/shielddns:latest\n    ports:\n      - \"53:53/udp\"      # DNS (UDP)\n      - \"53:53/tcp\"      # DNS (TCP)\n      - \"853:853/tcp\"    # DoT\n      - \"443:443/tcp\"    # Admin Dashboard (HTTPS)\n    environment:\n      - UPSTREAM_DNS=86.54.11.100, 1.1.1.1, 9.9.9.9, 8.8.8.8, 1.0.0.1 # Max 5\n      - UPSTREAM_DOT=unfiltered.joindns4.eu, dns.quad9.net, one.one.one.one # Max 5\n      - PREFER_ENCRYPTED=true\n      - LOG_LEVEL=info\n      - DATA_DIR=/etc/shielddns\n    volumes:\n      - ./ssl:/ssl\n      - ./data:/etc/shielddns # Persistent config, database, and lists\n```\n\n### 🐋 Standard Docker\nIf you prefer the command line, use the following to build and run with persistence:\n```bash\ndocker build -t shielddns:local .\ndocker run -d \\\n  --name shielddns \\\n  -p 53:53/udp -p 53:53/tcp \\\n  -p 443:443/tcp -p 853:853/tcp \\\n  -v $(pwd)/data:/etc/shielddns \\\n  -v $(pwd)/ssl:/ssl \\\n  shielddns:local\n```\n\n### 💾 Persistent Storage\nTo ensure your configuration, query logs, and SSL certificates are saved across container updates and restarts, you **must** mount the following directories:\n- `/etc/shielddns` (Config, SQLite Database, Blocklists)\n- `/ssl` (Your certificates, or where ShieldDNS generates fallback ones)\n\n## 🛠️ Troubleshooting\n\n### Port 53 already in use\nOn many Linux systems (like Ubuntu), `systemd-resolved` uses port 53 by default. To use ShieldDNS, you must disable the stub listener on your host:\n\n1. Edit `/etc/systemd/resolved.conf` and set `DNSStubListener=no`.\n2. Run `sudo ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf`.\n3. Restart the service: `sudo systemctl restart systemd-resolved`.\n\n### Oracle Cloud VM (OCI) - Ubuntu 24.04\nOracle Cloud VMs have multiple layers of firewalls. For 2026, the recommended approach is as follows:\n\n1. **OCI Console**: Use the search bar to find **Network Security Groups**. Add ingress rules for UDP 53 and TCP 53, 443, 853.\n2. **Host Firewall (iptables)**:\n```bash\nsudo iptables -I INPUT -p udp --dport 53 -j ACCEPT\nsudo iptables -I INPUT -p tcp -m multiport --dports 53,443,853 -j ACCEPT\nsudo netfilter-persistent save\n```\n\n## 🔐 API Key Management \u0026 RBAC\n\nShieldDNS includes a secure, granular API key system for remote monitoring and automation (e.g., Home Assistant integration).\n\n### Authentication\nAuthenticate by sending your API key in the `X-API-Key` header or as a `Bearer` token in the `Authorization` header.\n\n### Permissions (RBAC)\nShieldDNS uses a Role-Based Access Control model. Tokens can be restricted to:\n- `read:stats`: Dashboard metrics and analytics history.\n- `read:logs`: Sensitive data including Query Logs and Client IPs.\n- `read:system`: System terminal logs, SSL diagnostics, and backups.\n- `write:filtering`: Toggle the global protection/filtering engine.\n- `read:all`: Grant all read-only permissions above.\n\n### Health Endpoints\n- `/api/health/live`: Public endpoint for container liveness checks (No authentication required).\n- `/api/health/ready`: System readiness check (Requires `read:system` permission).\n\n\u003e [!IMPORTANT]\n\u003e **Security Guard Policy**: If no API keys are defined in the Settings, all token-based authentication attempts are rejected by default.\n\n## 🖥️ Admin Dashboard\n\nAccess the dashboard at `https://your.domain/`.\n\n### 🛡️ Setup Wizard\nOn your first visit, a multi-step setup wizard will guide you through:\n1.  **Security**: Setting a strong administrative password (hashed with bcrypt).\n2.  **Upstream DNS**: Selecting your preferred DoT and standard DNS providers.\n3.  **Protection**: Choosing from a curated catalog of industry-standard blocklists.\n\n### 📊 Advanced Analytics\nShieldDNS now stores your query history in a persistent SQLite database:\n- **Query History**: View the last 100 queries or search through historical data.\n- **Top Blocked Domains**: identify the most aggressive trackers on your network.\n- **Top Clients**: See which devices are generating the most traffic.\n- **Client Aliasing**: Assign friendly names to IPs for easier identification across all views.\n- **Hourly Trends**: 24-hour traffic visualization shows you exactly when your network is most active.\n- **Live Logs**: Zero-latency query streaming via Server-Sent Events (SSE).\n- **Client IP Diagnostics**: Interactive query logs where clicking an IP reveals GeoIP location, Reverse DNS hostname, and a client-specific query history preview.\n- **Cache Hit Ratio \u0026 Upstream Performance**: Real-time diagnostic trackers showing local cache efficiency and a live upstream latency chart.\n\n### 🚫 Client IP Blocking\n\nShieldDNS allows you to permanently block any individual client IP address from using your DNS server — directly from the Admin UI, without editing any configuration files.\n\n**How it works:**\n1. In the **Query Log** or **Top Clients** view, click on any client IP to open the **Client Details** modal.\n2. In the modal header, click **🚫 Block Client** to immediately prevent that IP from receiving DNS responses.\n3. The IP is added to the `blocked_clients` list in your configuration and takes effect instantly via a CoreDNS ACL rule update.\n4. To reverse the action, re-open the same Client Details modal and click **✅ Unblock Client**.\n\n**Technical details:**\n- Blocked IPs are stored in `config.json` under `blocked_clients` and survive container restarts.\n- The `blocked_clients_info` field tracks the exact timestamp and context (e.g., manual vs auto-blocked).\n- Enforcement is handled by CoreDNS's built-in `acl` plugin using `block net \u003cIP\u003e` directives.\n- Multiple blocked IPs are combined into a single ACL block, so there is no performance penalty.\n- Blocking is applied across all protocols simultaneously (DNS/TCP, DoT, DoH, DoQ).\n\n### 🤖 Abuse Detection Engine (Auto-Blocking)\n\nShieldDNS monitors traffic in real-time to detect anomalous patterns and automatically blocks misbehaving clients or bots. This protects your DNS server from being used in amplification attacks or being overwhelmed by infected devices.\n\n**How it works:**\nThe engine uses sliding-window tracking in-memory (cleaned up efficiently via background routines) to measure traffic against four thresholds:\n1. **Domain Flood**: A single client requests the exact same domain ≥ 120 times in 60 seconds (`auto:domain_flood`).\n2. **Rate Limit**: A single client requests ≥ 1000 total DNS queries in 60 seconds (`auto:rate_limit`).\n3. **NXDOMAIN Flood (DGA Bots)**: A client triggers ≥ 300 NXDOMAIN (Domain Not Found) responses in 60 seconds, indicative of malware searching for randomized domains (`auto:nxdomain_flood`).\n4. **TLD Scan**: A client heavily queries a single uncommon Top Level Domain (e.g., ≥ 1000 requests in 5 minutes, representing ≥ 90% of their total traffic) (`auto:tld_scan`).\n\nWhen a threshold is exceeded, the client IP is instantly blocked, and a warning badge (e.g., `Automatically blocked: auto:domain_flood`) will appear in the **Client Details** UI. \n\n*This feature is **ON** by default but can be disabled via the Settings toggle.*\n\n### 🏳️ Custom Rules\nImmediately take control of your network without managing external lists:\n- **Custom Blocklist**: Instantly block any domain (e.g., `tiktok.com`). Paste a full URL — it's auto-sanitized to a clean domain.\n- **Custom Allowlist**: Ensure critical domains are never blocked.\n- **1-Click Allow/Block**: Act on any domain directly from the live Query Log without copy-pasting.\n\n### ⚡ Optimization \u0026 Health\n- **Intelligent Caching**: Large 10k entry cache reduces upstream lookups.\n- **IP Info Caching**: In-memory caching for GeoIP and Reverse DNS lookups (cached for 24h) to ensure zero-latency UI interaction.\n- **Prefetching**: ShieldDNS proactively refreshes popular records before they expire.\n- **Upstream Probing**: Background health checks every 30 seconds ensure you only use healthy upstreams.\n- **Smart Selection**: Optionally reorder upstreams dynamically to always use the lowest-latency provider.\n- **Data Retention \u0026 Maintenance**: Configurable history purging (e.g., 7, 30, 90 days) augmented with automated background SQL VACUUM tasks to maintain database performance and optimize disk space.\n- **System Backups**: One-click `.zip` backup of configuration and query history.\n- **Config Restore**: Upload a `config.json` directly from the Settings page to instantly restore a previous configuration.\n- **Dark \u0026 Light Mode**: Toggle the UI theme — preference is saved locally.\n- **Optimized Default Lists**: Ships with a single curated default (HaGeZi Multi Normal). Avoids enabling multiple overlapping lists (e.g., OISD + HaGeZi + AdGuard) by default, which would triple RAM usage with near-zero added coverage.\n- **Streaming Blocklist Downloader**: Lists are processed line-by-line via streaming (not loaded fully into RAM) — critical for low-memory hardware like Raspberry Pi 3/4.\n- **Structured Log Parsing**: Uses CoreDNS structured log format for robust, format-change-resistant query parsing.\n\n\n## 📱 Client Configuration\n\n### DoT (DNS-over-TLS) \u0026 DoQ (DNS-over-QUIC) - Port 853\n- **Android**: Scan the QR code on the public landing page, or manually go to **Settings \u003e Network \u003e Private DNS** and enter your domain (e.g., `dns.example.com`). Modern Android versions will automatically attempt DoT first. For DoQ, use a supporting app like *Nebulo* or *Personal DNS Filter*.\n- **iOS/macOS**: Download the `.mobileconfig` from your ShieldDNS dashboard. It implements both DoT and DoH. For native DoQ, ensure you are on iOS 17+.\n\n### ⚡ Setup DNS-over-QUIC (DoQ)\nDNS-over-QUIC is the fastest encrypted protocol as it eliminates TCP head-of-line blocking by using UDP/443. ShieldDNS supports it natively on **port 853 (UDP)**.\n\n#### **Android (Advanced)**\nStandard \"Private DNS\" uses DoT. To use **DoQ** for superior performance on mobile data:\n1.  **Install**: [Google Intra](https://play.google.com/store/apps/details?id=app.intra) or [AdGuard for Android](https://adguard.com/).\n2.  **Configure**: In the app settings, add a custom server using the QUIC scheme:\n    `quic://your.domain:853`\n\n#### **iOS 17+ (Native)**\nFor native DoQ support on modern iPhones:\n1.  Ensure **Port 853 (UDP)** is open in your firewall.\n2.  **App Approach**: Use [DNSecure](https://apps.apple.com/app/dnsecure/id1531065103). Add a \"DNS-over-QUIC\" configuration and enter your domain.\n3.  **Profile Approach**: The `.mobileconfig` generated by ShieldDNS includes a DoQ payload. If you are on iOS 17+, it will automatically be available in **Settings \u003e VPN \u0026 Device Management \u003e DNS**.\n\n#### **Desktop (AdGuard Home/CoreDNS)**\nIf using ShieldDNS as an upstream for another server:\n`quic://your.domain:853`\n\n### OpenWrt Integration (Best Practices)\nIf you host ShieldDNS publicly and want to route your entire home network through it via an OpenWrt router, follow these steps:\n\n#### 1. Configure DNS Forwarding\nNavigate to **Network \u003e DHCP and DNS** in LuCI:\n- **DNS forwardings**: Enter the IP of your ShieldDNS server (e.g., `94.31.75.54`).\n- **Fallback**: Add a secondary DNS server (e.g., `1.1.1.1`) as a second entry.\n- **Strict Order**: (Optional) In the **Advanced Settings** tab, check `Strict Order` to ensure ShieldDNS is always tried first.\n\n#### 2. Enforce ShieldDNS (DNS Hijacking)\nTo prevent devices from bypassing ShieldDNS by using hardcoded DNS servers (like 8.8.8.8), add a NAT rule under **Network \u003e Firewall \u003e Traffic Rules \u003e DNAT**:\n- **Protocol**: `UDP`, `TCP`\n- **Source zone**: `lan`\n- **Destination port**: `53`\n- **Action**: `DNAT`\n- **Rewrite IP**: (Select your router's LAN IP)\n- **Rewrite port**: `53`\n\nThis forces all DNS traffic on your network to go through the router's DNSmasq, which then forwards it to ShieldDNS.\n\n## 🛡️ Technical Hardening\nShieldDNS is built for extreme reliability in production environments:\n1.  **Graceful Shutdown**: SIGTERM/SIGINT handling ensures all buffered logs are flushed to SQLite and connections are closed safely, preventing data corruption.\n2.  **IPv6 Robustness**: Native support for IPv6 client IP extraction using `net.SplitHostPort`.\n3.  **Brute-Force Protection**: Intelligent rate-limiting on the `/api/login` endpoint (max 5 attempts/min/IP).\n4.  **Modern TLS**: Enforced AEAD-only cipher suites (TLS 1.2/1.3) for all management and DNS-over-TLS endpoints.\n\n## 🛡️ Security Best Practices\n1.  **Password**: Use a strong, unique password for the Admin UI.\n2.  **Certificates**: Use valid Let's Encrypt certificates for both DoT and the Admin UI.\n3.  **Firewall**: Only expose ports 53, 443, and 853.\n\n## 📋 Blocklist Recommendations\n\nThe preset catalog is organized by category. For most home users, the following configuration offers the best balance of protection vs. compatibility:\n\n| Scenario | Recommended Lists |\n| :--- | :--- |\n| **Minimal (fast, few false positives)** | HaGeZi Multi (Light) |\n| **Balanced (recommended default ✅)** | HaGeZi Multi (Normal) |\n| **Max Protection** | HaGeZi Multi (Pro) + HaGeZi TIF |\n| **+ Malware/Phishing** | + HaGeZi TIF (Threat Intelligence) |\n| **+ Adult Content Blocking** | + OISD NSFW |\n| **+ Regional (German)** | + KADhost (German Blocklist) |\n\n\u003e [!WARNING]\n\u003e **Avoid enabling multiple large lists in the same category at once** (e.g., HaGeZi Normal + OISD Full + AdGuard Main). These lists overlap heavily — using all three triples your RAM consumption without adding meaningful coverage.\n\n\u003e [!TIP]\n\u003e **UI Feedback**: When lists are downloading, real-time progress entries appear in the **System Logs** tab. On first setup with many large lists, the dashboard may take 1–2 minutes to populate blocklist data — this is normal.\n\n## 🧪 Testing Your Setup\n\nTo verify that your devices are correctly using ShieldDNS and that filtering is active, you can visit the following built-in test URL in your browser:\n\n👉 **[http://shielddns-maleware.test](http://shielddns-maleware.test)**\n\nThis test domain is permanently blocked at the system level regardless of which blocklists you have enabled. If ShieldDNS is working correctly, you will see the official ShieldDNS \"Website Blocked\" page.\n\n\u003e [!NOTE]\n\u003e For the block page to be reachable by network clients, you must set the **Block Page IP** to your ShieldDNS server's actual IP address in the **Settings** or via the `BLOCK_PAGE_IP` environment variable.\n\n## 💻 Development \u0026 Testing\n\nShieldDNS uses Go's standard `testing` package with a fully in-memory test environment (no Docker required).\n\n```bash\n# Run all tests\ncd admin\ngo test ./... -v\n\n# Run a specific test\ngo test ./... -run TestProcessList_StreamingMemoryEfficiency -v\n```\n\n### Test Coverage\n\n| Area | Test File | What's Covered |\n| :--- | :--- | :--- |\n| Blocklist streaming parser | `config_test.go` | AdBlock/hosts/dnsmasq/allowlist formats, streaming line-by-line download |\n| CoreDNS log parser | `dns_test.go` | Structured log format, blocked detection, SSE broadcast, latency parsing |\n| API handlers | `main_test.go`, `api_test.go` | Stats, search, history, auth, token management |\n| Client IP Blocking | `client_block_test.go` | Block/unblock lifecycle, idempotency, config preservation, ACL rule generation |\n| Upstream health \u0026 smart sorting | `main_test.go` | Latency-based upstream ordering, Corefile generation |\n| Presets integrity | `presets_test.go` | Default preset list availability |\n\n## 🏠 Home Assistant Integration\n\n\nShieldDNS has full first-class Home Assistant support:\n\n- **Official HA Addon** (run ShieldDNS directly inside Home Assistant with Ingress support):\n  👉 [hassio-addons / ShieldDNS](https://github.com/FaserF/hassio-addons/tree/master/ShieldDNS)\n\n- **Official HA Integration** (expose ShieldDNS stats and controls as sensors/services in Home Assistant):\n  👉 [ha-shielddns](https://github.com/FaserF/ha-shielddns)\n\n## 🙏 Acknowledgements\n\nShieldDNS stands on the shoulders of giants. We would like to express our profound gratitude to the following projects:\n\n- **[CoreDNS](https://coredns.io/)**: The incredibly fast, flexible, and robust CNCF-hosted DNS server that powers the core naming resolution engine of ShieldDNS.\n- **[AdGuard Home](https://github.com/AdguardTeam/AdGuardHome)** \u0026 **[Pi-hole](https://pi-hole.net/)**: The trailblazers in network-wide ad-blocking. Their pioneering ideas, standard-setting filter list syntax, and community-driven approach deeply inspired the development and feature-set of ShieldDNS.\n\n## 📄 License\n\n**ShieldDNS** is released under the **[ShieldDNS Personal \u0026 Internal Commercial License](LICENSE)**.\n\n✅ **Allowed (Free)**:\n- Personal and home usage.\n- Internal business/company usage to protect your own networks or employees.\n\n❌ **Prohibited (Without Permission)**:\n- Commercial hosted services (e.g., offering ShieldDNS as a paid cloud service or SaaS).\n- Reselling the software or packaging it into a commercial product for profit.\n\nFor the full legal text, please review the [LICENSE](LICENSE) file.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffaserf%2Fshielddns","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffaserf%2Fshielddns","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffaserf%2Fshielddns/lists"}