Added detailed logging for various configuration changes during hot reload, including log level, ad tag, middle proxy pool size, and user access changes.
Closes#156
- Add handling for -V and --version arguments in CLI parser
- Print version to stdout using CARGO_PKG_VERSION from Cargo.toml
- Update help text to include version option
When IPv6 is unavailable on the host, treat NetworkUnreachable at
connect() as Ok(None) instead of propagating an error, so the dual
STUN probe succeeds with just the IPv4 result and no spurious WARN.
- Users with "scope_{name}" prefix are routed to upstreams where {name}
is present in the "scopes" property (comma-separated).
- Strict separation: Scoped upstreams are excluded from general routing, and vice versa.
- Constraint: SOCKS upstreams and DIRECT(`use_middle_proxy =
false`) mode only.
Example:
User "scope_hello" matches an upstream with `scopes = "world,hello"`
Add new 'announce' field to ListenerConfig that accepts both IP addresses
and hostnames for proxy link generation. The old 'announce_ip' field is
deprecated but still supported via automatic migration.
Changes:
- Add 'announce: Option<String>' field to ListenerConfig
- Add migration logic: announce_ip → announce if announce not set
- Update main.rs to use announce field for link generation
- Support both hostnames (e.g., 'proxy.example.com') and IPs
Backward compatible: existing configs using announce_ip continue to work.
Move all startup output (DC pings, proxy links) from println!() to
info!() for consistent tracing format. Add reload::Layer so startup
messages stay visible even in silent mode.
- Added fire-and-forget ignition via `--init` CLI command:
- New `mod cli;` module handling installation logic
- Extended `parse_cli()` to process `--init` flag (runs synchronously before tokio runtime)
- Expanded `--help` output with installation options
- `--init` command functionality:
- Generates random secret if not provided via `--secret`
- Creates `/etc/telemt/config.toml` from template with user-provided or default parameters (`--port`, `--domain`, `--user`, `--config-dir`)
- Creates hardened systemd unit `/etc/systemd/system/telemt.service` with security features:
- `NoNewPrivileges=true`
- `ProtectSystem=strict`
- `PrivateTmp=true`
- Runs `systemctl enable --now telemt.service`
- Outputs `tg://` proxy links for the running service
- Implementation approach:
- `--init` handled at the very start of `main()` before any async context
- Uses blocking operations throughout (file I/O, `std::process::Command` for systemctl)
- IP detection for tg:// links performed via blocking HTTP request
- Command exits after installation without entering normal proxy runtime
- New CLI parameters for installation:
- `--port` - listening port (default: 443)
- `--domain` - TLS domain (default: auto-detected)
- `--secret` - custom secret (default: randomly generated)
- `--user` - systemd service user (default: telemt)
- `--config-dir` - configuration directory (default: /etc/telemt)
Co-Authored-By: brekotis <93345790+brekotis@users.noreply.github.com>
- Per-DC latency tracking in UpstreamState (array of 5 EMA instances, one per DC):
- Added `dc_latency: [LatencyEma; 5]` – per‑DC tracking instead of a single global EMA
- `effective_latency(dc_idx)` – returns DC‑specific latency, falls back to average if unavailable
- `select_upstream(dc_idx)` – now performs latency‑weighted selection: effective_weight = config_weight × (1000 / latency_ms)
- Example: two upstreams with equal config weight but latencies of 50ms and 200ms → selection probabilities become 80% / 20%
- `connect(target, dc_idx)` – extended signature, dc_idx used for upstream selection and per‑DC RTT recording
- All ping/health‑check operations now record RTT into `dc_latency[dc_zero_index]`
- `upstream_manager.connect(dc_addr)` changed to `upstream_manager.connect(dc_addr, Some(success.dc_idx))` – DC index now participates in upstream selection and per‑DC RTT logging
- `client.rs` – passes dc_idx when connecting to Telegram
- Summary: Upstream selection now accounts for per‑DC latency using the formula weight × (1000/ms). With multiple upstreams (e.g., direct + socks5), traffic automatically flows to the faster route for each specific DC. With a single upstream, the data is used for monitoring without affecting routing.
Co-Authored-By: brekotis <93345790+brekotis@users.noreply.github.com>
- Fix: LruCache::get type ambiguity in stats/mod.rs
- Changed `self.cache.get(&key.into())` to `self.cache.get(key)` (key is already &[u8], resolved via Box<[u8]>: Borrow<[u8]>)
- Changed `self.cache.peek(&key)` / `.pop(&key)` to `.peek(key.as_ref())` / `.pop(key.as_ref())` (explicit &[u8] instead of &Box<[u8]>)
- Startup DC ping with RTT display and improved health-check (all DCs, RTT tracking, EMA latency, 30s interval):
- Implemented `LatencyEma` – exponential moving average (α=0.3) for RTT
- `connect()` – measures RTT of each real connection and updates EMA
- `ping_all_dcs()` – pings all 5 DCs via each upstream, returns `Vec<StartupPingResult>` with RTT or error
- `run_health_checks(prefer_ipv6)` – accepts IPv6 preference parameter, rotates DC between cycles (DC1→DC2→...→DC5→DC1...), interval reduced to 30s from 60s, failed checks now mark upstream as unhealthy after 3 consecutive fails
- `DcPingResult` / `StartupPingResult` – public structures for display
- DC Ping at startup: calls `upstream_manager.ping_all_dcs()` before accept loop, outputs table via `println!` (always visible)
- Health checks with `prefer_ipv6`: `run_health_checks(prefer_ipv6)` receives the parameter
- Exported `StartupPingResult` and `DcPingResult`
- Summary: Startup DC ping with RTT, rotational health-check with EMA latency tracking, 30-second interval, correct unhealthy marking after 3 fails.
Co-Authored-By: brekotis <93345790+brekotis@users.noreply.github.com>