dns-switch
Production-ready DNS management with security and portability. A self-contained, portable DNS management tool with comprehensive security, health checking, and remote discovery capabilities.
File Information
| Property | Value |
|---|---|
| Binary Name | dns-switch |
| Version | 9.8.4 (build 320) |
| Build Date | Not disclosed |
| Rust Version | Not disclosed |
| File Size | 10.8MB |
| Author | Warith Al Maawali |
| License | Proprietary |
| Category | Kodachi Binary |
| Description | Production-ready DNS management with security and portability. A self-contained, portable DNS management tool with compr... |
| Git Commit | unknown |
| Metadata Generated | 2026-08-10T13:22:47Z |
| Binary Timestamp | Unknown |
| JSON Data | View Raw JSON |
SHA256 Checksum
ed67bacef19db2414f43662042a060bc0a85fbd92b37545766eaa158b79cd9b3
Features
| # | Feature |
|---|---|
| 1 | Embedded DNS server lists (no external config dependencies) |
| 2 | Dynamic path detection (works in any directory) |
| 3 | Comprehensive input validation and sanitization |
| 4 | JSON output support for automation |
| 5 | Health monitoring and performance testing |
| 6 | Remote DNS server discovery and testing |
| 7 | Security-focused design with privilege checking |
| 8 | DNSCrypt proxy integration |
| 9 | Pi-hole DNS filter integration |
| 10 | Automatic backup and restore capabilities |
Security Features
| Feature | Description |
|---|---|
| Authentication | Integrated with Kodachi authentication system |
| Encryption | Supports DNSCrypt for encrypted DNS queries |
| Input Validation | All inputs sanitized and validated before use |
| Rate Limiting | Built-in rate limiting for remote operations |
System Requirements
| Requirement | Value |
|---|---|
| OS | Linux (Debian-based) |
| Privileges | root/sudo for system changes |
| Dependencies | systemd-resolved or resolvconf, DNSCrypt proxy (optional), Pi-hole (optional) |
Global Options
| Flag | Description |
|---|---|
-h, --help |
Print help information |
-v, --version |
Print version information |
-n, --info |
Display detailed information |
-e, --examples |
Show usage examples |
--json |
Output in JSON format |
-o, --output-format <FORMAT> |
Force output format (text|json) |
--verbose |
Enable verbose output |
--quiet |
Suppress non-essential output |
--no-color |
Disable colored output |
--timeout <SECS> |
Set timeout (default: 30) |
--config <FILE> |
Use custom configuration file |
--json-pretty |
Pretty-print JSON output |
--json-human |
Enhanced JSON output with improved formatting (like jq) |
--fields <FIELDS> |
Select specific fields to include |
--limit <NUMBER> |
Limit number of results |
--offset <NUMBER> |
Skip first N results |
--work-dir <DIR> |
Specify working directory |
--no-action |
Dry run mode |
--log-level <LEVEL> |
Set logging verbosity (error|warn|info|debug|trace) |
Commands
DNS Management
switch
Switch DNS to a specific category or provider
Usage:
dns-switch switch [OPTIONS]
Options:
--category <CATEGORY>: DNS category: reputable, normal, fallback or remotely_fetched. The parser recognizes 'encrypted' and 'all', but switch rejects them before changing DNS; use 'dnscrypt-set' for encrypted DNS, or --names dnscrypt for the supported alias path--names <NAMES>: Switch DNS by server names (e.g., cloudflare, adguard)--servers <IPS>: Switch DNS by server IP addresses--verify: Health-check each server and apply only the ones that answer--no-action: Dry run: print the servers that would be applied and change nothing (also drops the root requirement)--json: Machine-readable output
Examples:
sudo dns-switch switch --category reputable
sudo dns-switch switch --names cloudflare adguard
sudo dns-switch switch --servers 1.1.1.1 9.9.9.9
sudo dns-switch switch --category reputable --verify
dns-switch switch --names cloudflare --no-action
random
Switch to random DNS servers with advanced selection
Usage:
dns-switch random [OPTIONS]
Options:
--type <TYPE>: Type of DNS servers: reputable, normal, remotely_fetched, all, or a comma-separated mix of the first three. NOTE: 'encrypted', 'fallback', 'failed' and 'both' are NOT usable here: encrypted servers are configured with dnscrypt-set, fallback uses the embedded pool via 'dns-switch fallback', failed servers are excluded by design--count <COUNT>: Number of random DNS servers to select. Ignored when --type all is used (that always takes 3 per category, up to 9)--verify: Health-check the picked servers and apply only the ones that answer--no-action: Dry run: print the servers that would be applied and change nothing (also drops the root requirement)
Examples:
sudo dns-switch random
sudo dns-switch random --type reputable --verify
sudo dns-switch random --type all
sudo dns-switch random --type reputable,normal --count 6
dns-switch random --type normal --count 5 --no-action
fallback
Switch to the embedded emergency fallback DNS servers. Applies immediately: this command has NO dry run (--no-action is ignored)
Usage:
dns-switch fallback
Options:
--json: Machine-readable output
Examples:
sudo dns-switch fallback
sudo dns-switch fallback --json
status
Show current DNS configuration
Usage:
dns-switch status
Options:
--json: Machine-readable output (add --json-pretty or --json-human to format it)
Examples:
dns-switch status
dns-switch status --json
DNS Mode Management
get-mode
Show current DNS management mode (modern vs legacy)
Usage:
dns-switch get-mode
Options:
--json: Machine-readable output
Examples:
dns-switch get-mode
dns-switch get-mode --json
set-mode
Set DNS management mode (modern=systemd-resolved, legacy=/etc/resolv.conf)
Usage:
dns-switch set-mode --mode <modern|legacy>
Options:
--mode <MODE>: DNS mode: 'modern' (systemd-resolved) or 'legacy' (/etc/resolv.conf)
Examples:
sudo dns-switch set-mode --mode modern # Switch to systemd-resolved
sudo dns-switch set-mode --mode legacy # Switch to legacy /etc/resolv.conf
detect-mode
Auto-detect recommended DNS mode for this system
Usage:
dns-switch detect-mode
Options:
--json: Machine-readable output
Examples:
dns-switch detect-mode
dns-switch detect-mode --json
fix-dns
Repair broken DNS configuration: mode mismatches, broken symlinks, corrupted files, then applies fallback DNS servers to restore connectivity. Also accepts the legacy alias 'dns-fix'
Usage:
dns-switch fix-dns
Options:
--force: Run all repair stages even if DNS appears healthy
Examples:
sudo dns-switch fix-dns
sudo dns-switch fix-dns --force
sudo dns-switch dns-fix
get-modern-method
Show which method systemd-resolved uses (global / per-interface / networkmanager / auto)
Usage:
dns-switch get-modern-method
Options:
--json: Machine-readable output
Examples:
dns-switch get-modern-method
dns-switch get-modern-method --json
set-modern-method
Set systemd-resolved DNS application method (only relevant in modern mode)
Usage:
dns-switch set-modern-method --method <global|per-interface|networkmanager|auto>
Options:
--method <METHOD>: global (resolved.conf, safest), per-interface (resolvectl), networkmanager (nmcli), or auto
Examples:
sudo dns-switch set-modern-method --method global
sudo dns-switch set-modern-method --method auto
external-dns
Hand DNS management to a third-party VPN GUI (Mullvad, ProtonVPN, etc.) or take it back. Kodachi normally locks /etc/resolv.conf immutable for DNS-leak protection, which stops those clients from setting their tunnel DNS, so they fail with 'internet blocked' / 'failed to set system DNS'. Turn this ON before connecting such a client, OFF to restore Kodachi-managed DNS. WARNING: while ON, Kodachi's immutable DNS-leak lock is paused and your VPN client must enforce its own leak protection (Mullvad and ProtonVPN do). Clients that strictly require systemd-resolved may still not work; switch to modern mode with 'set-mode --mode modern' for those
Usage:
dns-switch external-dns --state <on|off|status>
Options:
--state <STATE>: on = unlock resolv.conf + pause Kodachi DNS protection so a VPN GUI can manage DNS; off = re-lock and return DNS to Kodachi; status = show current mode (read-only, no sudo)
Examples:
sudo dns-switch external-dns --state on
sudo dns-switch external-dns --state off
dns-switch external-dns --state status
Health & Discovery
health
Check health of DNS servers with detailed analysis (read-only by default)
Usage:
dns-switch health [OPTIONS]
Options:
--type <TYPE>: Test a specific category: reputable, normal, encrypted, fallback, remotely_fetched, failed, or all ('both' is deprecated and rejected)--full: Perform comprehensive health check--fresh: Force fresh health check, bypassing cache--save: Save health check results to database (default: read-only, no database changes)--force-move: BYPASS 3-strike rule: move failed servers to 'failed' category IMMEDIATELY (requires --save). Use for urgent cleanup or known-bad servers
Examples:
dns-switch health
dns-switch health --type reputable
dns-switch health --type all
dns-switch health --type reputable --save
dns-switch health --full --save
dns-switch health --fresh --save --json
fetch
Fetch and test remote DNS servers with advanced options
Usage:
dns-switch fetch [OPTIONS]
Options:
--all: Fetch all available DNS servers (instead of default 25)--count <NUM>: Specify number of DNS servers to fetch--fresh: Force fresh data retrieval, bypassing all caches--history: Show fetch history--load <CACHE_ID>: Load cached results
Examples:
dns-switch fetch
dns-switch fetch --count 100
dns-switch fetch --all
dns-switch fetch --fresh --json
fetch-count
Fetch a specific number of DNS servers from remote sources. This command reads --fetch-count ONLY: a --count passed here is silently ignored and you get the default 25
Usage:
dns-switch fetch-count --fetch-count <NUM>
Options:
--fetch-count <NUM>: Number of DNS servers to fetch (this command does NOT read --count)--fresh: Force fresh data retrieval, bypassing caches--json: Machine-readable output
Examples:
dns-switch fetch-count
dns-switch fetch-count --fetch-count 50
dns-switch fetch-count --fetch-count 100 --fresh
dns-switch fetch-count --fetch-count 35 --json
fetch-dns-from-card
Pull DNSCrypt and Tor DNS servers from your authenticated Kodachi card into the local DB (encrypted category). Requires a valid online-auth session: run 'online-auth authenticate' first
Usage:
dns-switch fetch-dns-from-card
Options:
--json: Machine-readable output
Examples:
dns-switch fetch-dns-from-card
dns-switch fetch-dns-from-card --json
DNSCrypt Management
dnscrypt
Show DNSCrypt status (read-only: it changes nothing, so --no-action does nothing here)
Usage:
dns-switch dnscrypt
Options:
--json: Machine-readable output
Examples:
dns-switch dnscrypt
dns-switch dnscrypt --json
dnscrypt-set
Enable DNSCrypt with specific resolver
Usage:
dns-switch dnscrypt-set --resolver <NAME>
Options:
--resolver <NAME>: DNSCrypt resolver name--no-action: Dry run: show the DNSCrypt configuration that would be written and change nothing
Examples:
sudo dns-switch dnscrypt-set --resolver cloudflare
dns-switch dnscrypt-set --resolver cloudflare --no-action
dnscrypt-restart
Restart DNSCrypt proxy
Usage:
dns-switch dnscrypt-restart
Options:
--json: Machine-readable output
Examples:
sudo dns-switch dnscrypt-restart
dnscrypt-remove
Remove DNSCrypt configuration
Usage:
dns-switch dnscrypt-remove
Options:
--json: Machine-readable output
Examples:
sudo dns-switch dnscrypt-remove
dnscrypt-monitor-status
Show whether the DNSCrypt auto-recovery monitor timer is active
Usage:
dns-switch dnscrypt-monitor-status
Options:
--json: Machine-readable output
Examples:
dns-switch dnscrypt-monitor-status
dnscrypt-monitor-check
Run a single monitor check now (used by the timer; safe to invoke manually)
Usage:
dns-switch dnscrypt-monitor-check
Options:
--json: Machine-readable output
Examples:
sudo dns-switch dnscrypt-monitor-check
enable-dnscrypt-monitor
Install and enable the systemd timer that auto-recovers DNSCrypt and falls back to safe DNS on failure
Usage:
dns-switch enable-dnscrypt-monitor
Options:
--json: Machine-readable output
Examples:
sudo dns-switch enable-dnscrypt-monitor
disable-dnscrypt-monitor
Disable and remove the DNSCrypt auto-recovery timer
Usage:
dns-switch disable-dnscrypt-monitor
Options:
--json: Machine-readable output
Examples:
sudo dns-switch disable-dnscrypt-monitor
dnssec-on
Enable DNSSEC signature validation (require_dnssec=true) in dnscrypt-proxy.toml and restart dnscrypt-proxy. Earns +0.1 dns_privacy score
Usage:
dns-switch dnssec-on
Options:
--json: Machine-readable output
Examples:
sudo dns-switch dnssec-on
dnssec-off
Disable DNSSEC validation (require_dnssec=false, default state) in dnscrypt-proxy.toml and restart dnscrypt-proxy
Usage:
dns-switch dnssec-off
Options:
--json: Machine-readable output
Examples:
sudo dns-switch dnssec-off
dot-on
Enable DNS-over-HTTPS (doh_servers=true) in dnscrypt-proxy.toml and restart dnscrypt-proxy. The legacy command name says 'dot', but this configures DoH, not DNS-over-TLS. Earns +0.2 dns_privacy score
Usage:
dns-switch dot-on
Options:
--json: Machine-readable output
Examples:
sudo dns-switch dot-on
dot-off
Disable DoH (doh_servers=false) in dnscrypt-proxy.toml; dnscrypt-proxy reverts to DNSCrypt-only protocol and restarts
Usage:
dns-switch dot-off
Options:
--json: Machine-readable output
Examples:
sudo dns-switch dot-off
Boot & Leak Protection
boot-check
One-shot DNS health probe (used at boot to detect and repair empty or broken nameservers). Read-only while DNS is healthy, but it rewrites /etc/resolv.conf with fallback servers when it finds none, so run it with sudo
Usage:
dns-switch boot-check
Options:
--json: Machine-readable output
Examples:
sudo dns-switch boot-check
sudo dns-switch boot-check --json
enable-boot-check
Install the systemd service that runs boot-check on every boot (requires auth)
Usage:
dns-switch enable-boot-check
Options:
--json: Machine-readable output
Examples:
sudo dns-switch enable-boot-check
disable-boot-check
Remove the boot-time DNS validation systemd service (requires auth)
Usage:
dns-switch disable-boot-check
Options:
--json: Machine-readable output
Examples:
sudo dns-switch disable-boot-check
verify-no-leaks
Report any interface with DNS servers different from the expected system DNS (per-interface leak detection)
Usage:
dns-switch verify-no-leaks
Options:
--json: Machine-readable output with the leaking interfaces listed
Examples:
dns-switch verify-no-leaks
dns-switch verify-no-leaks --json
Pi-hole Integration
pihole
Show Pi-hole status
Usage:
dns-switch pihole
Options:
--json: Machine-readable output
Examples:
dns-switch pihole
dns-switch pihole --json
pihole-enable
Enable Pi-hole DNS filtering
Usage:
dns-switch pihole-enable
Options:
--json: Machine-readable output
Examples:
sudo dns-switch pihole-enable
pihole-disable
Disable Pi-hole DNS filtering
Usage:
dns-switch pihole-disable
Options:
--json: Machine-readable output
Examples:
sudo dns-switch pihole-disable
pihole-password
Set Pi-hole web interface password. The TOML file is unprotected and re-protected automatically; to change it by hand instead, run 'sudo chattr -i /etc/pihole/pihole.toml' first
Usage:
dns-switch pihole-password --password <PASSWORD>
Options:
--password <PASSWORD>: New password for Pi-hole web interface (TOML file auto-unprotected)
Examples:
sudo dns-switch pihole-password --password MyNewPassword
pihole-reset
Reset Pi-hole configuration
Usage:
dns-switch pihole-reset
Options:
--json: Machine-readable output
Examples:
sudo dns-switch pihole-reset
Information & Utilities
list
List available DNS servers
Usage:
dns-switch list --category <CATEGORY>
Options:
--category <CATEGORY>: Category to list: reputable, normal, encrypted, fallback or all. NOTE: 'remotely_fetched' is NOT a valid value here and is rejected--type <TYPE>: Alias for --category with two extra aliases: privacy (means encrypted) and security (means reputable)
Examples:
dns-switch list --category reputable
dns-switch list --category encrypted
dns-switch list --category all --json
dns-switch list --type privacy
help
Print this help (the positional form of --help). Use '<action> --help' for a single action
Usage:
dns-switch help
Options:
--json: Machine-readable help, used by the dashboard and the docs catalog
Examples:
dns-switch help
dns-switch switch --help
dns-switch --help --json
count
Count DNS servers by category
Usage:
dns-switch count
Options:
--json: Machine-readable output
Examples:
dns-switch count
dns-switch count --json
Maintenance & Recovery
clean
Clean temporary files and cache
Usage:
dns-switch clean
Options:
--no-action: Dry run: list the temporary files that would be removed--json: Machine-readable output
Examples:
dns-switch clean
dns-switch clean --no-action
clean-duplicates
Remove duplicate DNS entries from the local database. Applies immediately: --no-action is ignored by this command
Usage:
dns-switch clean-duplicates
Options:
--json: Machine-readable output with the removed-duplicate count
Examples:
dns-switch clean-duplicates
dns-switch clean-duplicates --json
flush-cache
Flush systemd-resolved and nscd DNS caches to clear stale entries. Runs as your own user: resolvectl needs no root and the nscd step uses a non-interactive 'sudo -n' that is skipped when it is not available
Usage:
dns-switch flush-cache
Options:
--json: Machine-readable output listing which caches were flushed
Examples:
dns-switch flush-cache
dns-switch flush-cache --json
backup
Create a timestamped backup of the dns-switch server database (not /etc/resolv.conf)
Usage:
dns-switch backup
Options:
--json: Machine-readable output with the backup file path
Examples:
dns-switch backup
dns-switch backup --json
restore-default
Reset the DNS server database to factory defaults and apply the default DNS. DESTRUCTIVE: custom entries and health history in the database are discarded
Usage:
dns-switch restore-default
Options:
--no-action: Dry run: show what would be restored and change nothing--json: Machine-readable output
Examples:
dns-switch restore-default --no-action
sudo dns-switch restore-default
restore-backup
Restore the DNS server database from a backup (defaults to the most recent one). DESTRUCTIVE and immediate: it overwrites the current database and has NO dry run (--no-action is ignored)
Usage:
dns-switch restore-backup [--file <FILE>]
Options:
--file <FILE>: Backup file to restore (path may not contain '..')--json: Machine-readable output
Examples:
sudo dns-switch restore-backup
sudo dns-switch restore-backup --file backup.json
Operational Scenarios
Scenario-oriented workflows generated from the binary's built-in -e --json examples.
Scenario 1: Quick Start
The handful of commands that cover a normal day: see what DNS you are on, switch it, prove it did not leak.
Step 1: See which DNS servers the system is using right now
dns-switch status
Step 2: Move the system onto trusted DNS servers
sudo dns-switch switch --category reputable
Note
Needs root because it rewrites the system resolver configuration.
Step 3: Confirm no interface is quietly using different DNS servers
dns-switch verify-no-leaks
Step 4: Repair DNS when name resolution is broken
sudo dns-switch fix-dns
Note
Emergency recovery command. 'dns-fix' is the legacy alias for the same action.
Scenario 2: DNS Status & Information
Check current DNS configuration and available servers
Step 1: Display current system DNS servers with detailed information
dns-switch status
Step 2: Get DNS status in machine-readable JSON format
dns-switch status --json
Note
Useful for scripting and automation
Step 3: Count available DNS servers by category (reputable, normal, encrypted, etc.)
dns-switch count
Step 4: List all reputable DNS servers with details
dns-switch list --category reputable
Scenario 3: Basic DNS Switching
Switch DNS servers by category, by provider name or by IP. Categories accepted by 'switch' are reputable, normal, fallback and remotely_fetched. 'encrypted' and 'all' are recognized but rejected before DNS changes: use 'dnscrypt-set' for encrypted DNS, or the supported '--names dnscrypt' alias path.
Step 1: Switch to 3 random reputable DNS servers from the database
sudo dns-switch switch --category reputable
Note
Category switching always picks 3 servers at random from that category.
Step 2: Switch to servers discovered earlier by the 'fetch' command
sudo dns-switch switch --category remotely_fetched
Note
Run 'dns-switch fetch' first; a normal fetch persists its results, while --no-action previews without database changes.
Step 3: Switch to specific DNS providers by name
sudo dns-switch switch --names cloudflare adguard
Step 4: Switch to specific DNS servers by IP address
sudo dns-switch switch --servers 1.1.1.1 9.9.9.9
Note
Useful when you know exact server IPs
Step 5: Switch to the embedded fallback DNS servers for emergencies
sudo dns-switch fallback
Note
Use when the database is corrupted or unavailable. This command applies immediately and has NO dry run: --no-action is ignored here.
Scenario 4: Random DNS Selection
Pick DNS servers at random. --type accepts reputable, normal, remotely_fetched, all, or a comma-separated mix of the first three. 'encrypted', 'fallback', 'failed' and 'both' are rejected here.
Step 1: Select 3 random DNS servers from reputable category (default behavior)
sudo dns-switch random
Step 2: Select 3 random reputable DNS servers and verify they work before applying
sudo dns-switch random --verify
Note
Only applies servers that pass health check
Step 3: Select 3 random reputable DNS servers and verify each works before applying
sudo dns-switch random --type reputable --verify
Note
Health checks each selected server; only uses working ones
Step 4: Select 5 random servers from normal category
sudo dns-switch random --type normal --count 5
Step 5: Select 6 random normal DNS servers and verify they work before applying
sudo dns-switch random --type normal --count 6 --verify
Note
If some servers fail health check, only working ones are used
Step 6: Select 6 servers: 3 from reputable + 3 from normal categories
sudo dns-switch random --type reputable,normal --count 6
Note
Count is distributed evenly across specified types
Step 7: Select 7 servers distributed: 4 reputable + 3 normal
sudo dns-switch random --type reputable,normal --count 7
Note
Uneven distribution favors first type
Step 8: Select 3 servers each from reputable, normal and remotely_fetched (9 total)
sudo dns-switch random --type all
Note
'all' excludes the encrypted, fallback and failed categories. --count is IGNORED with --type all: you always get up to 3 per category.
Step 9: Select 6 servers, 2 from each of the 3 named categories
sudo dns-switch random --type reputable,normal,remotely_fetched --count 6
Step 10: Select 10 servers, distributed 4+3+3 across the 3 categories
sudo dns-switch random --type reputable,normal,remotely_fetched --count 10
Note
The count flag is --count. There is no --count-random flag.
Step 11: Preview a random selection without touching the system DNS
dns-switch random --type reputable --count 5 --no-action
Note
--no-action also drops the root requirement, so no sudo is needed for a preview.
Scenario 5: DNS Health Checking
Test DNS servers for availability and performance. Health checks are read-only by default: use --save to persist results to the database. Valid --type values are reputable, normal, encrypted, fallback, remotely_fetched, failed and all. IMPORTANT: Failed servers are moved to 'failed' category only after 3 CONSECUTIVE failures (3-strike rule) to prevent false positives from temporary network issues. Run health checks 3 times to trigger category changes.
Step 1: Test reputable DNS servers (default) for availability and response times (read-only)
dns-switch health
Note
Read-only: does not modify the database
Step 2: Test reputable DNS servers only (read-only)
dns-switch health --type reputable
Note
Tests curated high-quality DNS providers. Read-only: does not modify database
Step 3: Test reputable servers and save results to database
dns-switch health --type reputable --save
Note
--save updates: status, response times, geolocation, consecutive_failures counter. Servers move to 'failed' category ONLY after 3 consecutive failures (run 3 times)
Step 4: Test normal DNS servers only (read-only)
dns-switch health --type normal
Note
Tests standard reliable DNS providers. Read-only mode
Step 5: Test encrypted DNS servers (DNSCrypt, DoH, DoT) only
dns-switch health --type encrypted
Note
Tests DNSCrypt and secure DNS providers. Read-only mode
Step 6: Check health of remotely fetched DNS servers (read-only)
dns-switch health --type remotely_fetched
Note
Tests servers previously discovered via 'fetch' command
Step 7: Test remotely fetched servers and save results to database
dns-switch health --type remotely_fetched --save
Note
3-STRIKE RULE: Servers move to 'failed' category only after 3 consecutive failures. Run this command 3 times to trigger category moves
Step 8: Test ALL working server categories (excludes failed servers)
dns-switch health --type all
Note
Tests: fallback + reputable + normal + encrypted + remotely_fetched. Excludes failed servers for efficiency. May take several minutes
Step 9: Test all working categories and save results to database
dns-switch health --type all --save
Note
Updates: status, response times, geolocation, consecutive_failures counter. 3-STRIKE RULE: Run 3 times to move failed servers to 'failed' category (prevents false positives)
Step 10: Run health check 3 times to trigger 3-strike rule and move failed servers
dns-switch health --type all --save && dns-switch health --type all --save && dns-switch health --type all --save
Note
WORKFLOW EXAMPLE: The 3-strike rule requires 3 consecutive failures before moving servers. Run 'count' after 3rd run to see category changes
Step 11: Test ONLY failed servers and update their status if recovered
dns-switch health --type failed --save
Note
Recovery is instant (1 success = move back). Tests servers from dns-database-failed.json. --save required to persist recovery
Step 12: BYPASS 3-strike rule: move failed servers to 'failed' category IMMEDIATELY
dns-switch health --type all --save --force-move
Note
⚠️ CAUTION: Bypasses protection against transient network issues. Use for urgent cleanup or when you're CERTAIN servers are permanently down. --save required
Step 13: Test remotely fetched servers and force-move failures immediately
dns-switch health --type remotely_fetched --save --force-move
Note
Useful for quickly cleaning up newly discovered servers that are non-responsive. Skips 3-strike protection
Step 14: Full health check with geolocation, save results
dns-switch health --full --save
Note
Full check includes geolocation lookup for all working servers
Step 15: Health check with JSON output (read-only)
dns-switch health --json
Note
Default tests reputable servers. Use --type to specify category
Step 16: Test encrypted DNS servers with JSON output for parsing
dns-switch health --type encrypted --json
Note
Structured JSON output for automation and integration
Step 17: Fresh health check, save results, JSON output
dns-switch health --fresh --save --json
Note
Bypasses cache for current data, persists to database
Scenario 6: JSON Output
Automation-friendly JSON responses
Step 1: Get status in JSON format
dns-switch status --json
Step 2: Pretty-printed DNS server counts
dns-switch count --json --json-pretty
Step 3: Human-readable JSON with enhanced formatting
dns-switch status --json-human
Scenario 7: DNS Switching by Names
Switch DNS servers using provider names
Step 1: Switch to Cloudflare DNS (1.1.1.1)
sudo dns-switch switch --names cloudflare
Step 2: Switch to Cloudflare DNS after verifying it's working
sudo dns-switch switch --names cloudflare --verify
Note
Health check performed before applying DNS change
Step 3: Switch to Cloudflare and Quad9 DNS servers (space-separated)
sudo dns-switch switch --names cloudflare QuadServer1
Note
Multiple names separated by spaces
Step 4: Switch to multiple DNS providers (comma-separated)
sudo dns-switch switch --names cloudflare,QuadServer1,adguard
Note
Alternative syntax using commas to separate names
Step 5: Switch to multiple DNS providers after verifying each works
sudo dns-switch switch --names cloudflare QuadServer1 adguard --verify
Note
Only working servers will be applied to resolv.conf
Step 6: Switch to AdGuard DNS (94.140.14.14, 94.140.15.15) - Privacy-respecting
sudo dns-switch switch --names adguard
Note
Blocks ads and trackers
Step 7: Switch to OpenDNS (208.67.222.222, 208.67.220.220)
sudo dns-switch switch --names opendns
Step 8: Switch to NextDNS (45.90.28.167, 45.90.30.167)
sudo dns-switch switch --names nextdns
Step 9: Switch to CleanBrowsing DNS (185.228.168.9, 185.228.169.9)
sudo dns-switch switch --names cleanbrowsing
Note
Family-friendly content filtering
Scenario 8: DNS Switching by IP
Switch DNS servers using IP addresses
Step 1: Switch to specific DNS server IP
sudo dns-switch switch --servers 1.1.1.1
Step 2: Switch to specific DNS server IP after verifying it works
sudo dns-switch switch --servers 1.1.1.1 --verify
Note
Health check ensures DNS server is responsive before applying
Step 3: Switch to multiple specific DNS server IPs
sudo dns-switch switch --servers 1.1.1.1 9.9.9.9
Step 4: Switch to multiple DNS IPs after verifying each works
sudo dns-switch switch --servers 1.1.1.1 9.9.9.9 208.67.222.222 --verify
Note
Failed servers are excluded from final configuration
Step 5: Switch to AdGuard DNS by IP
sudo dns-switch switch --servers 94.140.14.14 94.140.15.15
Scenario 9: Remote DNS Discovery & Fetching
Discover and fetch new DNS servers from remote sources. None of these need root: they only write the local dns-switch database.
Step 1: Fetch 25 DNS servers from remote sources, test them, and save to database
dns-switch fetch
Note
Default fetches 25 servers
Step 2: Fetch exactly 50 DNS servers from remote sources
dns-switch fetch --count 50
Note
Shows all results when count < 100
Step 3: Fetch exactly 100 DNS servers from remote sources
dns-switch fetch --count 100
Note
May take longer to complete
Step 4: Alternative syntax to fetch 35 servers (same result as fetch --count 35)
dns-switch fetch-count --fetch-count 35
Note
fetch-count reads --fetch-count ONLY. Passing --count to it is silently ignored and you get the default 25.
Step 5: Fetch ALL available DNS servers from remote sources
dns-switch fetch --all
Note
Note: Use kitty terminal to see country flags. Total servers > 60,000 so this will take very long to test all servers
Step 6: Force a fresh fetch, bypassing every cache (API cache, result cache)
dns-switch fetch --count 35 --fresh
Note
--fresh ensures completely new data from remote sources
Step 7: Fetch 25 servers with JSON output
dns-switch fetch --json
Step 8: Fresh fetch of 35 servers with JSON output
dns-switch fetch --count 35 --fresh --json
Step 9: Preview a fetch without writing anything to the database
dns-switch fetch --count 10 --no-action
Step 10: List previous fetch runs and their cache IDs
dns-switch fetch --history
Note
Take a cache ID from here and hand it to 'fetch --load'.
Step 11: Re-open the results of an earlier fetch instead of hitting the network
dns-switch fetch --load <CACHE_ID>
Note
Replace <CACHE_ID> with an ID printed by 'dns-switch fetch --history'.
Step 12: Pull the DNSCrypt and Tor DNS servers of your Kodachi card into the encrypted category
dns-switch fetch-dns-from-card
Note
Requires an active online-auth session: run 'online-auth authenticate' first, otherwise it fails with an authentication error.
Scenario 10: DNSCrypt & Pi-hole Integration
Encrypted DNS and ad-blocking integration
Step 1: Switch DNS to use local DNSCrypt (127.0.0.1)
sudo dns-switch switch --names dnscrypt
Note
Automatically starts dnscrypt-proxy service if not running. Aliases: dnscrypt | dnscrypt-server | dnscryptproxy | encrypted
Step 2: Check DNSCrypt proxy service status (read-only)
dns-switch dnscrypt
Step 3: Configure DNSCrypt to use Cloudflare's encrypted resolver
sudo dns-switch dnscrypt-set --resolver cloudflare
Note
Requires the dnscrypt-proxy package. Add --no-action to preview the configuration without writing it.
Step 4: Restart DNSCrypt proxy service
sudo dns-switch dnscrypt-restart
Step 5: Install and enable the systemd timer that auto-recovers DNSCrypt and falls back to safe DNS on failure
sudo dns-switch enable-dnscrypt-monitor
Note
Runs periodic health checks; on failure restarts DNSCrypt or falls back to safe DNS
Step 6: Show whether the DNSCrypt auto-recovery monitor timer is active
dns-switch dnscrypt-monitor-status
Step 7: Run a single DNSCrypt monitor check now (the same check the timer performs)
sudo dns-switch dnscrypt-monitor-check
Note
Safe to invoke manually; used internally by the auto-recovery timer
Step 8: Disable and remove the DNSCrypt auto-recovery timer
sudo dns-switch disable-dnscrypt-monitor
Step 9: Stop DNSCrypt and switch to reputable DNS servers
sudo dns-switch dnscrypt-remove
Note
Automatically switches to reputable DNS to avoid DNS being offline
Step 10: Switch to remote DNSCrypt IPv4 server from authentication card
sudo dns-switch switch --names RemoteDNSCryptIPv4
Note
Requires running 'fetch-dns-from-card' first to add remote servers
Step 11: Switch to remote DNSCrypt IPv6 server from authentication card
sudo dns-switch switch --names RemoteDNSCryptIPv6
Note
Requires running 'fetch-dns-from-card' first to add remote servers
Step 12: Switch to both remote DNSCrypt servers (comma-separated)
sudo dns-switch switch --names RemoteDNSCryptIPv4,RemoteDNSCryptIPv6
Note
Comma-separated format - both IPv4 and IPv6 from your VPS
Step 13: Switch to both remote DNSCrypt servers (space-separated)
sudo dns-switch switch --names RemoteDNSCryptIPv4 RemoteDNSCryptIPv6
Note
Space-separated format - alternative syntax for multiple servers
Step 14: Check Pi-hole service status with systemctl info (read-only)
dns-switch pihole
Note
Use 'systemctl status pihole-FTL.service' to verify service state directly
Step 15: Enable Pi-hole ad blocking DNS with automatic DNSCrypt integration
sudo dns-switch pihole-enable
Note
Pi-hole must be installed. DNSCrypt integration is automatic - no manual config needed!
Step 16: Disable Pi-hole DNS filtering and stop the service
sudo dns-switch pihole-disable
Note
DNSCrypt continues independently if running. Use 'sudo dns-switch pihole-enable' to re-enable.
Step 17: Set Pi-hole web interface password (automatically unprotects TOML file)
sudo dns-switch pihole-password --password NewSecurePassword123
Note
Note: To manually change password, run 'sudo chattr -i /etc/pihole/pihole.toml' first
Step 18: Reset Pi-hole configuration to a clean state
sudo dns-switch pihole-reset
Note
Pi-hole must be installed. Use 'pihole-enable' afterwards to re-apply Kodachi's DNSCrypt-upstream integration.
Scenario 11: Database Maintenance
Manage the DNS server database, its backups and its cleanup. Only the two restore commands touch system DNS, and only they need root.
Step 1: Remove the temporary and cache files the tool leaves behind
dns-switch clean
Note
Add --no-action to list them without deleting anything.
Step 2: Remove duplicate DNS entries from the database
dns-switch clean-duplicates
Note
Applies immediately: this command ignores --no-action.
Step 3: Flush systemd-resolved and nscd DNS caches to clear stale entries
dns-switch flush-cache
Note
Clears cached lookups so the next query reaches the configured DNS servers fresh. resolvectl needs no root; the nscd step is skipped when passwordless sudo is unavailable.
Step 4: Create a timestamped backup of the DNS server database
dns-switch backup
Note
Backs up the dns-switch database only, NOT /etc/resolv.conf.
Step 5: Create the backup and report the result as JSON
dns-switch backup --json
Step 6: Preview a factory reset of the database before committing to it
dns-switch restore-default --no-action
Note
--no-action drops the root requirement, so the preview needs no sudo.
Step 7: Reset the DNS database to factory defaults and apply the default DNS
sudo dns-switch restore-default
Note
DESTRUCTIVE: your custom entries and the collected health history are discarded. Take a 'dns-switch backup' first.
Step 8: Restore the DNS database from the most recent backup
sudo dns-switch restore-backup
Note
DESTRUCTIVE and immediate: it overwrites the current database and has NO dry run (--no-action is ignored). Run 'switch' afterwards to apply servers to the system.
Step 9: Restore the database from one specific backup file
sudo dns-switch restore-backup --file <BACKUP_FILE>
Note
Replace <BACKUP_FILE> with a file produced by 'dns-switch backup'. Paths containing '..' are rejected.
Scenario 12: Dry Run & JSON Output
Preview a change before you make it, and get machine-readable output. Only switch, random, fetch, dnscrypt-set, clean and restore-default honour --no-action; on every other command the flag is accepted and ignored, so do NOT trust it as a safety net (fallback, restore-backup and clean-duplicates apply for real regardless). --no-action also drops the root requirement, so previews need no sudo.
Step 1: Preview a switch without touching the system DNS
dns-switch switch --names cloudflare --no-action
Step 2: Preview a random selection without applying it
dns-switch random --type reputable --count 5 --no-action
Step 3: Preview a DNSCrypt resolver change without writing the config
dns-switch dnscrypt-set --resolver cloudflare --no-action
Step 4: Preview the temporary-file cleanup without deleting anything
dns-switch clean --no-action
Step 5: Get the current DNS status as indented JSON
dns-switch status --json --json-pretty
Step 6: Get health-check results in the enhanced, colorized JSON format
dns-switch health --type reputable --json-human
Step 7: Get the per-category server counts in enhanced JSON
dns-switch count --json-human
Scenario 13: DNS Mode Management (Modern vs Legacy)
Manage DNS configuration modes: modern (systemd-resolved) vs legacy (/etc/resolv.conf)
Step 1: Check current DNS management mode
dns-switch get-mode
Note
Displays mode health status and any configuration issues
Step 2: Get DNS mode in JSON format
dns-switch get-mode --json
Note
Includes resolv.conf symlink status and detected issues
Step 3: Auto-detect recommended DNS mode for this system
dns-switch detect-mode
Note
Checks systemd-resolved installation and activity status
Step 4: Get mode detection results in JSON
dns-switch detect-mode --json
Step 5: Switch to modern mode (systemd-resolved)
sudo dns-switch set-mode --mode modern
Note
Backs up existing resolv.conf, starts systemd-resolved if needed
Step 6: Switch to legacy mode (/etc/resolv.conf)
sudo dns-switch set-mode --mode legacy
Note
Extracts current DNS from systemd-resolved before switching
Step 7: Auto-repair broken DNS configuration
sudo dns-switch fix-dns
Note
Emergency repair command for connectivity issues
Step 8: Run complete DNS repair sequence regardless of initial health
sudo dns-switch fix-dns --force
Note
Use after unstable DNS incidents or repeated resolver failures
Step 9: Check current systemd-resolved configuration method
dns-switch get-modern-method
Note
Only applies when in modern mode (systemd-resolved)
Step 10: Get systemd-resolved method in JSON
dns-switch get-modern-method --json
Step 11: Set to global config method (RECOMMENDED)
sudo dns-switch set-modern-method --method global
Note
Safest method - prevents DNS leaks on all network interfaces
Step 12: Set to per-interface method
sudo dns-switch set-modern-method --method per-interface
Note
May miss virtual/VPN interfaces - use global method instead
Step 13: Set to NetworkManager method
sudo dns-switch set-modern-method --method networkmanager
Note
Only for NetworkManager-managed systems
Step 14: Set to auto with smart fallback chain
sudo dns-switch set-modern-method --method auto
Note
Automatically selects best available method
Step 15: Check for DNS leaks across all network interfaces
dns-switch verify-no-leaks
Note
Essential for privacy - detects DNS configuration bypasses
Step 16: Get DNS leak detection results in JSON
dns-switch verify-no-leaks --json
Note
Use after switching DNS to verify no leaks occurred
Scenario 14: Boot-Time DNS Check Management
Manage automatic DNS checking and fixing on system boot
Step 1: Run the boot-time DNS check by hand: report status and repair empty or invalid nameservers
sudo dns-switch boot-check
Note
Read-only while DNS is healthy, but it rewrites /etc/resolv.conf when it has to repair, which is why it needs sudo. Fallback servers come from the configuration, never from hardcoded values.
Step 2: Enable automatic DNS checking on system boot
sudo dns-switch enable-boot-check
Note
Ensures DNS is always configured correctly after system restart
Step 3: Disable automatic DNS checking on system boot
sudo dns-switch disable-boot-check
Note
DNS configuration will not be automatically checked on boot
Step 4: Check status of the boot-check systemd service
systemctl status dns-boot-check.service
Note
Useful for verifying boot-check is working correctly
Scenario 15: DNSSEC validation and DNS-over-HTTPS
Enable DNSSEC signature validation and DNS-over-HTTPS in dnscrypt-proxy. All four commands are authentication- and root-gated because they edit /etc/dnscrypt-proxy/dnscrypt-proxy.toml and restart the service. The legacy dot-on and dot-off names configure DoH, not DNS-over-TLS.
Step 1: Enable DNSSEC validation in dnscrypt-proxy.toml; restart dnscrypt-proxy. Earns +0.1 dns_privacy score.
sudo dns-switch dnssec-on
Note
DNSCrypt-proxy must be installed. Falls back to plain DNS if upstream doesn't sign.
Step 2: Disable DNSSEC validation (default state).
sudo dns-switch dnssec-off
Step 3: Enable DNS-over-HTTPS in dnscrypt-proxy.toml; restart service. Earns +0.2 dns_privacy score.
sudo dns-switch dot-on
Note
Despite the legacy command name, this selects DoH over HTTPS; it does not configure DNS-over-TLS. On Kodachi the encryption layer is dnscrypt-proxy, not systemd-resolved.
Step 4: Disable DoH; dnscrypt-proxy reverts to DNSCrypt-only protocol.
sudo dns-switch dot-off
Scenario 16: External VPN DNS handover (Mullvad, ProtonVPN, etc.)
Let a third-party VPN GUI manage DNS. Kodachi locks /etc/resolv.conf immutable for DNS-leak protection, which prevents such clients from setting their tunnel DNS: they fail with "internet blocked" or "failed to set system DNS". Hand DNS to the client before connecting, then take it back when done.
Step 1: Unlock /etc/resolv.conf and pause Kodachi DNS protection (immutable lock + boot-check) so the VPN GUI can set its tunnel DNS. Run BEFORE connecting Mullvad/ProtonVPN.
sudo dns-switch external-dns --state on
Note
While ON, Kodachi's immutable DNS-leak lock is paused, so your VPN client must enforce its own leak protection (Mullvad and ProtonVPN do). Pi-hole cannot be enabled while this is ON.
Step 2: Remove the handover marker and re-apply Kodachi-managed, locked DNS. Disconnect the VPN client first.
sudo dns-switch external-dns --state off
Step 3: Show whether a third-party VPN currently owns DNS (read-only; no sudo).
dns-switch external-dns --state status
Scenario 17: Program Information & Per-Command Help
Version, capabilities, examples, and the per-action help pages.
Step 1: Show every action, grouped by topic, with the global flags
dns-switch --help
Step 2: Show the help page for a single action
dns-switch switch --help
Note
Works for any action: '<action> --help', '<action> -h' or '<action> help'.
Step 3: Same as --help, as a positional action
dns-switch help
Step 4: Show the version number
dns-switch --version
Step 5: Machine-readable capability record for tooling
dns-switch --info --json
Step 6: All examples as JSON, for docs and automation
dns-switch --examples --json
Environment Variables
| Variable | Description | Default | Values |
|---|---|---|---|
RUST_LOG |
Set logging level | info | error|warn|info|debug|trace |
NO_COLOR |
Disable all colored output when set | unset | 1|true|yes (any value disables color) |
DNS_SWITCH_CONFIG |
Path to configuration file | ~/.config/dns-switch/config.json | /path/to/config.json |
Exit Codes
| Code | Description |
|---|---|
| 0 | Success |
| 1 | General error |
| 2 | Invalid arguments |
| 3 | Permission denied |
| 4 | Network error |
| 5 | File not found |
| 6 | Operation timeout |
| 7 | Authentication error |