Ctrl K
ComunidadGuías…

Cargo.toml

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# Virtual workspace root. The binary lives in crates/ferrite; future subsystem
# crates (core, dns, proxy, …) join as siblings under crates/.
[workspace]
resolver = "3"
members = ["crates/*"]
# `cargo build` / `cargo run` at the root build the binary, not every member —
# release CI relies on this (`cargo build --release --target …`).
default-members = ["crates/ferrite"]

[workspace.package]
version = "0.2.0"
edition = "2024"
rust-version = "1.97"
license = "MIT"
authors = ["Korob Labs <opensource@koroblabs.com>"]
repository = "https://github.com/koroblabs/ferrite-server"
# Not on crates.io: ferrite ships as a binary.
publish = false

# One authoritative version/feature spec per dependency; member crates opt in
# with `<name>.workspace = true`.
[workspace.dependencies]
# ── Internal crates ───────────────────────────────────────────────────────────
ferrite-api = { path = "crates/api" }
ferrite-app = { path = "crates/app" }
ferrite-blocklist = { path = "crates/blocklist" }
ferrite-clients = { path = "crates/clients" }
ferrite-core = { path = "crates/core" }
ferrite-dhcp = { path = "crates/dhcp" }
ferrite-secure = { path = "crates/secure" }
ferrite-edge = { path = "crates/edge" }
ferrite-dns = { path = "crates/dns" }
ferrite-proxy = { path = "crates/proxy" }
ferrite-stats = { path = "crates/stats" }
ferrite-storage = { path = "crates/storage" }
ferrite-updater = { path = "crates/updater" }
ferrite-upstream = { path = "crates/upstream" }

# ── Async runtime ─────────────────────────────────────────────────────────────
tokio = { version = "1", features = ["full"] }

# ── DNS ───────────────────────────────────────────────────────────────────────
# Upstream resolution (plain + DoT/DoH/DoQ) and DNS wire-format encode/decode.
hickory-resolver = { version = "0.26.1", features = ["tls-ring", "https-ring", "quic-ring"] }
hickory-proto = "0.26.1"                              # Message/Query/PTR parsing (dns/, clients/resolver)
# Tunneled upstream: ferrite speaks DNS-over-TLS / DNS-over-TCP itself, directly
# over a userspace egress stream (WireGuard/SOCKS5), so its own upstream queries
# can ride the tunnel. hickory/reqwest own their sockets and can't, hence raw TLS.
# default-features off drops rustls's `aws_lc_rs` provider: ring is already in the
# tree (hickory's *-ring features, plus `ring` directly), and pulling aws-lc too
# would compile a second full crypto stack — dead weight in the binary and a C
# toolchain the musl cross-build has to satisfy. See `install_default_crypto`.
tokio-rustls = { version = "0.26", default-features = false, features = ["ring", "tls12", "logging"] }   # TLS client over an arbitrary egress stream (tunneled DoT)
webpki-roots = "1"      # Mozilla root store for tunneled DoT certificate verification
x509-parser = "0.18"    # parse presented certs for the /tools/cert inspector
# Let's Encrypt for encrypted DNS (DNS-01). ring, not the default aws-lc-rs, for the
# same reason as tokio-rustls above; rcgen makes the key and the signing request.
instant-acme = { version = "0.8.5", default-features = false, features = ["ring", "hyper-rustls", "rcgen"] }

# ── HTTP: API server + outbound client ────────────────────────────────────────
axum = { version = "0.8", features = ["macros"] }     # REST API + serves the web UI
# hyper/hyper-util: serve the panel on a single peeked connection so the :80
# listener can demux panel-vs-proxy by Host (already in the tree via axum).
hyper = { version = "1", features = ["server", "http1"] }
http = "1"
# DNS over HTTPS over HTTP/3 (QUIC) for devices; ring, like the rest of TLS.
quinn = { version = "0.11", default-features = false, features = ["runtime-tokio", "rustls-ring"] }
h3 = "0.0.8"
h3-quinn = "0.0.10"
# The relay: a box's own key and self-signed certificate, and its ID.
rcgen = { version = "0.14", default-features = false, features = ["crypto", "ring", "pem", "x509-parser"] }
data-encoding = "2"
hyper-util = { version = "0.1", features = ["tokio", "service"] }
tower-http = { version = "0.6", features = ["cors", "trace"] }  # CORS + request tracing middleware
# `rustls-no-provider` rather than `rustls`: the latter force-enables the aws-lc-rs
# provider (a second crypto stack next to ring). With no provider chosen here,
# reqwest uses the process-wide default that `install_default_crypto` installs.
reqwest = { version = "0.13.4", features = ["rustls-no-provider", "json", "http2"], default-features = false }  # blocklist & update downloads; http2 required for DoH endpoints that reject HTTP/1.1 (e.g. Quad9 → HTTP 505)

# ── Blocklist engine ──────────────────────────────────────────────────────────
fst = "0.4"        # finite-state-transducer set — fast exact-domain blocklist lookups
memmap2 = "0.9"    # serve FSTs from mmap'd files (page cache) instead of anonymous RSS
psl = "2"          # public suffix list (eTLD+1 boundaries)
regex = "1"        # wildcard / adblock-style rule matching (blocklist/engine)

