refactor: Rename project from dns-helper to ekdns across all files and documentation
This commit is contained in:
@@ -1,8 +1,8 @@
|
|||||||
# dns-helper Development Guidelines
|
# ekdns Development Guidelines
|
||||||
|
|
||||||
## Project Overview
|
## Project Overview
|
||||||
|
|
||||||
dns-helper — a Go CLI tool that resolves hostnames against a specified DNS server and writes the resulting IP-to-hostname mappings into the local hosts file. It manages a clearly delimited block within the hosts file so it can cleanly add and remove only its own entries. Built as a single static binary with no runtime dependencies.
|
ekdns — a Go CLI tool that resolves hostnames against a specified DNS server and writes the resulting IP-to-hostname mappings into the local hosts file. It manages a clearly delimited block within the hosts file so it can cleanly add and remove only its own entries. Built as a single static binary with no runtime dependencies.
|
||||||
|
|
||||||
## Go Toolchain — CRITICAL
|
## Go Toolchain — CRITICAL
|
||||||
|
|
||||||
@@ -48,32 +48,32 @@ go test ./... # May use incompatible Go version
|
|||||||
.\build.ps1 -Release -Package
|
.\build.ps1 -Release -Package
|
||||||
```
|
```
|
||||||
|
|
||||||
Output: `build\dns-helper.exe` (default), `build\dns-helper-<os>-<arch>[.exe]` (cross-compile).
|
Output: `build\ekdns.exe` (default), `build\ekdns-<os>-<arch>[.exe]` (cross-compile).
|
||||||
Release packages: `releases\dns-helper-<version>-<os>-<arch>.zip` / `.tar.gz`
|
Release packages: `releases\ekdns-<version>-<os>-<arch>.zip` / `.tar.gz`
|
||||||
|
|
||||||
## Running dns-helper
|
## Running ekdns
|
||||||
|
|
||||||
dns-helper has two commands: `add` and `delete` (with short aliases `a` and `d`/`del`).
|
ekdns has two commands: `add` and `delete` (with short aliases `a` and `d`/`del`).
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Add one or more hostnames (resolves via the given DNS server, writes to hosts file)
|
# Add one or more hostnames (resolves via the given DNS server, writes to hosts file)
|
||||||
.\build\dns-helper.exe add -host hostname.example.com -server dns.example.com
|
.\build\ekdns.exe add -host hostname.example.com -server dns.example.com
|
||||||
.\build\dns-helper.exe a -host hostname.example.com -server dns.example.com
|
.\build\ekdns.exe a -host hostname.example.com -server dns.example.com
|
||||||
|
|
||||||
# Add multiple hostnames at once (comma-separated)
|
# Add multiple hostnames at once (comma-separated)
|
||||||
.\build\dns-helper.exe add -host "host1.example.com,host2.example.com" -server dns.example.com
|
.\build\ekdns.exe add -host "host1.example.com,host2.example.com" -server dns.example.com
|
||||||
|
|
||||||
# Delete a specific hostname from the managed block
|
# Delete a specific hostname from the managed block
|
||||||
.\build\dns-helper.exe delete -host hostname.example.com
|
.\build\ekdns.exe delete -host hostname.example.com
|
||||||
.\build\dns-helper.exe del -host hostname.example.com
|
.\build\ekdns.exe del -host hostname.example.com
|
||||||
.\build\dns-helper.exe d -host hostname.example.com
|
.\build\ekdns.exe d -host hostname.example.com
|
||||||
|
|
||||||
# Delete multiple hostnames (comma-separated)
|
# Delete multiple hostnames (comma-separated)
|
||||||
.\build\dns-helper.exe delete -host "host1.example.com,host2.example.com"
|
.\build\ekdns.exe delete -host "host1.example.com,host2.example.com"
|
||||||
|
|
||||||
# Delete ALL entries added by dns-helper
|
# Delete ALL entries added by ekdns
|
||||||
.\build\dns-helper.exe delete all
|
.\build\ekdns.exe delete all
|
||||||
.\build\dns-helper.exe delete a
|
.\build\ekdns.exe delete a
|
||||||
```
|
```
|
||||||
|
|
||||||
### Flag Reference
|
### Flag Reference
|
||||||
@@ -83,7 +83,7 @@ dns-helper has two commands: `add` and `delete` (with short aliases `a` and `d`/
|
|||||||
| `add` | `-host` | Yes | Comma-separated list of hostnames to resolve and add |
|
| `add` | `-host` | Yes | Comma-separated list of hostnames to resolve and add |
|
||||||
| `add` | `-server` | Yes | DNS resolver to query (e.g. `dns.example.com`) |
|
| `add` | `-server` | Yes | DNS resolver to query (e.g. `dns.example.com`) |
|
||||||
| `delete` | `-host` | Yes (unless `all`) | Comma-separated list of hostnames to remove |
|
| `delete` | `-host` | Yes (unless `all`) | Comma-separated list of hostnames to remove |
|
||||||
| `delete all` | — | — | Removes every entry dns-helper has written |
|
| `delete all` | — | — | Removes every entry ekdns has written |
|
||||||
|
|
||||||
### Exit Codes
|
### Exit Codes
|
||||||
|
|
||||||
@@ -94,7 +94,7 @@ dns-helper has two commands: `add` and `delete` (with short aliases `a` and `d`/
|
|||||||
|
|
||||||
### Hosts File Management
|
### Hosts File Management
|
||||||
|
|
||||||
dns-helper wraps its entries between two marker lines:
|
ekdns wraps its entries between two marker lines:
|
||||||
|
|
||||||
```
|
```
|
||||||
# DNSHelper <<-> START CONFIG
|
# DNSHelper <<-> START CONFIG
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
Follow-up TODOs: None
|
Follow-up TODOs: None
|
||||||
-->
|
-->
|
||||||
|
|
||||||
# DNS-Helper Constitution
|
# ekdns Constitution
|
||||||
|
|
||||||
## Core Principles
|
## Core Principles
|
||||||
|
|
||||||
@@ -188,7 +188,7 @@ None. All external functionality is provided by `golang.org/x/net/dns/dnsmessage
|
|||||||
## Governance
|
## Governance
|
||||||
|
|
||||||
This constitution is the authoritative source of project standards for
|
This constitution is the authoritative source of project standards for
|
||||||
DNS-Helper. It supersedes informal conventions, ad-hoc decisions, and
|
ekdns. It supersedes informal conventions, ad-hoc decisions, and
|
||||||
prior practices that conflict with its contents.
|
prior practices that conflict with its contents.
|
||||||
|
|
||||||
- **Amendment process**: Any change to this constitution MUST be
|
- **Amendment process**: Any change to this constitution MUST be
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
# dns-helper
|
# ekekDNSHelper
|
||||||
|
|
||||||
A cross-platform CLI tool that resolves hostnames against DNS servers and writes the resulting IP-to-hostname mappings into the local hosts file. It manages a clearly delimited block within the hosts file so it can cleanly add and remove only its own entries.
|
A cross-platform CLI tool that resolves hostnames against DNS servers and writes the resulting IP-to-hostname mappings into the local hosts file. It manages a clearly delimited block within the hosts file so it can cleanly add and remove only its own entries.
|
||||||
|
|
||||||
By default, dns-helper performs **smart resolution**: it discovers the authoritative nameserver for each hostname through a parallel NS fan-out across local and public resolvers, then queries that NS directly for the freshest answer. Internal hostnames (without zone delegation) fall back to a parallel A-record query across all resolvers.
|
By default, ekdns performs **smart resolution**: it discovers the authoritative nameserver for each hostname through a parallel NS fan-out across local and public resolvers, then queries that NS directly for the freshest answer. Internal hostnames (without zone delegation) fall back to a parallel A-record query across all resolvers.
|
||||||
|
|
||||||
Built as a single static binary with no runtime dependencies.
|
Built as a single static binary with no runtime dependencies.
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@ Built as a single static binary with no runtime dependencies.
|
|||||||
- Context-aware error messages with private TLD hints (`.local`, `.corp`, `.internal`, etc.)
|
- Context-aware error messages with private TLD hints (`.local`, `.corp`, `.internal`, etc.)
|
||||||
- Per-query timeout control via `-timeout`
|
- Per-query timeout control via `-timeout`
|
||||||
- Verbose per-stage resolution trace via `-verbose`
|
- Verbose per-stage resolution trace via `-verbose`
|
||||||
- Managed block markers ensure only dns-helper's entries are ever modified
|
- Managed block markers ensure only ekdns's entries are ever modified
|
||||||
- Automatic backup of the hosts file before every write
|
- Automatic backup of the hosts file before every write
|
||||||
- File-based lock prevents concurrent modifications
|
- File-based lock prevents concurrent modifications
|
||||||
- Cross-platform: Windows, macOS, and Linux
|
- Cross-platform: Windows, macOS, and Linux
|
||||||
@@ -36,7 +36,7 @@ Built as a single static binary with no runtime dependencies.
|
|||||||
```powershell
|
```powershell
|
||||||
# Clone the repository
|
# Clone the repository
|
||||||
git clone <repo-url>
|
git clone <repo-url>
|
||||||
cd dns-helper
|
cd ekdns
|
||||||
|
|
||||||
# Build for the current platform
|
# Build for the current platform
|
||||||
.\build.ps1
|
.\build.ps1
|
||||||
@@ -45,7 +45,7 @@ cd dns-helper
|
|||||||
.\build.ps1 -Release -CrossCompile
|
.\build.ps1 -Release -CrossCompile
|
||||||
```
|
```
|
||||||
|
|
||||||
The default build output is `build\dns-helper.exe` (Windows). Cross-compiled binaries are named `build\dns-helper-<os>-<arch>[.exe]`.
|
The default build output is `build\ekdns.exe` (Windows). Cross-compiled binaries are named `build\ekdns-<os>-<arch>[.exe]`.
|
||||||
|
|
||||||
### Release packages
|
### Release packages
|
||||||
|
|
||||||
@@ -54,46 +54,46 @@ The default build output is `build\dns-helper.exe` (Windows). Cross-compiled bin
|
|||||||
.\build.ps1 -Release -CrossCompile -Package
|
.\build.ps1 -Release -CrossCompile -Package
|
||||||
```
|
```
|
||||||
|
|
||||||
Archives are written to `releases\dns-helper-<version>-<os>-<arch>.zip` (Windows) or `.tar.gz` (macOS/Linux).
|
Archives are written to `releases\ekdns-<version>-<os>-<arch>.zip` (Windows) or `.tar.gz` (macOS/Linux).
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
> **Note:** dns-helper must be run with elevated privileges (Run as Administrator on Windows, `sudo` on macOS/Linux) because it modifies the system hosts file.
|
> **Note:** ekdns must be run with elevated privileges (Run as Administrator on Windows, `sudo` on macOS/Linux) because it modifies the system hosts file.
|
||||||
|
|
||||||
### Add entries
|
### Add entries
|
||||||
|
|
||||||
Resolve hostnames using smart default resolution and add to hosts file:
|
Resolve hostnames using smart default resolution and add to hosts file:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
dns-helper add -host www.example.com
|
ekdns add -host www.example.com
|
||||||
```
|
```
|
||||||
|
|
||||||
Specify a resolution mode:
|
Specify a resolution mode:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
# Use only local DNS resolvers (no public fallback)
|
# Use only local DNS resolvers (no public fallback)
|
||||||
dns-helper add -host internal.corp -server local
|
ekdns add -host internal.corp -server local
|
||||||
|
|
||||||
# Use the default gateway as DNS
|
# Use the default gateway as DNS
|
||||||
dns-helper add -host www.example.com -server gateway
|
ekdns add -host www.example.com -server gateway
|
||||||
|
|
||||||
# Use a specific DNS server
|
# Use a specific DNS server
|
||||||
dns-helper add -host www.example.com -server 8.8.8.8
|
ekdns add -host www.example.com -server 8.8.8.8
|
||||||
|
|
||||||
# Use a specific DNS server on a non-standard port
|
# Use a specific DNS server on a non-standard port
|
||||||
dns-helper add -host www.example.com -server 10.0.0.53:5353
|
ekdns add -host www.example.com -server 10.0.0.53:5353
|
||||||
```
|
```
|
||||||
|
|
||||||
Add multiple hostnames at once:
|
Add multiple hostnames at once:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
dns-helper add -host "host1.example.com,host2.example.com"
|
ekdns add -host "host1.example.com,host2.example.com"
|
||||||
```
|
```
|
||||||
|
|
||||||
Use timeout and verbose options:
|
Use timeout and verbose options:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
dns-helper add -host www.example.com -timeout 5 -verbose
|
ekdns add -host www.example.com -timeout 5 -verbose
|
||||||
```
|
```
|
||||||
|
|
||||||
### Delete entries
|
### Delete entries
|
||||||
@@ -101,19 +101,19 @@ dns-helper add -host www.example.com -timeout 5 -verbose
|
|||||||
Remove a specific hostname:
|
Remove a specific hostname:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
dns-helper delete -host hostname.example.com
|
ekdns delete -host hostname.example.com
|
||||||
```
|
```
|
||||||
|
|
||||||
Remove multiple hostnames:
|
Remove multiple hostnames:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
dns-helper delete -host "host1.example.com,host2.example.com"
|
ekdns delete -host "host1.example.com,host2.example.com"
|
||||||
```
|
```
|
||||||
|
|
||||||
Remove **all** managed entries:
|
Remove **all** managed entries:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
dns-helper delete all
|
ekdns delete all
|
||||||
```
|
```
|
||||||
|
|
||||||
Short aliases: `a` for `add`, `d` / `del` for `delete`
|
Short aliases: `a` for `add`, `d` / `del` for `delete`
|
||||||
@@ -127,7 +127,7 @@ Short aliases: `a` for `add`, `d` / `del` for `delete`
|
|||||||
| `add` | `-timeout` | No | 3 | Per-query DNS timeout in seconds |
|
| `add` | `-timeout` | No | 3 | Per-query DNS timeout in seconds |
|
||||||
| `add` | `-verbose` | No | false | Emit per-stage resolution trace to stderr |
|
| `add` | `-verbose` | No | false | Emit per-stage resolution trace to stderr |
|
||||||
| `delete` | `-host` | Yes (unless `all`) | — | Comma-separated hostnames to remove |
|
| `delete` | `-host` | Yes (unless `all`) | — | Comma-separated hostnames to remove |
|
||||||
| `delete all` | — | — | — | Removes every entry dns-helper has written |
|
| `delete all` | — | — | — | Removes every entry ekdns has written |
|
||||||
|
|
||||||
### Exit codes
|
### Exit codes
|
||||||
|
|
||||||
@@ -140,7 +140,7 @@ Short aliases: `a` for `add`, `d` / `del` for `delete`
|
|||||||
|
|
||||||
### Smart Default (no `-server` flag)
|
### Smart Default (no `-server` flag)
|
||||||
|
|
||||||
When `-server` is omitted, dns-helper performs multi-stage authoritative resolution:
|
When `-server` is omitted, ekdns performs multi-stage authoritative resolution:
|
||||||
|
|
||||||
1. **Discover** local DNS resolvers and default gateway from OS network configuration.
|
1. **Discover** local DNS resolvers and default gateway from OS network configuration.
|
||||||
2. **Build resolver pool**: local resolvers + hardcoded bootstrap set (1.1.1.1, 8.8.8.8, etc.), deduplicated.
|
2. **Build resolver pool**: local resolvers + hardcoded bootstrap set (1.1.1.1, 8.8.8.8, etc.), deduplicated.
|
||||||
@@ -153,7 +153,7 @@ When `-server` is omitted, dns-helper performs multi-stage authoritative resolut
|
|||||||
|
|
||||||
```sh
|
```sh
|
||||||
# Example: smart default resolution with verbose trace
|
# Example: smart default resolution with verbose trace
|
||||||
dns-helper add -host www.example.com -verbose
|
ekdns add -host www.example.com -verbose
|
||||||
```
|
```
|
||||||
|
|
||||||
Verbose output:
|
Verbose output:
|
||||||
@@ -172,7 +172,7 @@ Verbose output:
|
|||||||
Queries only the locally configured DNS resolvers (from OS network configuration) in priority order. No fallback to public resolvers.
|
Queries only the locally configured DNS resolvers (from OS network configuration) in priority order. No fallback to public resolvers.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
dns-helper add -host internal.client.local -server local
|
ekdns add -host internal.client.local -server local
|
||||||
```
|
```
|
||||||
|
|
||||||
Fails with an error if all local resolvers are unreachable or no local resolvers are found.
|
Fails with an error if all local resolvers are unreachable or no local resolvers are found.
|
||||||
@@ -182,7 +182,7 @@ Fails with an error if all local resolvers are unreachable or no local resolvers
|
|||||||
Discovers the default gateway IP and uses it as the DNS server. No fallback.
|
Discovers the default gateway IP and uses it as the DNS server. No fallback.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
dns-helper add -host www.example.com -server gateway
|
ekdns add -host www.example.com -server gateway
|
||||||
```
|
```
|
||||||
|
|
||||||
### Explicit Server (`-server <ip>[:<port>]`)
|
### Explicit Server (`-server <ip>[:<port>]`)
|
||||||
@@ -190,8 +190,8 @@ dns-helper add -host www.example.com -server gateway
|
|||||||
Queries the specified DNS server directly. Port defaults to 53 if omitted.
|
Queries the specified DNS server directly. Port defaults to 53 if omitted.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
dns-helper add -host www.example.com -server 8.8.8.8
|
ekdns add -host www.example.com -server 8.8.8.8
|
||||||
dns-helper add -host www.example.com -server 10.0.0.53:5353
|
ekdns add -host www.example.com -server 10.0.0.53:5353
|
||||||
```
|
```
|
||||||
|
|
||||||
## Error Messages
|
## Error Messages
|
||||||
@@ -203,7 +203,7 @@ When a hostname with a private TLD (`.local`, `.corp`, `.internal`, `.lan`, `.ho
|
|||||||
```
|
```
|
||||||
Error: failed to resolve myservice.client.local: ...
|
Error: failed to resolve myservice.client.local: ...
|
||||||
Hint: the hostname uses a private TLD (.local). Try specifying an internal DNS server:
|
Hint: the hostname uses a private TLD (.local). Try specifying an internal DNS server:
|
||||||
dns-helper add -host myservice.client.local -server <internal-dns-ip>
|
ekdns add -host myservice.client.local -server <internal-dns-ip>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Split-horizon conflict
|
### Split-horizon conflict
|
||||||
@@ -226,17 +226,17 @@ Error: CNAME chain depth exceeded for www.example.com (max 10 hops): probable CN
|
|||||||
|
|
||||||
## How it works
|
## How it works
|
||||||
|
|
||||||
dns-helper wraps its entries between two marker lines in the hosts file:
|
ekdns wraps its entries between two marker lines in the hosts file:
|
||||||
|
|
||||||
```
|
```
|
||||||
# DNSHelper <<-> START CONFIG
|
# ekDNSHelper <<-> START CONFIG
|
||||||
192.0.2.1 hostname.example.com
|
192.0.2.1 hostname.example.com
|
||||||
# DNSHelper <->> END CONFIG
|
# ekDNSHelper <->> END CONFIG
|
||||||
```
|
```
|
||||||
|
|
||||||
Only lines within this managed block are ever modified or removed. The rest of the hosts file is preserved exactly as-is.
|
Only lines within this managed block are ever modified or removed. The rest of the hosts file is preserved exactly as-is.
|
||||||
|
|
||||||
Before every write, a backup of the hosts file is saved to the directory containing the dns-helper executable.
|
Before every write, a backup of the hosts file is saved to the directory containing the ekdns executable.
|
||||||
|
|
||||||
### Hosts file locations
|
### Hosts file locations
|
||||||
|
|
||||||
@@ -248,7 +248,7 @@ Before every write, a backup of the hosts file is saved to the directory contain
|
|||||||
|
|
||||||
### Network discovery (per platform)
|
### Network discovery (per platform)
|
||||||
|
|
||||||
When using smart default, local, or gateway modes, dns-helper discovers your network configuration via OS utilities:
|
When using smart default, local, or gateway modes, ekdns discovers your network configuration via OS utilities:
|
||||||
|
|
||||||
| Platform | Method |
|
| Platform | Method |
|
||||||
|----------|--------|
|
|----------|--------|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# Build script for dns-helper
|
# Build script for ekDNSHelper
|
||||||
# Builds the executables using the go1.20 toolchain
|
# Builds the executables using the go1.20 toolchain
|
||||||
#
|
#
|
||||||
# USAGE:
|
# USAGE:
|
||||||
@@ -10,13 +10,13 @@
|
|||||||
# .\build.ps1 -Release -Package # Full release: optimized build + packages
|
# .\build.ps1 -Release -Package # Full release: optimized build + packages
|
||||||
#
|
#
|
||||||
# OUTPUT:
|
# OUTPUT:
|
||||||
# - Default build: build\dns-helper.exe
|
# - Default build: build\ekdns.exe
|
||||||
# - Cross-compiled: build\dns-helper-<os>-<arch>[.exe]
|
# - Cross-compiled: build\ekdns-<os>-<arch>[.exe]
|
||||||
# - Release packages: releases\dns-helper-<version>-<os>-<arch>.zip / .tar.gz
|
# - Release packages: releases\ekdns-<version>-<os>-<arch>.zip / .tar.gz
|
||||||
|
|
||||||
param(
|
param(
|
||||||
[string]$OutputDir = "build",
|
[string]$OutputDir = "build",
|
||||||
[string]$OutputName = "dns-helper",
|
[string]$OutputName = "ekdns",
|
||||||
[switch]$Release,
|
[switch]$Release,
|
||||||
[switch]$Clean,
|
[switch]$Clean,
|
||||||
[switch]$CrossCompile,
|
[switch]$CrossCompile,
|
||||||
@@ -54,7 +54,7 @@ $ErrorActionPreference = $prevErrorActionPreference
|
|||||||
$buildTime = Get-Date -Format "yyyy-MM-ddTHH:mm:ssZ"
|
$buildTime = Get-Date -Format "yyyy-MM-ddTHH:mm:ssZ"
|
||||||
|
|
||||||
Write-Host "============================================" -ForegroundColor Cyan
|
Write-Host "============================================" -ForegroundColor Cyan
|
||||||
Write-Host " dns-helper Build" -ForegroundColor Cyan
|
Write-Host " ekDNSHelper Build" -ForegroundColor Cyan
|
||||||
Write-Host "============================================" -ForegroundColor Cyan
|
Write-Host "============================================" -ForegroundColor Cyan
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host " Version: $gitTag" -ForegroundColor Gray
|
Write-Host " Version: $gitTag" -ForegroundColor Gray
|
||||||
@@ -232,7 +232,7 @@ if ($Package) {
|
|||||||
|
|
||||||
# VERSION.txt
|
# VERSION.txt
|
||||||
@"
|
@"
|
||||||
dns-helper Version Information
|
ekDNSHelper Version Information
|
||||||
===============================
|
===============================
|
||||||
|
|
||||||
Version: $gitTag
|
Version: $gitTag
|
||||||
@@ -246,7 +246,7 @@ Run '$exeName --help' for usage information.
|
|||||||
# CHECKSUMS.txt
|
# CHECKSUMS.txt
|
||||||
$exeHash = (Get-FileHash -Path (Join-Path $packageDir $exeName) -Algorithm SHA256).Hash
|
$exeHash = (Get-FileHash -Path (Join-Path $packageDir $exeName) -Algorithm SHA256).Hash
|
||||||
@"
|
@"
|
||||||
dns-helper Release Checksums
|
ekDNSHelper Release Checksums
|
||||||
Version: $gitTag
|
Version: $gitTag
|
||||||
Build: $gitHash
|
Build: $gitHash
|
||||||
Platform: $platformName
|
Platform: $platformName
|
||||||
@@ -296,7 +296,7 @@ To verify (Linux/macOS):
|
|||||||
Write-Host "Release packaging complete!" -ForegroundColor Green
|
Write-Host "Release packaging complete!" -ForegroundColor Green
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host "Package contents:" -ForegroundColor Cyan
|
Write-Host "Package contents:" -ForegroundColor Cyan
|
||||||
Write-Host " - dns-helper executable" -ForegroundColor Gray
|
Write-Host " - ekdns executable" -ForegroundColor Gray
|
||||||
Write-Host " - README.md (if present)" -ForegroundColor Gray
|
Write-Host " - README.md (if present)" -ForegroundColor Gray
|
||||||
Write-Host " - VERSION.txt" -ForegroundColor Gray
|
Write-Host " - VERSION.txt" -ForegroundColor Gray
|
||||||
Write-Host " - CHECKSUMS.txt (integrity verification)" -ForegroundColor Gray
|
Write-Host " - CHECKSUMS.txt (integrity verification)" -ForegroundColor Gray
|
||||||
|
|||||||
+3
-3
@@ -1,4 +1,4 @@
|
|||||||
# Bump Version Script for dns-helper
|
# Bump Version Script for ekdnsr
|
||||||
# Automatically increments version based on semantic versioning
|
# Automatically increments version based on semantic versioning
|
||||||
#
|
#
|
||||||
# USAGE:
|
# USAGE:
|
||||||
@@ -36,7 +36,7 @@ param(
|
|||||||
$ErrorActionPreference = "Stop"
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
||||||
Write-Host "============================================" -ForegroundColor Cyan
|
Write-Host "============================================" -ForegroundColor Cyan
|
||||||
Write-Host " dns-helper" -ForegroundColor Cyan
|
Write-Host " ekdnsr" -ForegroundColor Cyan
|
||||||
Write-Host " Version Bump" -ForegroundColor Cyan
|
Write-Host " Version Bump" -ForegroundColor Cyan
|
||||||
Write-Host "============================================" -ForegroundColor Cyan
|
Write-Host "============================================" -ForegroundColor Cyan
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
@@ -139,7 +139,7 @@ if ($DryRun) {
|
|||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host "Next steps:" -ForegroundColor Cyan
|
Write-Host "Next steps:" -ForegroundColor Cyan
|
||||||
Write-Host " 1. Build release: .\build.ps1 -Release -Package" -ForegroundColor White
|
Write-Host " 1. Build release: .\build.ps1 -Release -Package" -ForegroundColor White
|
||||||
Write-Host " 2. Test the build: .\build\dns-helper.exe --help" -ForegroundColor White
|
Write-Host " 2. Test the build: .\build\ekdns--help" -ForegroundColor White
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
|
|
||||||
# Output the new version for CI/CD pipelines
|
# Output the new version for CI/CD pipelines
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
StartMarker = "# DNSHelper <<-> START CONFIG"
|
StartMarker = "# ekDNSHelper <<-> START CONFIG"
|
||||||
EndMarker = "# DNSHelper <->> END CONFIG"
|
EndMarker = "# ekDNSHelper <->> END CONFIG"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DNSEntry represents a single IP-to-hostname mapping.
|
// DNSEntry represents a single IP-to-hostname mapping.
|
||||||
@@ -116,7 +116,7 @@ func (m *Manager) Write(hf *HostsFile, backupDir string) error {
|
|||||||
// This is required so the subsequent rename stays on the same filesystem
|
// This is required so the subsequent rename stays on the same filesystem
|
||||||
// partition (avoids EXDEV on Unix).
|
// partition (avoids EXDEV on Unix).
|
||||||
success := false
|
success := false
|
||||||
tempFile, err := m.fs.CreateTemp(filepath.Dir(hf.Path), ".dns-helper-tmp-*")
|
tempFile, err := m.fs.CreateTemp(filepath.Dir(hf.Path), ".ekdns-tmp-*")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
m.fs.Remove(backupPath) //nolint:errcheck
|
m.fs.Remove(backupPath) //nolint:errcheck
|
||||||
return fmt.Errorf("creating temp file: %w", err)
|
return fmt.Errorf("creating temp file: %w", err)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package hostfile_test
|
package hostfile_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"ekdns/hostfile"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
@@ -8,8 +9,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"dns-helper/hostfile"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|||||||
+2
-2
@@ -17,13 +17,13 @@ func ParseManagedBlock(lines []string) (prefix, managed, postfix []string, hasMa
|
|||||||
endCount := 0
|
endCount := 0
|
||||||
|
|
||||||
for i, line := range lines {
|
for i, line := range lines {
|
||||||
if strings.Contains(line, "DNSHelper <<-> START CONFIG") {
|
if strings.Contains(line, "ekDNSHelper <<-> START CONFIG") {
|
||||||
startCount++
|
startCount++
|
||||||
if startIdx == -1 {
|
if startIdx == -1 {
|
||||||
startIdx = i
|
startIdx = i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if strings.Contains(line, "DNSHelper <->> END CONFIG") {
|
if strings.Contains(line, "ekDNSHelper <->> END CONFIG") {
|
||||||
endCount++
|
endCount++
|
||||||
if endIdx == -1 {
|
if endIdx == -1 {
|
||||||
endIdx = i
|
endIdx = i
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"dns-helper/hostfile"
|
"ekdns/hostfile"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
@@ -253,7 +253,7 @@ func TestAssembleContent_EmptyManagedOmitsBlock(t *testing.T) {
|
|||||||
t.Fatalf("expected 2 lines (no managed block), got %d: %v", len(result), result)
|
t.Fatalf("expected 2 lines (no managed block), got %d: %v", len(result), result)
|
||||||
}
|
}
|
||||||
for _, line := range result {
|
for _, line := range result {
|
||||||
if strings.Contains(line, "DNSHelper") {
|
if strings.Contains(line, "ekDNSHelper") {
|
||||||
t.Errorf("managed block markers should be absent when managed is empty: %v", result)
|
t.Errorf("managed block markers should be absent when managed is empty: %v", result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -353,7 +353,7 @@ func TestRemoveAll_AssembleContentOmitsBlock(t *testing.T) {
|
|||||||
t.Fatalf("expected 2 lines with no managed block, got %d: %v", len(result), result)
|
t.Fatalf("expected 2 lines with no managed block, got %d: %v", len(result), result)
|
||||||
}
|
}
|
||||||
for _, line := range result {
|
for _, line := range result {
|
||||||
if strings.Contains(line, "DNSHelper") {
|
if strings.Contains(line, "ekDNSHelper") {
|
||||||
t.Errorf("managed block markers should be absent after RemoveAll: %v", result)
|
t.Errorf("managed block markers should be absent after RemoveAll: %v", result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
lockFileName = ".dns-helper.lock"
|
lockFileName = ".ekdns.lock"
|
||||||
staleTimeout = 2 * time.Minute
|
staleTimeout = 2 * time.Minute
|
||||||
retryInterval = 200 * time.Millisecond
|
retryInterval = 200 * time.Millisecond
|
||||||
maxWait = 2 * time.Second
|
maxWait = 2 * time.Second
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"dns-helper/lockfile"
|
"ekdns/lockfile"
|
||||||
)
|
)
|
||||||
|
|
||||||
// T006-1: Acquire succeeds and lock file exists on disk.
|
// T006-1: Acquire succeeds and lock file exists on disk.
|
||||||
@@ -18,7 +18,7 @@ func TestAcquireSucceeds(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer lock.Release()
|
defer lock.Release()
|
||||||
|
|
||||||
lockPath := filepath.Join(dir, ".dns-helper.lock")
|
lockPath := filepath.Join(dir, ".ekdns.lock")
|
||||||
if _, err := os.Stat(lockPath); os.IsNotExist(err) {
|
if _, err := os.Stat(lockPath); os.IsNotExist(err) {
|
||||||
t.Error("lock file does not exist after Acquire")
|
t.Error("lock file does not exist after Acquire")
|
||||||
}
|
}
|
||||||
@@ -36,7 +36,7 @@ func TestReleaseDeletesLockFile(t *testing.T) {
|
|||||||
t.Fatalf("Release returned unexpected error: %v", err)
|
t.Fatalf("Release returned unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
lockPath := filepath.Join(dir, ".dns-helper.lock")
|
lockPath := filepath.Join(dir, ".ekdns.lock")
|
||||||
if _, err := os.Stat(lockPath); !os.IsNotExist(err) {
|
if _, err := os.Stat(lockPath); !os.IsNotExist(err) {
|
||||||
t.Error("lock file still exists after Release")
|
t.Error("lock file still exists after Release")
|
||||||
}
|
}
|
||||||
@@ -60,7 +60,7 @@ func TestDoubleAcquireFails(t *testing.T) {
|
|||||||
// T006-4: Stale lock file (>2 minutes old) is broken and Acquire succeeds.
|
// T006-4: Stale lock file (>2 minutes old) is broken and Acquire succeeds.
|
||||||
func TestStaleLockBroken(t *testing.T) {
|
func TestStaleLockBroken(t *testing.T) {
|
||||||
dir := t.TempDir()
|
dir := t.TempDir()
|
||||||
lockPath := filepath.Join(dir, ".dns-helper.lock")
|
lockPath := filepath.Join(dir, ".ekdns.lock")
|
||||||
|
|
||||||
// Manually create a lock file with a stale modification time.
|
// Manually create a lock file with a stale modification time.
|
||||||
if err := os.WriteFile(lockPath, []byte("99999\n"), 0644); err != nil {
|
if err := os.WriteFile(lockPath, []byte("99999\n"), 0644); err != nil {
|
||||||
|
|||||||
@@ -8,15 +8,15 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"dns-helper/hostfile"
|
"ekdns/hostfile"
|
||||||
"dns-helper/lockfile"
|
"ekdns/lockfile"
|
||||||
"dns-helper/platform"
|
"ekdns/platform"
|
||||||
"dns-helper/resolver"
|
"ekdns/resolver"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
// Banner (always printed to stdout).
|
// Banner (always printed to stdout).
|
||||||
fmt.Println("DNSHelper v1.0")
|
fmt.Println("ekDNSHelper v1.0")
|
||||||
fmt.Println("Copyright (c) 2024 Emberkom LLC")
|
fmt.Println("Copyright (c) 2024 Emberkom LLC")
|
||||||
fmt.Println("")
|
fmt.Println("")
|
||||||
|
|
||||||
@@ -291,9 +291,9 @@ func printUsage() {
|
|||||||
fmt.Println("Updates the local hosts file with DNS entries resolved by this tool.")
|
fmt.Println("Updates the local hosts file with DNS entries resolved by this tool.")
|
||||||
fmt.Println("")
|
fmt.Println("")
|
||||||
fmt.Println("Usage:")
|
fmt.Println("Usage:")
|
||||||
fmt.Println(" dns-helper add -host <hostnames> [-server <mode>] [-timeout <seconds>] [-verbose]")
|
fmt.Println(" ekdns add -host <hostnames> [-server <mode>] [-timeout <seconds>] [-verbose]")
|
||||||
fmt.Println(" dns-helper delete -host <hostnames>")
|
fmt.Println(" ekdns delete -host <hostnames>")
|
||||||
fmt.Println(" dns-helper delete all")
|
fmt.Println(" ekdns delete all")
|
||||||
fmt.Println("")
|
fmt.Println("")
|
||||||
fmt.Println("Flags (add):")
|
fmt.Println("Flags (add):")
|
||||||
fmt.Println(" -host Comma-separated list of hostnames to resolve and add (required)")
|
fmt.Println(" -host Comma-separated list of hostnames to resolve and add (required)")
|
||||||
@@ -307,19 +307,19 @@ func printUsage() {
|
|||||||
fmt.Println(" -verbose Emit per-stage resolution trace to stderr")
|
fmt.Println(" -verbose Emit per-stage resolution trace to stderr")
|
||||||
fmt.Println("")
|
fmt.Println("")
|
||||||
fmt.Println("Examples:")
|
fmt.Println("Examples:")
|
||||||
fmt.Println(" dns-helper add -host www.example.com")
|
fmt.Println(" ekdns add -host www.example.com")
|
||||||
fmt.Println(" Resolve using smart default (NS fan-out + authoritative query).")
|
fmt.Println(" Resolve using smart default (NS fan-out + authoritative query).")
|
||||||
fmt.Println(" dns-helper add -host internal.client.local -server local")
|
fmt.Println(" ekdns add -host internal.client.local -server local")
|
||||||
fmt.Println(" Resolve using only locally configured DNS resolvers.")
|
fmt.Println(" Resolve using only locally configured DNS resolvers.")
|
||||||
fmt.Println(" dns-helper add -host www.example.com -server gateway")
|
fmt.Println(" ekdns add -host www.example.com -server gateway")
|
||||||
fmt.Println(" Resolve via the default gateway IP.")
|
fmt.Println(" Resolve via the default gateway IP.")
|
||||||
fmt.Println(" dns-helper add -host www.example.com -server 8.8.8.8")
|
fmt.Println(" ekdns add -host www.example.com -server 8.8.8.8")
|
||||||
fmt.Println(" Resolve via a specific DNS server.")
|
fmt.Println(" Resolve via a specific DNS server.")
|
||||||
fmt.Println(" dns-helper add -host www.example.com -server 8.8.8.8:5353 -timeout 5 -verbose")
|
fmt.Println(" ekdns add -host www.example.com -server 8.8.8.8:5353 -timeout 5 -verbose")
|
||||||
fmt.Println(" Resolve via 8.8.8.8:5353 with 5s timeout and verbose trace.")
|
fmt.Println(" Resolve via 8.8.8.8:5353 with 5s timeout and verbose trace.")
|
||||||
fmt.Println(" dns-helper delete -host www.example.com")
|
fmt.Println(" ekdns delete -host www.example.com")
|
||||||
fmt.Println(" Remove all managed entries for www.example.com from the hosts file.")
|
fmt.Println(" Remove all managed entries for www.example.com from the hosts file.")
|
||||||
fmt.Println(" dns-helper delete all")
|
fmt.Println(" ekdns delete all")
|
||||||
fmt.Println(" Remove all managed entries from the hosts file.")
|
fmt.Println(" Remove all managed entries from the hosts file.")
|
||||||
fmt.Println("")
|
fmt.Println("")
|
||||||
fmt.Println("Notes:")
|
fmt.Println("Notes:")
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
package platform_test
|
package platform_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"ekdns/platform"
|
||||||
"errors"
|
"errors"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"dns-helper/platform"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestFakeNetworkDiscoverer_ReturnsInfo(t *testing.T) {
|
func TestFakeNetworkDiscoverer_ReturnsInfo(t *testing.T) {
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
package platform_test
|
package platform_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"ekdns/platform"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"dns-helper/platform"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// T007-1: GetHostsFilePath returns a non-empty path with no error on the current OS.
|
// T007-1: GetHostsFilePath returns a non-empty path with no error on the current OS.
|
||||||
|
|||||||
@@ -2,13 +2,12 @@ package resolver_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"ekdns/resolver"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"dns-helper/resolver"
|
|
||||||
|
|
||||||
"golang.org/x/net/dns/dnsmessage"
|
"golang.org/x/net/dns/dnsmessage"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -2,12 +2,11 @@ package resolver_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"ekdns/resolver"
|
||||||
"io"
|
"io"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"dns-helper/resolver"
|
|
||||||
|
|
||||||
"golang.org/x/net/dns/dnsmessage"
|
"golang.org/x/net/dns/dnsmessage"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -8,7 +8,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"dns-helper/platform"
|
"ekdns/platform"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Resolve performs DNS resolution for hostname using the specified mode and config.
|
// Resolve performs DNS resolution for hostname using the specified mode and config.
|
||||||
@@ -247,7 +247,7 @@ func addPrivateTLDHint(hostname string, origErr error) error {
|
|||||||
tld := strings.ToLower(parts[len(parts)-1])
|
tld := strings.ToLower(parts[len(parts)-1])
|
||||||
if PrivateTLDs[tld] {
|
if PrivateTLDs[tld] {
|
||||||
return fmt.Errorf(
|
return fmt.Errorf(
|
||||||
"%w\n Hint: the hostname uses a private TLD (.%s). Try specifying an internal DNS server:\n dns-helper add -host %s -server <internal-dns-ip>",
|
"%w\n Hint: the hostname uses a private TLD (.%s). Try specifying an internal DNS server:\n ekdns add -host %s -server <internal-dns-ip>",
|
||||||
origErr, tld, hostname)
|
origErr, tld, hostname)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
package resolver_test
|
package resolver_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"ekdns/platform"
|
||||||
|
"ekdns/resolver"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"dns-helper/platform"
|
|
||||||
"dns-helper/resolver"
|
|
||||||
|
|
||||||
"golang.org/x/net/dns/dnsmessage"
|
"golang.org/x/net/dns/dnsmessage"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
package resolver_test
|
package resolver_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"ekdns/resolver"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"dns-helper/resolver"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
package resolver
|
package resolver
|
||||||
|
|
||||||
import "dns-helper/platform"
|
import "ekdns/platform"
|
||||||
|
|
||||||
// BuildResolverPool constructs the ordered list of DNS resolver addresses for
|
// BuildResolverPool constructs the ordered list of DNS resolver addresses for
|
||||||
// the given ServerMode and discovered NetworkInfo.
|
// the given ServerMode and discovered NetworkInfo.
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
package resolver_test
|
package resolver_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"ekdns/platform"
|
||||||
|
"ekdns/resolver"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"dns-helper/platform"
|
|
||||||
"dns-helper/resolver"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestBuildResolverPool(t *testing.T) {
|
func TestBuildResolverPool(t *testing.T) {
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
package resolver_test
|
package resolver_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"ekdns/resolver"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"dns-helper/resolver"
|
|
||||||
|
|
||||||
"golang.org/x/net/dns/dnsmessage"
|
"golang.org/x/net/dns/dnsmessage"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -2,11 +2,10 @@ package resolver_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"ekdns/resolver"
|
||||||
"io"
|
"io"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"dns-helper/resolver"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -2,11 +2,10 @@ package resolver_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"ekdns/resolver"
|
||||||
"net"
|
"net"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"dns-helper/resolver"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user