mirror of
https://github.com/telemt/telemt.git
synced 2026-04-17 18:44:10 +03:00
Merge pull request #695 from vladon/fix/windows-run-inner-issue-690
fix(maestro): restore Windows build after cfg split (fixes #690)
This commit is contained in:
@@ -25,6 +25,7 @@ curl -fsSL https://raw.githubusercontent.com/telemt/telemt/main/install.sh | sh
|
|||||||
- [Quick Start Guide](docs/Quick_start/QUICK_START_GUIDE.en.md)
|
- [Quick Start Guide](docs/Quick_start/QUICK_START_GUIDE.en.md)
|
||||||
- [Инструкция по быстрому запуску](docs/Quick_start/QUICK_START_GUIDE.ru.md)
|
- [Инструкция по быстрому запуску](docs/Quick_start/QUICK_START_GUIDE.ru.md)
|
||||||
|
|
||||||
|
## Features
|
||||||
Our implementation of **TLS-fronting** is one of the most deeply debugged, focused, advanced and *almost* **"behaviorally consistent to real"**: we are confident we have it right - [see evidence on our validation and traces](docs/FAQ.en.md#recognizability-for-dpi-and-crawler)
|
Our implementation of **TLS-fronting** is one of the most deeply debugged, focused, advanced and *almost* **"behaviorally consistent to real"**: we are confident we have it right - [see evidence on our validation and traces](docs/FAQ.en.md#recognizability-for-dpi-and-crawler)
|
||||||
|
|
||||||
Our ***Middle-End Pool*** is fastest by design in standard scenarios, compared to other implementations of connecting to the Middle-End Proxy: non dramatically, but usual
|
Our ***Middle-End Pool*** is fastest by design in standard scenarios, compared to other implementations of connecting to the Middle-End Proxy: non dramatically, but usual
|
||||||
|
|||||||
@@ -54,7 +54,6 @@ curl -fsSL https://raw.githubusercontent.com/telemt/telemt/main/install.sh | sh
|
|||||||
- [FAQ EN](docs/FAQ.en.md)
|
- [FAQ EN](docs/FAQ.en.md)
|
||||||
|
|
||||||
## Сборка
|
## Сборка
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Клонируйте репозиторий
|
# Клонируйте репозиторий
|
||||||
git clone https://github.com/telemt/telemt
|
git clone https://github.com/telemt/telemt
|
||||||
@@ -63,7 +62,6 @@ cd telemt
|
|||||||
# Начните процесс сборки
|
# Начните процесс сборки
|
||||||
cargo build --release
|
cargo build --release
|
||||||
|
|
||||||
# Устройства с небольшим объёмом оперативной памяти (1 ГБ, например NanoPi Neo3 / Raspberry Pi Zero 2):
|
|
||||||
# В текущем release-профиле используется lto = "fat" для максимальной оптимизации (см. Cargo.toml).
|
# В текущем release-профиле используется lto = "fat" для максимальной оптимизации (см. Cargo.toml).
|
||||||
# На системах с малым объёмом RAM (~1 ГБ) можно переопределить это значение на "thin".
|
# На системах с малым объёмом RAM (~1 ГБ) можно переопределить это значение на "thin".
|
||||||
|
|
||||||
|
|||||||
11
config.toml
11
config.toml
@@ -32,13 +32,13 @@ show = "*"
|
|||||||
port = 443
|
port = 443
|
||||||
# proxy_protocol = false # Enable if behind HAProxy/nginx with PROXY protocol
|
# proxy_protocol = false # Enable if behind HAProxy/nginx with PROXY protocol
|
||||||
# metrics_port = 9090
|
# metrics_port = 9090
|
||||||
# metrics_listen = "0.0.0.0:9090" # Listen address for metrics (overrides metrics_port)
|
# metrics_listen = "127.0.0.1:9090" # Listen address for metrics (overrides metrics_port)
|
||||||
# metrics_whitelist = ["127.0.0.1", "::1", "0.0.0.0/0"]
|
# metrics_whitelist = ["127.0.0.1/32", "::1/128"]
|
||||||
|
|
||||||
[server.api]
|
[server.api]
|
||||||
enabled = true
|
enabled = true
|
||||||
listen = "0.0.0.0:9091"
|
listen = "127.0.0.1:9091"
|
||||||
whitelist = ["127.0.0.0/8"]
|
whitelist = ["127.0.0.1/32", "::1/128"]
|
||||||
minimal_runtime_enabled = false
|
minimal_runtime_enabled = false
|
||||||
minimal_runtime_cache_ttl_ms = 1000
|
minimal_runtime_cache_ttl_ms = 1000
|
||||||
|
|
||||||
@@ -48,7 +48,10 @@ ip = "0.0.0.0"
|
|||||||
|
|
||||||
# === Anti-Censorship & Masking ===
|
# === Anti-Censorship & Masking ===
|
||||||
[censorship]
|
[censorship]
|
||||||
|
# Fake-TLS / SNI masking domain used in generated ee-links.
|
||||||
|
# Changing tls_domain invalidates previously generated TLS links.
|
||||||
tls_domain = "petrovich.ru"
|
tls_domain = "petrovich.ru"
|
||||||
|
|
||||||
mask = true
|
mask = true
|
||||||
tls_emulation = true # Fetch real cert lengths and emulate TLS records
|
tls_emulation = true # Fetch real cert lengths and emulate TLS records
|
||||||
tls_front_dir = "tlsfront" # Cache directory for TLS emulation
|
tls_front_dir = "tlsfront" # Cache directory for TLS emulation
|
||||||
|
|||||||
@@ -9,12 +9,12 @@ API runtime is configured in `[server.api]`.
|
|||||||
|
|
||||||
| Field | Type | Default | Description |
|
| Field | Type | Default | Description |
|
||||||
| --- | --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
| `enabled` | `bool` | `false` | Enables REST API listener. |
|
| `enabled` | `bool` | `true` | Enables REST API listener. |
|
||||||
| `listen` | `string` (`IP:PORT`) | `127.0.0.1:9091` | API bind address. |
|
| `listen` | `string` (`IP:PORT`) | `0.0.0.0:9091` | API bind address. |
|
||||||
| `whitelist` | `CIDR[]` | `127.0.0.1/32, ::1/128` | Source IP allowlist. Empty list means allow all. |
|
| `whitelist` | `CIDR[]` | `127.0.0.0/8` | Source IP allowlist. Empty list means allow all. |
|
||||||
| `auth_header` | `string` | `""` | Exact value for `Authorization` header. Empty disables header auth. |
|
| `auth_header` | `string` | `""` | Exact value for `Authorization` header. Empty disables header auth. |
|
||||||
| `request_body_limit_bytes` | `usize` | `65536` | Maximum request body size. Must be `> 0`. |
|
| `request_body_limit_bytes` | `usize` | `65536` | Maximum request body size. Must be `> 0`. |
|
||||||
| `minimal_runtime_enabled` | `bool` | `false` | Enables runtime snapshot endpoints requiring ME pool read-lock aggregation. |
|
| `minimal_runtime_enabled` | `bool` | `true` | Enables runtime snapshot endpoints requiring ME pool read-lock aggregation. |
|
||||||
| `minimal_runtime_cache_ttl_ms` | `u64` | `1000` | Cache TTL for minimal snapshots. `0` disables cache; valid range is `[0, 60000]`. |
|
| `minimal_runtime_cache_ttl_ms` | `u64` | `1000` | Cache TTL for minimal snapshots. `0` disables cache; valid range is `[0, 60000]`. |
|
||||||
| `runtime_edge_enabled` | `bool` | `false` | Enables runtime edge endpoints with cached aggregation payloads. |
|
| `runtime_edge_enabled` | `bool` | `false` | Enables runtime edge endpoints with cached aggregation payloads. |
|
||||||
| `runtime_edge_cache_ttl_ms` | `u64` | `1000` | Cache TTL for runtime edge summary payloads. `0` disables cache. |
|
| `runtime_edge_cache_ttl_ms` | `u64` | `1000` | Cache TTL for runtime edge summary payloads. `0` disables cache. |
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -27,7 +27,8 @@ cargo build --release
|
|||||||
./target/release/telemt --version
|
./target/release/telemt --version
|
||||||
```
|
```
|
||||||
|
|
||||||
For low-RAM systems, this repository already uses `lto = "thin"` in release profile.
|
For low-RAM systems, note that this repository currently uses `lto = "fat"` in release profile.
|
||||||
|
On constrained builders, a local override to `lto = "thin"` may be more practical.
|
||||||
|
|
||||||
## 3. Install binary and config
|
## 3. Install binary and config
|
||||||
|
|
||||||
|
|||||||
@@ -112,13 +112,13 @@ show = "*"
|
|||||||
port = 443
|
port = 443
|
||||||
# proxy_protocol = false # Enable if behind HAProxy/nginx with PROXY protocol
|
# proxy_protocol = false # Enable if behind HAProxy/nginx with PROXY protocol
|
||||||
# metrics_port = 9090
|
# metrics_port = 9090
|
||||||
# metrics_listen = "0.0.0.0:9090" # Listen address for metrics (overrides metrics_port)
|
# metrics_listen = "127.0.0.1:9090" # Listen address for metrics (overrides metrics_port)
|
||||||
# metrics_whitelist = ["127.0.0.1", "::1", "0.0.0.0/0"]
|
# metrics_whitelist = ["127.0.0.1/32", "::1/128"]
|
||||||
|
|
||||||
[server.api]
|
[server.api]
|
||||||
enabled = true
|
enabled = true
|
||||||
listen = "0.0.0.0:9091"
|
listen = "127.0.0.1:9091"
|
||||||
whitelist = ["127.0.0.0/8"]
|
whitelist = ["127.0.0.1/32", "::1/128"]
|
||||||
minimal_runtime_enabled = false
|
minimal_runtime_enabled = false
|
||||||
minimal_runtime_cache_ttl_ms = 1000
|
minimal_runtime_cache_ttl_ms = 1000
|
||||||
|
|
||||||
@@ -128,7 +128,7 @@ ip = "0.0.0.0"
|
|||||||
|
|
||||||
# === Anti-Censorship & Masking ===
|
# === Anti-Censorship & Masking ===
|
||||||
[censorship]
|
[censorship]
|
||||||
tls_domain = "petrovich.ru"
|
tls_domain = "petrovich.ru" # Fake-TLS / SNI masking domain used in generated ee-links
|
||||||
mask = true
|
mask = true
|
||||||
tls_emulation = true # Fetch real cert lengths and emulate TLS records
|
tls_emulation = true # Fetch real cert lengths and emulate TLS records
|
||||||
tls_front_dir = "tlsfront" # Cache directory for TLS emulation
|
tls_front_dir = "tlsfront" # Cache directory for TLS emulation
|
||||||
@@ -141,9 +141,9 @@ hello = "00000000000000000000000000000000"
|
|||||||
then Ctrl+S -> Ctrl+X to save
|
then Ctrl+S -> Ctrl+X to save
|
||||||
|
|
||||||
> [!WARNING]
|
> [!WARNING]
|
||||||
> Replace the value of the hello parameter with the value you obtained in step 0.
|
> Replace the value of the `hello` parameter with the value you obtained in step 0.
|
||||||
> Additionally, change the value of the tls_domain parameter to a different website.
|
> Additionally, change the value of the `tls_domain` parameter to a different website.
|
||||||
> Changing the tls_domain parameter will break all links that use the old domain!
|
> Changing the `tls_domain` parameter will break all links that use the old domain!
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -103,22 +103,22 @@ tls = true
|
|||||||
[general.links]
|
[general.links]
|
||||||
show = "*"
|
show = "*"
|
||||||
# show = ["alice", "bob"] # Показывать ссылки только для alice и bob
|
# show = ["alice", "bob"] # Показывать ссылки только для alice и bob
|
||||||
# show = "*" # Показывать ссылки для всех пользователей
|
# show = "*" # Показывать ссылки для всех пользователей
|
||||||
# public_host = "proxy.example.com" # Хост (IP-адрес или домен) для ссылок tg://
|
# public_host = "proxy.example.com" # Хост (IP-адрес или домен) для ссылок tg://
|
||||||
# public_port = 443 # Порт для ссылок tg:// (по умолчанию: server.port)
|
# public_port = 443 # Порт для ссылок tg:// (по умолчанию: server.port)
|
||||||
|
|
||||||
# === Привязка сервера ===
|
# === Привязка сервера ===
|
||||||
[server]
|
[server]
|
||||||
port = 443
|
port = 443
|
||||||
# proxy_protocol = false # Включите, если сервер находится за HAProxy/nginx с протоколом PROXY
|
# proxy_protocol = false # Включите, если сервер находится за HAProxy/nginx с протоколом PROXY
|
||||||
# metrics_port = 9090
|
# metrics_port = 9090
|
||||||
# metrics_listen = "0.0.0.0:9090" # Адрес прослушивания для метрик (переопределяет metrics_port)
|
# metrics_listen = "127.0.0.1:9090" # Адрес прослушивания для метрик (переопределяет metrics_port)
|
||||||
# metrics_whitelist = ["127.0.0.1", "::1", "0.0.0.0/0"]
|
# metrics_whitelist = ["127.0.0.1/32", "::1/128"]
|
||||||
|
|
||||||
[server.api]
|
[server.api]
|
||||||
enabled = true
|
enabled = true
|
||||||
listen = "0.0.0.0:9091"
|
listen = "127.0.0.1:9091"
|
||||||
whitelist = ["127.0.0.0/8"]
|
whitelist = ["127.0.0.1/32", "::1/128"]
|
||||||
minimal_runtime_enabled = false
|
minimal_runtime_enabled = false
|
||||||
minimal_runtime_cache_ttl_ms = 1000
|
minimal_runtime_cache_ttl_ms = 1000
|
||||||
|
|
||||||
@@ -128,7 +128,7 @@ ip = "0.0.0.0"
|
|||||||
|
|
||||||
# === Обход блокировок и маскировка ===
|
# === Обход блокировок и маскировка ===
|
||||||
[censorship]
|
[censorship]
|
||||||
tls_domain = "petrovich.ru"
|
tls_domain = "petrovich.ru" # Домен Fake-TLS / SNI, который будет использоваться в сгенерированных ee-ссылках
|
||||||
mask = true
|
mask = true
|
||||||
tls_emulation = true # Получить реальную длину сертификата и эмулировать запись TLS
|
tls_emulation = true # Получить реальную длину сертификата и эмулировать запись TLS
|
||||||
tls_front_dir = "tlsfront" # Директория кэша для эмуляции TLS
|
tls_front_dir = "tlsfront" # Директория кэша для эмуляции TLS
|
||||||
@@ -141,9 +141,9 @@ hello = "00000000000000000000000000000000"
|
|||||||
Затем нажмите Ctrl+S -> Ctrl+X, чтобы сохранить
|
Затем нажмите Ctrl+S -> Ctrl+X, чтобы сохранить
|
||||||
|
|
||||||
> [!WARNING]
|
> [!WARNING]
|
||||||
> Замените значение параметра hello на значение, которое вы получили в пункте 0.
|
> Замените значение параметра `hello` на значение, которое вы получили в пункте 0.
|
||||||
> Так же замените значение параметра tls_domain на другой сайт.
|
> Так же замените значение параметра `tls_domain` на другой сайт.
|
||||||
> Изменение параметра tls_domain сделает нерабочими все ссылки, использующие старый домен!
|
> Изменение параметра `tls_domain` сделает нерабочими все ссылки, использующие старый домен!
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -81,23 +81,9 @@ pub async fn run() -> std::result::Result<(), Box<dyn std::error::Error>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(unix)]
|
// Shared maestro startup and main loop. `drop_after_bind` runs on Unix after listeners are bound
|
||||||
async fn run_inner(
|
// (for privilege drop); it is a no-op on other platforms.
|
||||||
daemon_opts: DaemonOptions,
|
async fn run_telemt_core(drop_after_bind: impl FnOnce()) -> std::result::Result<(), Box<dyn std::error::Error>> {
|
||||||
) -> std::result::Result<(), Box<dyn std::error::Error>> {
|
|
||||||
// Acquire PID file if daemonizing or if explicitly requested
|
|
||||||
// Keep it alive until shutdown (underscore prefix = intentionally kept for RAII cleanup)
|
|
||||||
let _pid_file = if daemon_opts.daemonize || daemon_opts.pid_file.is_some() {
|
|
||||||
let mut pf = PidFile::new(daemon_opts.pid_file_path());
|
|
||||||
if let Err(e) = pf.acquire() {
|
|
||||||
eprintln!("[telemt] {}", e);
|
|
||||||
std::process::exit(1);
|
|
||||||
}
|
|
||||||
Some(pf)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
let process_started_at = Instant::now();
|
let process_started_at = Instant::now();
|
||||||
let process_started_at_epoch_secs = SystemTime::now()
|
let process_started_at_epoch_secs = SystemTime::now()
|
||||||
.duration_since(UNIX_EPOCH)
|
.duration_since(UNIX_EPOCH)
|
||||||
@@ -761,17 +747,8 @@ async fn run_inner(
|
|||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Drop privileges after binding sockets (which may require root for port < 1024)
|
// On Unix, caller supplies privilege drop after bind (may require root for port < 1024).
|
||||||
if daemon_opts.user.is_some() || daemon_opts.group.is_some() {
|
drop_after_bind();
|
||||||
if let Err(e) = drop_privileges(
|
|
||||||
daemon_opts.user.as_deref(),
|
|
||||||
daemon_opts.group.as_deref(),
|
|
||||||
_pid_file.as_ref(),
|
|
||||||
) {
|
|
||||||
error!(error = %e, "Failed to drop privileges");
|
|
||||||
std::process::exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
runtime_tasks::apply_runtime_log_filter(
|
runtime_tasks::apply_runtime_log_filter(
|
||||||
has_rust_log,
|
has_rust_log,
|
||||||
@@ -819,3 +796,43 @@ async fn run_inner(
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
async fn run_inner(
|
||||||
|
daemon_opts: DaemonOptions,
|
||||||
|
) -> std::result::Result<(), Box<dyn std::error::Error>> {
|
||||||
|
// Acquire PID file if daemonizing or if explicitly requested
|
||||||
|
// Keep it alive until shutdown (underscore prefix = intentionally kept for RAII cleanup)
|
||||||
|
let _pid_file = if daemon_opts.daemonize || daemon_opts.pid_file.is_some() {
|
||||||
|
let mut pf = PidFile::new(daemon_opts.pid_file_path());
|
||||||
|
if let Err(e) = pf.acquire() {
|
||||||
|
eprintln!("[telemt] {}", e);
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
Some(pf)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let user = daemon_opts.user.clone();
|
||||||
|
let group = daemon_opts.group.clone();
|
||||||
|
|
||||||
|
run_telemt_core(|| {
|
||||||
|
if user.is_some() || group.is_some() {
|
||||||
|
if let Err(e) = drop_privileges(
|
||||||
|
user.as_deref(),
|
||||||
|
group.as_deref(),
|
||||||
|
_pid_file.as_ref(),
|
||||||
|
) {
|
||||||
|
error!(error = %e, "Failed to drop privileges");
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(unix))]
|
||||||
|
async fn run_inner() -> std::result::Result<(), Box<dyn std::error::Error>> {
|
||||||
|
run_telemt_core(|| {}).await
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user