# ── Storage (SQLite) ──────────────────────────────────────────────────────────
rusqlite = { version = "0.37", features = ["bundled"] }  # embedded SQLite — query log, rollups, settings
tokio-rusqlite = "0.7"                                   # async wrapper around rusqlite

# ── Allocator ─────────────────────────────────────────────────────────────────
# musl's malloc retains freed pages and fragments badly under threads (the old
# "RSS grows to 500 MB and never comes back"); mimalloc returns memory to the OS.
mimalloc = "0.1"
# extended: mi_process_info — mimalloc's own committed-memory figure, exposed in
# /api/stats/system so allocator retention is distinguishable from other RSS.
libmimalloc-sys = { version = "0.1", features = ["extended"] }

# ── Caching & concurrent state ────────────────────────────────────────────────
dashmap = "6"        # concurrent maps — client registry, sessions, in-flight resolves
lru = "0.18"         # LRU caches — DNS response cache + blocklist decision cache
arc-swap = "1"       # lock-free hot-swap of the blocklist FST on reload
parking_lot = "0.12" # faster Mutex / RwLock

# ── Serialization ─────────────────────────────────────────────────────────────
serde = { version = "1", features = ["derive"] }
serde_json = "1"     # JSON API payloads
toml = "1"           # config file parsing (config.toml)
postcard = { version = "1", default-features = false, features = ["use-std"] }  # compact binary state snapshots (snapshot/)
chrono = { version = "0.4", features = ["serde"] }  # timestamps
bytes = { version = "1", features = ["serde"] }  # zero-copy byte buffers for DNS wire data (serde: the state snapshot writes them straight out)

# ── Logging ───────────────────────────────────────────────────────────────────
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }

# ── Error handling ────────────────────────────────────────────────────────────
thiserror = "2"   # typed library errors (FeriteError)
anyhow = "1"      # app-level error context

# ── Crypto / auth ─────────────────────────────────────────────────────────────
ring = "0.17"     # secure RNG (DNS query IDs) + SHA checksums (updater) + auth tokens
hex = "0.4"       # lowercase hex for session tokens and checksums (already in the tree via boringtun)
argon2 = "0.5"    # web UI password hashing (Argon2id)
subtle = "2"      # constant-time comparison (API key check)

# ── Networking & system ───────────────────────────────────────────────────────
# "all": SO_MARK (set_mark) for kernel-WG fwmark routing, Linux-only API.
socket2 = { version = "0.6", features = ["all"] }   # low-level socket options (mDNS multicast, SO_MARK)
sysinfo = "0.39"  # CPU / memory / system stats
dirs = "6"        # locate config & data directories

# ── Self-update (download & unpack release archives) ──────────────────────────
flate2 = "1"      # gzip decompression
yaml-rust2 = { version = "0.13", default-features = false }  # reads AdGuardHome.yaml for import
tar = "0.4"       # tar extraction (server binary + web bundle)

# ── WireGuard egress (userspace, in-process; no TUN / no root) ────────────────
boringtun = { version = "0.7.1", default-features = false }  # WireGuard protocol (Noise handshake + transport crypto), no netstack
smoltcp = { version = "0.13", default-features = false, features = ["std", "medium-ip", "proto-ipv4", "proto-ipv6", "socket-tcp", "socket-udp"] }  # userspace TCP/IP stack over the tunnel

# ── Zero-copy relay (Linux-only) ──────────────────────────────────────────────
libc = "0.2"   # splice(2) + pipe2(2): move proxied bytes without a userspace copy

# ── WireGuard egress (kernel backend; Linux-only, CAP_NET_ADMIN) ──────────────
rtnetlink = "0.21"                  # wg netdev / address / route / rule via rtnetlink
genetlink = "0.2.6"                 # generic-netlink family resolution + connection
netlink-packet-generic = "0.4"      # GenlMessage wrapper
netlink-packet-wireguard = "0.4.1"  # WG_CMD_SET/GET_DEVICE messages
netlink-packet-core = "0.8"         # NLM_F_* flags for genl requests
futures-util = { version = "0.3", default-features = false }  # drive netlink response streams

# ── Misc ──────────────────────────────────────────────────────────────────────
async-trait = "0.1"  # async methods in the Storage trait
base64 = "0.22"

# dev-dependencies
tower = "0.5"

[profile.release]
# Line-table debug info: keeps release optimisations but lets gdb show file:line
# in backtraces.  Negligible performance impact; small binary size increase.
debug = 1

# The profile shipped artifacts are built with (`make linux-arm64`, release CI).
# Same optimisations as `release`, but sized for distribution: on a static musl
# build the line tables inherited from `release` dominate the file — 171 MB
# unstripped vs 23 MB stripped for aarch64 — and nobody debugs a released binary
# with gdb. `cargo build --release` keeps its debug info for local work.
#
# `panic` stays at unwind on purpose: with `abort` a panic in one tokio task
# would take the whole DNS server down instead of just that task.
[profile.dist]
inherits = "release"
strip = "symbols"
# Cross-crate inlining shrinks the binary further and is measurably faster;
# "thin" gets nearly all of it for a fraction of "fat"'s link time.
lto = "thin"
codegen-units = 1