Compare commits
18 Commits
fix/self-r
...
v0.14.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c787de1548 | ||
|
|
e6e79273b9 | ||
|
|
3ec3b40830 | ||
|
|
90fa79bc0f | ||
|
|
b8a125b598 | ||
|
|
bc30be94e7 | ||
|
|
26b1cd5917 | ||
|
|
77d6d89f80 | ||
|
|
4fdd05f284 | ||
|
|
2e461ccc0f | ||
|
|
bf84c44346 | ||
|
|
df2062882c | ||
|
|
76dda89078 | ||
|
|
640b64bf7e | ||
|
|
5ba19e04c8 | ||
|
|
c98afafaa1 | ||
|
|
5cba02a6c8 | ||
|
|
46a95d58aa |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,6 +1,7 @@
|
|||||||
/target
|
/target
|
||||||
/build-dir
|
/build-dir
|
||||||
CLAUDE.md
|
CLAUDE.md
|
||||||
|
.claude/
|
||||||
docs/
|
docs/
|
||||||
site/blog/posts/
|
site/blog/posts/
|
||||||
ios/
|
ios/
|
||||||
|
|||||||
6
Cargo.lock
generated
6
Cargo.lock
generated
@@ -1547,7 +1547,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "numa"
|
name = "numa"
|
||||||
version = "0.14.1"
|
version = "0.14.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arc-swap",
|
"arc-swap",
|
||||||
"axum",
|
"axum",
|
||||||
@@ -2130,9 +2130,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustls-webpki"
|
name = "rustls-webpki"
|
||||||
version = "0.103.12"
|
version = "0.103.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8279bb85272c9f10811ae6a6c547ff594d6a7f3c6c6b02ee9726d1d0dcfcdd06"
|
checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aws-lc-rs",
|
"aws-lc-rs",
|
||||||
"ring",
|
"ring",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "numa"
|
name = "numa"
|
||||||
version = "0.14.1"
|
version = "0.14.2"
|
||||||
authors = ["razvandimescu <razvan@dimescu.com>"]
|
authors = ["razvandimescu <razvan@dimescu.com>"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "Portable DNS resolver in Rust — .numa local domains, ad blocking, developer overrides, DNS-over-HTTPS"
|
description = "Portable DNS resolver in Rust — .numa local domains, ad blocking, developer overrides, DNS-over-HTTPS"
|
||||||
|
|||||||
@@ -125,6 +125,10 @@ docker run -d --name numa --network host \
|
|||||||
|
|
||||||
Multi-arch: `linux/amd64` and `linux/arm64`.
|
Multi-arch: `linux/amd64` and `linux/arm64`.
|
||||||
|
|
||||||
|
Turnkey compose recipes:
|
||||||
|
- [`packaging/client/`](packaging/client/) — ODoH client mode (anonymous DNS), Numa + starter `numa.toml`.
|
||||||
|
- [`packaging/relay/`](packaging/relay/) — public ODoH relay, Numa + Caddy + ACME.
|
||||||
|
|
||||||
## How It Compares
|
## How It Compares
|
||||||
|
|
||||||
| | Pi-hole | AdGuard Home | Unbound | Numa |
|
| | Pi-hole | AdGuard Home | Unbound | Numa |
|
||||||
|
|||||||
29
numa.toml
29
numa.toml
@@ -22,6 +22,7 @@ api_port = 5380
|
|||||||
# [upstream]
|
# [upstream]
|
||||||
# mode = "forward" # "forward" (default) — relay to upstream
|
# mode = "forward" # "forward" (default) — relay to upstream
|
||||||
# # "recursive" — resolve from root hints (no address needed)
|
# # "recursive" — resolve from root hints (no address needed)
|
||||||
|
# # "odoh" — Oblivious DoH (see ODoH block below)
|
||||||
# address = "9.9.9.9" # single upstream (plain UDP)
|
# address = "9.9.9.9" # single upstream (plain UDP)
|
||||||
# address = ["192.168.1.1", "9.9.9.9:5353"] # multiple upstreams — SRTT picks fastest
|
# address = ["192.168.1.1", "9.9.9.9:5353"] # multiple upstreams — SRTT picks fastest
|
||||||
# address = "https://dns.quad9.net/dns-query" # DNS-over-HTTPS (encrypted)
|
# address = "https://dns.quad9.net/dns-query" # DNS-over-HTTPS (encrypted)
|
||||||
@@ -29,11 +30,29 @@ api_port = 5380
|
|||||||
# fallback = ["8.8.8.8", "1.1.1.1"] # tried only when all primaries fail
|
# fallback = ["8.8.8.8", "1.1.1.1"] # tried only when all primaries fail
|
||||||
# port = 53 # default port for addresses without :port
|
# port = 53 # default port for addresses without :port
|
||||||
# timeout_ms = 3000
|
# timeout_ms = 3000
|
||||||
# hedge_ms = 10 # request hedging delay (ms). After this delay
|
# hedge_ms = 0 # request hedging delay (ms). Default: 0 (off).
|
||||||
# # without a response, fires a parallel request
|
# # Set to e.g. 10 to fire a parallel upstream
|
||||||
# # to the same upstream. Rescues packet loss (UDP),
|
# # request after 10ms of silence — rescues packet
|
||||||
# # dispatch spikes (DoH), TLS stalls (DoT).
|
# # loss (UDP), dispatch spikes (DoH), TLS stalls
|
||||||
# # Set to 0 to disable. Default: 10
|
# # (DoT). Doubles the upstream query count, so
|
||||||
|
# # leave off for quota'd providers (NextDNS,
|
||||||
|
# # Control D).
|
||||||
|
|
||||||
|
# ODoH (Oblivious DNS-over-HTTPS, RFC 9230). The relay sees your IP but
|
||||||
|
# not the question; the target sees the question but not your IP. Numa
|
||||||
|
# refuses same-operator relay+target configs by default (eTLD+1 check).
|
||||||
|
# [upstream]
|
||||||
|
# mode = "odoh"
|
||||||
|
# relay = "https://odoh-relay.numa.rs/proxy"
|
||||||
|
# target = "https://odoh.cloudflare-dns.com/dns-query"
|
||||||
|
# strict = true # default: refuse to downgrade to `fallback`
|
||||||
|
# # on relay failure. Set false to allow a
|
||||||
|
# # non-oblivious fallback path.
|
||||||
|
# relay_ip = "178.104.229.30" # optional: pin IPs so numa doesn't leak the
|
||||||
|
# target_ip = "104.16.249.249" # relay/target hostnames via the bootstrap
|
||||||
|
# # resolver on cold boot when numa is its
|
||||||
|
# # own system DNS. See docs/implementation/
|
||||||
|
# # bootstrap-resolver.md.
|
||||||
# root_hints = [ # only used in recursive mode
|
# root_hints = [ # only used in recursive mode
|
||||||
# "198.41.0.4", # a.root-servers.net (Verisign)
|
# "198.41.0.4", # a.root-servers.net (Verisign)
|
||||||
# "199.9.14.201", # b.root-servers.net (USC-ISI)
|
# "199.9.14.201", # b.root-servers.net (USC-ISI)
|
||||||
|
|||||||
72
packaging/client/README.md
Normal file
72
packaging/client/README.md
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
# Numa ODoH Client — Docker deploy
|
||||||
|
|
||||||
|
Single-container deploy that runs Numa as an ODoH (RFC 9230) client: every
|
||||||
|
DNS query routes through an independent relay + target so neither operator
|
||||||
|
sees both your IP and your question. See the [ODoH integration doc][odoh]
|
||||||
|
for the full protocol and privacy trade-offs.
|
||||||
|
|
||||||
|
[odoh]: ../../docs/implementation/odoh-integration.md
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- Docker + Docker Compose v2.
|
||||||
|
- Port 53 (UDP+TCP) free on the host — Numa listens there for DNS
|
||||||
|
clients on your LAN.
|
||||||
|
|
||||||
|
## Configure
|
||||||
|
|
||||||
|
The shipped `numa.toml` points at Numa's own public relay
|
||||||
|
(`odoh-relay.numa.rs`) paired with Cloudflare's ODoH target
|
||||||
|
(`odoh.cloudflare-dns.com`). That's two independent operators with
|
||||||
|
distinct eTLD+1s — the default configuration passes Numa's same-operator
|
||||||
|
check and works out of the box.
|
||||||
|
|
||||||
|
To use a different relay or target, edit `numa.toml` and adjust the URLs.
|
||||||
|
The `relay` and `target` must resolve to distinct operators or Numa
|
||||||
|
refuses to start.
|
||||||
|
|
||||||
|
## Deploy
|
||||||
|
|
||||||
|
```sh
|
||||||
|
docker compose up -d
|
||||||
|
docker compose logs -f numa # watch startup
|
||||||
|
```
|
||||||
|
|
||||||
|
The first query fires the bootstrap resolver + ODoH config fetch;
|
||||||
|
subsequent queries reuse the warm HTTP/2 connection.
|
||||||
|
|
||||||
|
## Point your devices at it
|
||||||
|
|
||||||
|
Set each device's DNS server to the IP of the Docker host. For a LAN-wide
|
||||||
|
rollout, set the DNS server in your router's DHCP config so every device
|
||||||
|
picks it up automatically.
|
||||||
|
|
||||||
|
Verify a query landed on the ODoH path:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
dig @<host-ip> example.com
|
||||||
|
curl http://<host-ip>:5380/stats | jq '.upstream_transport.odoh'
|
||||||
|
```
|
||||||
|
|
||||||
|
`upstream_transport.odoh` should increment on each query.
|
||||||
|
|
||||||
|
## What this does NOT buy you
|
||||||
|
|
||||||
|
ODoH protects the *path*, not the content:
|
||||||
|
|
||||||
|
- **The target (Cloudflare here) still sees the question.** It just
|
||||||
|
doesn't know it's you asking. If Cloudflare logs every ODoH query, the
|
||||||
|
query is still visible — it's simply unattributed.
|
||||||
|
- **The relay is a trusted party for availability.** A malicious relay
|
||||||
|
can drop or delay queries; it just can't read them.
|
||||||
|
- **Traffic analysis defeats small relays.** If you're the only client
|
||||||
|
talking to a relay, timing alone re-identifies you. Shared, busy relays
|
||||||
|
give better anonymity sets.
|
||||||
|
|
||||||
|
See the [ODoH integration doc][odoh] for more.
|
||||||
|
|
||||||
|
## Relay operator?
|
||||||
|
|
||||||
|
If you'd rather run your own relay (same binary, different mode), see
|
||||||
|
[`../relay/`](../relay/) — that package spins up a public-facing relay
|
||||||
|
with Caddy + ACME in front of it.
|
||||||
15
packaging/client/docker-compose.yml
Normal file
15
packaging/client/docker-compose.yml
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
services:
|
||||||
|
numa:
|
||||||
|
image: ghcr.io/razvandimescu/numa:latest
|
||||||
|
command: ["/etc/numa/numa.toml"]
|
||||||
|
ports:
|
||||||
|
- "53:53/udp"
|
||||||
|
- "53:53/tcp"
|
||||||
|
- "5380:5380/tcp" # dashboard + REST API
|
||||||
|
volumes:
|
||||||
|
- ./numa.toml:/etc/numa/numa.toml:ro
|
||||||
|
- numa_data:/var/lib/numa
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
numa_data:
|
||||||
23
packaging/client/numa.toml
Normal file
23
packaging/client/numa.toml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
# Numa — ODoH client mode (docker-compose starter).
|
||||||
|
# Sends every DNS query through an independent relay + target pair so
|
||||||
|
# neither operator sees both your IP and your question. See
|
||||||
|
# docs/implementation/odoh-integration.md for the protocol details and
|
||||||
|
# packaging/client/README.md for deploy notes.
|
||||||
|
|
||||||
|
[server]
|
||||||
|
bind_addr = "0.0.0.0:53"
|
||||||
|
api_bind_addr = "0.0.0.0"
|
||||||
|
data_dir = "/var/lib/numa"
|
||||||
|
|
||||||
|
[upstream]
|
||||||
|
mode = "odoh"
|
||||||
|
# Numa's own relay (Hetzner, systemd + Caddy). Swap to any other public
|
||||||
|
# ODoH relay if you'd rather not depend on a single operator; the protocol
|
||||||
|
# tolerates it, and Numa refuses same-operator relay+target by default.
|
||||||
|
relay = "https://odoh-relay.numa.rs/relay"
|
||||||
|
target = "https://odoh.cloudflare-dns.com/dns-query"
|
||||||
|
# strict = true (default). Relay failure → SERVFAIL, never silent downgrade.
|
||||||
|
|
||||||
|
[blocking]
|
||||||
|
enabled = true
|
||||||
|
# Default blocklist (Hagezi Pro). Edit the `lists` array to taste.
|
||||||
@@ -1,14 +1,41 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
# Dev server for site/: regenerates drafts on each MD change, reloads the
|
||||||
|
# browser on each rendered HTML/CSS/JS change. Port is the first numeric arg
|
||||||
|
# (default 9000); any other args are ignored for back-compat.
|
||||||
|
#
|
||||||
|
# First run downloads chokidar-cli + browser-sync into the npm cache — slow
|
||||||
|
# once, instant after that.
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
PORT="${1:-9000}"
|
PORT=9000
|
||||||
|
for arg in "$@"; do
|
||||||
if [[ "${1:-}" == "--drafts" ]] || [[ "${2:-}" == "--drafts" ]]; then
|
if [[ "$arg" =~ ^[0-9]+$ ]]; then
|
||||||
PORT="${PORT//--drafts/9000}" # default port if --drafts was first arg
|
PORT="$arg"
|
||||||
make blog-drafts
|
break
|
||||||
else
|
|
||||||
make blog
|
|
||||||
fi
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
echo "Serving site at http://localhost:$PORT"
|
command -v npx >/dev/null || { echo "npx not found. Install Node.js: https://nodejs.org" >&2; exit 1; }
|
||||||
cd site && python3 -m http.server "$PORT"
|
command -v pandoc >/dev/null || { echo "pandoc not found (required by 'make blog-drafts')." >&2; exit 1; }
|
||||||
|
|
||||||
|
# Initial render so the first page load has everything.
|
||||||
|
make blog-drafts
|
||||||
|
|
||||||
|
echo "Serving site at http://localhost:$PORT (drafts included, live reload)"
|
||||||
|
|
||||||
|
# Kill child processes on exit so re-runs don't leave orphaned watchers.
|
||||||
|
trap 'kill $(jobs -p) 2>/dev/null' EXIT INT TERM
|
||||||
|
|
||||||
|
# Regenerate HTML when MD sources or the blog template change.
|
||||||
|
npx --yes chokidar-cli \
|
||||||
|
"drafts/*.md" "blog/*.md" "site/blog-template.html" \
|
||||||
|
-c "make blog-drafts" &
|
||||||
|
|
||||||
|
# Serve + reload on rendered-asset changes.
|
||||||
|
cd site && exec npx --yes browser-sync start \
|
||||||
|
--server . \
|
||||||
|
--port "$PORT" \
|
||||||
|
--files "**/*.html,**/*.css,**/*.js" \
|
||||||
|
--no-open \
|
||||||
|
--no-notify
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
//! servers, with TCP fallback on UDP timeout (for networks that block
|
//! servers, with TCP fallback on UDP timeout (for networks that block
|
||||||
//! outbound UDP:53 — see memory: `project_network_udp_hostile.md`).
|
//! outbound UDP:53 — see memory: `project_network_udp_hostile.md`).
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::BTreeMap;
|
||||||
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
@@ -34,7 +34,7 @@ const DEFAULT_BOOTSTRAP: &[SocketAddr] = &[
|
|||||||
|
|
||||||
pub struct NumaResolver {
|
pub struct NumaResolver {
|
||||||
bootstrap: Vec<SocketAddr>,
|
bootstrap: Vec<SocketAddr>,
|
||||||
overrides: HashMap<String, Vec<IpAddr>>,
|
overrides: BTreeMap<String, Vec<IpAddr>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NumaResolver {
|
impl NumaResolver {
|
||||||
@@ -44,7 +44,7 @@ impl NumaResolver {
|
|||||||
/// `fallback` entries are filtered to IP literals only — hostnames would
|
/// `fallback` entries are filtered to IP literals only — hostnames would
|
||||||
/// re-introduce the self-loop inside the resolver itself. Empty or
|
/// re-introduce the self-loop inside the resolver itself. Empty or
|
||||||
/// unusable fallback yields the hardcoded default (Quad9 + Cloudflare).
|
/// unusable fallback yields the hardcoded default (Quad9 + Cloudflare).
|
||||||
pub fn new(fallback: &[String], overrides: HashMap<String, Vec<IpAddr>>) -> Self {
|
pub fn new(fallback: &[String], overrides: BTreeMap<String, Vec<IpAddr>>) -> Self {
|
||||||
let mut bootstrap: Vec<SocketAddr> = Vec::with_capacity(fallback.len());
|
let mut bootstrap: Vec<SocketAddr> = Vec::with_capacity(fallback.len());
|
||||||
for entry in fallback {
|
for entry in fallback {
|
||||||
match crate::forward::parse_upstream_addr(entry, 53) {
|
match crate::forward::parse_upstream_addr(entry, 53) {
|
||||||
@@ -71,11 +71,10 @@ impl NumaResolver {
|
|||||||
source
|
source
|
||||||
);
|
);
|
||||||
if !overrides.is_empty() {
|
if !overrides.is_empty() {
|
||||||
let mut pairs: Vec<String> = overrides
|
let pairs: Vec<String> = overrides
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|(host, ips)| ips.iter().map(move |ip| format!("{}={}", host, ip)))
|
.flat_map(|(host, addrs)| addrs.iter().map(move |ip| format!("{}={}", host, ip)))
|
||||||
.collect();
|
.collect();
|
||||||
pairs.sort();
|
|
||||||
info!(
|
info!(
|
||||||
"bootstrap resolver: host overrides (skip DNS, connect direct): {}",
|
"bootstrap resolver: host overrides (skip DNS, connect direct): {}",
|
||||||
pairs.join(", ")
|
pairs.join(", ")
|
||||||
@@ -185,7 +184,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn empty_fallback_uses_defaults() {
|
fn empty_fallback_uses_defaults() {
|
||||||
let r = NumaResolver::new(&[], HashMap::new());
|
let r = NumaResolver::new(&[], BTreeMap::new());
|
||||||
let got: Vec<String> = r.bootstrap().iter().map(|s| s.to_string()).collect();
|
let got: Vec<String> = r.bootstrap().iter().map(|s| s.to_string()).collect();
|
||||||
assert_eq!(got, vec!["9.9.9.9:53", "1.1.1.1:53"]);
|
assert_eq!(got, vec!["9.9.9.9:53", "1.1.1.1:53"]);
|
||||||
}
|
}
|
||||||
@@ -197,14 +196,14 @@ mod tests {
|
|||||||
"dns.quad9.net".to_string(),
|
"dns.quad9.net".to_string(),
|
||||||
"1.1.1.1:5353".to_string(),
|
"1.1.1.1:5353".to_string(),
|
||||||
];
|
];
|
||||||
let r = NumaResolver::new(&fallback, HashMap::new());
|
let r = NumaResolver::new(&fallback, BTreeMap::new());
|
||||||
let got: Vec<String> = r.bootstrap().iter().map(|s| s.to_string()).collect();
|
let got: Vec<String> = r.bootstrap().iter().map(|s| s.to_string()).collect();
|
||||||
assert_eq!(got, vec!["9.9.9.9:53", "1.1.1.1:5353"]);
|
assert_eq!(got, vec!["9.9.9.9:53", "1.1.1.1:5353"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn override_returns_configured_ips_without_dns() {
|
fn override_returns_configured_ips_without_dns() {
|
||||||
let mut overrides = HashMap::new();
|
let mut overrides = BTreeMap::new();
|
||||||
overrides.insert(
|
overrides.insert(
|
||||||
"odoh-relay.example".to_string(),
|
"odoh-relay.example".to_string(),
|
||||||
vec![IpAddr::V4(Ipv4Addr::new(178, 104, 229, 30))],
|
vec![IpAddr::V4(Ipv4Addr::new(178, 104, 229, 30))],
|
||||||
@@ -220,7 +219,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn override_supports_multiple_ips_including_ipv6() {
|
fn override_supports_multiple_ips_including_ipv6() {
|
||||||
let mut overrides = HashMap::new();
|
let mut overrides = BTreeMap::new();
|
||||||
overrides.insert(
|
overrides.insert(
|
||||||
"dual.example".to_string(),
|
"dual.example".to_string(),
|
||||||
vec![
|
vec![
|
||||||
|
|||||||
@@ -245,8 +245,8 @@ impl OdohUpstream {
|
|||||||
/// Per-host IP overrides for the bootstrap resolver, lifted from
|
/// Per-host IP overrides for the bootstrap resolver, lifted from
|
||||||
/// `relay_ip`/`target_ip`. Keeps the "zero plain-DNS leak for ODoH
|
/// `relay_ip`/`target_ip`. Keeps the "zero plain-DNS leak for ODoH
|
||||||
/// endpoints" property when numa is its own system resolver.
|
/// endpoints" property when numa is its own system resolver.
|
||||||
pub fn host_ip_overrides(&self) -> std::collections::HashMap<String, Vec<std::net::IpAddr>> {
|
pub fn host_ip_overrides(&self) -> std::collections::BTreeMap<String, Vec<std::net::IpAddr>> {
|
||||||
let mut out = std::collections::HashMap::new();
|
let mut out = std::collections::BTreeMap::new();
|
||||||
if let Some(addr) = self.relay_bootstrap {
|
if let Some(addr) = self.relay_bootstrap {
|
||||||
out.entry(self.relay_host.clone())
|
out.entry(self.relay_host.clone())
|
||||||
.or_insert_with(Vec::new)
|
.or_insert_with(Vec::new)
|
||||||
@@ -451,8 +451,12 @@ fn default_upstream_port() -> u16 {
|
|||||||
fn default_timeout_ms() -> u64 {
|
fn default_timeout_ms() -> u64 {
|
||||||
5000
|
5000
|
||||||
}
|
}
|
||||||
|
/// Off by default: hedging fires a second upstream query, which silently
|
||||||
|
/// doubles the count at the provider — hurts quota'd DNS (NextDNS, Control
|
||||||
|
/// D). Opt in with `hedge_ms = 10` for tail-latency rescue on flaky nets
|
||||||
|
/// or handshake-slow DoT.
|
||||||
fn default_hedge_ms() -> u64 {
|
fn default_hedge_ms() -> u64 {
|
||||||
10
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ pub async fn run(config_path: String) -> crate::Result<()> {
|
|||||||
.odoh_upstream()
|
.odoh_upstream()
|
||||||
.map(|o| o.host_ip_overrides())
|
.map(|o| o.host_ip_overrides())
|
||||||
.unwrap_or_default(),
|
.unwrap_or_default(),
|
||||||
_ => std::collections::HashMap::new(),
|
_ => std::collections::BTreeMap::new(),
|
||||||
};
|
};
|
||||||
let bootstrap_resolver: Arc<NumaResolver> = Arc::new(NumaResolver::new(
|
let bootstrap_resolver: Arc<NumaResolver> = Arc::new(NumaResolver::new(
|
||||||
&config.upstream.fallback,
|
&config.upstream.fallback,
|
||||||
|
|||||||
@@ -975,11 +975,10 @@ check "Same-host relay+target rejected at startup" \
|
|||||||
"same host" \
|
"same host" \
|
||||||
"$STARTUP_OUT"
|
"$STARTUP_OUT"
|
||||||
|
|
||||||
# relay_ip / target_ip must land in the bootstrap resolver's override map,
|
# Guards ODoH's zero-plain-DNS-leak property: relay_ip / target_ip must
|
||||||
# so reqwest connects direct to the configured IPs instead of resolving the
|
# land in the bootstrap resolver's override map so reqwest connects direct
|
||||||
# hostnames via plain DNS (ODoH's zero-plain-DNS-leak property). Using
|
# to the configured IPs instead of resolving the hostnames via plain DNS.
|
||||||
# RFC 5737 TEST-NET-1 IPs — never routable, so the OdohConfigCache won't
|
# RFC 5737 TEST-NET-1 IPs (unroutable).
|
||||||
# actually connect, but the override-map wiring is visible in the startup log.
|
|
||||||
cat > "$CONFIG" << 'CONF'
|
cat > "$CONFIG" << 'CONF'
|
||||||
[server]
|
[server]
|
||||||
bind_addr = "127.0.0.1:5354"
|
bind_addr = "127.0.0.1:5354"
|
||||||
@@ -1019,7 +1018,6 @@ check "target_ip wired into bootstrap override map" \
|
|||||||
|
|
||||||
kill "$NUMA_PID" 2>/dev/null || true
|
kill "$NUMA_PID" 2>/dev/null || true
|
||||||
wait "$NUMA_PID" 2>/dev/null || true
|
wait "$NUMA_PID" 2>/dev/null || true
|
||||||
sleep 1
|
|
||||||
|
|
||||||
fi # end Suite 8
|
fi # end Suite 8
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user