Merge pull request #95 from Katze-942/main-fix
Fix: public_host/public_port + unix socket
This commit is contained in:
23
Cargo.lock
generated
23
Cargo.lock
generated
@@ -1066,6 +1066,25 @@ dependencies = [
|
|||||||
"windows-sys 0.61.2",
|
"windows-sys 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-bigint"
|
||||||
|
version = "0.4.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
|
||||||
|
dependencies = [
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-integer"
|
||||||
|
version = "0.1.46"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-traits"
|
name = "num-traits"
|
||||||
version = "0.2.19"
|
version = "0.2.19"
|
||||||
@@ -1723,7 +1742,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "telemt"
|
name = "telemt"
|
||||||
version = "1.2.0"
|
version = "3.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aes",
|
"aes",
|
||||||
"base64",
|
"base64",
|
||||||
@@ -1741,6 +1760,8 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
"lru",
|
"lru",
|
||||||
"md-5",
|
"md-5",
|
||||||
|
"num-bigint",
|
||||||
|
"num-traits",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
"proptest",
|
"proptest",
|
||||||
"rand",
|
"rand",
|
||||||
|
|||||||
14
README.md
14
README.md
@@ -208,10 +208,6 @@ then Ctrl+X -> Y -> Enter to save
|
|||||||
## Configuration
|
## Configuration
|
||||||
### Minimal Configuration for First Start
|
### Minimal Configuration for First Start
|
||||||
```toml
|
```toml
|
||||||
# === UI ===
|
|
||||||
# Users to show in the startup log (tg:// links)
|
|
||||||
show_link = ["hello"]
|
|
||||||
|
|
||||||
# === General Settings ===
|
# === General Settings ===
|
||||||
[general]
|
[general]
|
||||||
prefer_ipv6 = false
|
prefer_ipv6 = false
|
||||||
@@ -240,6 +236,12 @@ ip = "0.0.0.0"
|
|||||||
[[server.listeners]]
|
[[server.listeners]]
|
||||||
ip = "::"
|
ip = "::"
|
||||||
|
|
||||||
|
# Users to show in the startup log (tg:// links)
|
||||||
|
[general.links]
|
||||||
|
show = ["hello"] # Users to show in the startup log (tg:// links)
|
||||||
|
# public_host = "proxy.example.com" # Host (IP or domain) for tg:// links
|
||||||
|
# public_port = 443 # Port for tg:// links (default: server.port)
|
||||||
|
|
||||||
# === Timeouts (in seconds) ===
|
# === Timeouts (in seconds) ===
|
||||||
[timeouts]
|
[timeouts]
|
||||||
client_handshake = 15
|
client_handshake = 15
|
||||||
@@ -287,6 +289,10 @@ weight = 10
|
|||||||
# address = "127.0.0.1:9050"
|
# address = "127.0.0.1:9050"
|
||||||
# enabled = false
|
# enabled = false
|
||||||
# weight = 1
|
# weight = 1
|
||||||
|
|
||||||
|
# === DC Address Overrides ===
|
||||||
|
# [dc_overrides]
|
||||||
|
# "203" = "91.105.192.100:443"
|
||||||
```
|
```
|
||||||
### Advanced
|
### Advanced
|
||||||
#### Adtag
|
#### Adtag
|
||||||
|
|||||||
20
config.toml
20
config.toml
@@ -1,7 +1,3 @@
|
|||||||
# === UI ===
|
|
||||||
# Users to show in the startup log (tg:// links)
|
|
||||||
show_link = ["hello"]
|
|
||||||
|
|
||||||
# === General Settings ===
|
# === General Settings ===
|
||||||
[general]
|
[general]
|
||||||
prefer_ipv6 = true
|
prefer_ipv6 = true
|
||||||
@@ -24,6 +20,8 @@ tls = true
|
|||||||
port = 443
|
port = 443
|
||||||
listen_addr_ipv4 = "0.0.0.0"
|
listen_addr_ipv4 = "0.0.0.0"
|
||||||
listen_addr_ipv6 = "::"
|
listen_addr_ipv6 = "::"
|
||||||
|
# listen_unix_sock = "/var/run/telemt.sock" # Unix socket
|
||||||
|
# listen_unix_sock_perm = "0666" # Socket file permissions
|
||||||
# metrics_port = 9090
|
# metrics_port = 9090
|
||||||
# metrics_whitelist = ["127.0.0.1", "::1"]
|
# metrics_whitelist = ["127.0.0.1", "::1"]
|
||||||
|
|
||||||
@@ -35,6 +33,12 @@ ip = "0.0.0.0"
|
|||||||
[[server.listeners]]
|
[[server.listeners]]
|
||||||
ip = "::"
|
ip = "::"
|
||||||
|
|
||||||
|
# Users to show in the startup log (tg:// links)
|
||||||
|
[general.links]
|
||||||
|
show = ["hello"] # Users to show in the startup log (tg:// links)
|
||||||
|
# public_host = "proxy.example.com" # Host (IP or domain) for tg:// links
|
||||||
|
# public_port = 443 # Port for tg:// links (default: server.port)
|
||||||
|
|
||||||
# === Timeouts (in seconds) ===
|
# === Timeouts (in seconds) ===
|
||||||
[timeouts]
|
[timeouts]
|
||||||
client_handshake = 15
|
client_handshake = 15
|
||||||
@@ -65,7 +69,7 @@ hello = "00000000000000000000000000000000"
|
|||||||
# hello = 50
|
# hello = 50
|
||||||
|
|
||||||
# [access.user_max_unique_ips]
|
# [access.user_max_unique_ips]
|
||||||
# hello = 5
|
# hello = 5
|
||||||
|
|
||||||
# [access.user_data_quota]
|
# [access.user_data_quota]
|
||||||
# hello = 1073741824 # 1 GB
|
# hello = 1073741824 # 1 GB
|
||||||
@@ -80,4 +84,8 @@ weight = 10
|
|||||||
# type = "socks5"
|
# type = "socks5"
|
||||||
# address = "127.0.0.1:1080"
|
# address = "127.0.0.1:1080"
|
||||||
# enabled = false
|
# enabled = false
|
||||||
# weight = 1
|
# weight = 1
|
||||||
|
|
||||||
|
# === DC Address Overrides ===
|
||||||
|
# [dc_overrides]
|
||||||
|
# "203" = "91.105.192.100:443"
|
||||||
|
|||||||
@@ -256,6 +256,27 @@ pub struct GeneralConfig {
|
|||||||
/// Disable colored output in logs (useful for files/systemd)
|
/// Disable colored output in logs (useful for files/systemd)
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub disable_colors: bool,
|
pub disable_colors: bool,
|
||||||
|
|
||||||
|
/// [general.links] — proxy link generation overrides
|
||||||
|
#[serde(default)]
|
||||||
|
pub links: LinksConfig,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `[general.links]` — proxy link generation settings.
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
||||||
|
pub struct LinksConfig {
|
||||||
|
/// List of usernames whose tg:// links to display at startup.
|
||||||
|
/// `"*"` = all users, `["alice", "bob"]` = specific users.
|
||||||
|
#[serde(default)]
|
||||||
|
pub show: ShowLink,
|
||||||
|
|
||||||
|
/// Public hostname/IP for tg:// link generation (overrides detected IP).
|
||||||
|
#[serde(default)]
|
||||||
|
pub public_host: Option<String>,
|
||||||
|
|
||||||
|
/// Public port for tg:// link generation (overrides server.port).
|
||||||
|
#[serde(default)]
|
||||||
|
pub public_port: Option<u16>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for GeneralConfig {
|
impl Default for GeneralConfig {
|
||||||
@@ -274,6 +295,7 @@ impl Default for GeneralConfig {
|
|||||||
unknown_dc_log_path: default_unknown_dc_log_path(),
|
unknown_dc_log_path: default_unknown_dc_log_path(),
|
||||||
log_level: LogLevel::Normal,
|
log_level: LogLevel::Normal,
|
||||||
disable_colors: false,
|
disable_colors: false,
|
||||||
|
links: LinksConfig::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -283,8 +305,8 @@ pub struct ServerConfig {
|
|||||||
#[serde(default = "default_port")]
|
#[serde(default = "default_port")]
|
||||||
pub port: u16,
|
pub port: u16,
|
||||||
|
|
||||||
#[serde(default = "default_listen_addr")]
|
#[serde(default)]
|
||||||
pub listen_addr_ipv4: String,
|
pub listen_addr_ipv4: Option<String>,
|
||||||
|
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub listen_addr_ipv6: Option<String>,
|
pub listen_addr_ipv6: Option<String>,
|
||||||
@@ -292,6 +314,16 @@ pub struct ServerConfig {
|
|||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub listen_unix_sock: Option<String>,
|
pub listen_unix_sock: Option<String>,
|
||||||
|
|
||||||
|
/// Unix socket file permissions (octal, e.g. "0666" or "0777").
|
||||||
|
/// Applied via chmod after bind. Default: no change (inherits umask).
|
||||||
|
#[serde(default)]
|
||||||
|
pub listen_unix_sock_perm: Option<String>,
|
||||||
|
|
||||||
|
/// Enable TCP listening. Default: true when no unix socket, false when
|
||||||
|
/// listen_unix_sock is set. Set explicitly to override auto-detection.
|
||||||
|
#[serde(default)]
|
||||||
|
pub listen_tcp: Option<bool>,
|
||||||
|
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub metrics_port: Option<u16>,
|
pub metrics_port: Option<u16>,
|
||||||
|
|
||||||
@@ -306,9 +338,11 @@ impl Default for ServerConfig {
|
|||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
port: default_port(),
|
port: default_port(),
|
||||||
listen_addr_ipv4: default_listen_addr(),
|
listen_addr_ipv4: Some(default_listen_addr()),
|
||||||
listen_addr_ipv6: Some("::".to_string()),
|
listen_addr_ipv6: Some("::".to_string()),
|
||||||
listen_unix_sock: None,
|
listen_unix_sock: None,
|
||||||
|
listen_unix_sock_perm: None,
|
||||||
|
listen_tcp: None,
|
||||||
metrics_port: None,
|
metrics_port: None,
|
||||||
metrics_whitelist: default_metrics_whitelist(),
|
metrics_whitelist: default_metrics_whitelist(),
|
||||||
listeners: Vec::new(),
|
listeners: Vec::new(),
|
||||||
@@ -661,9 +695,25 @@ impl ProxyConfig {
|
|||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
config.censorship.fake_cert_len = rand::rng().gen_range(1024..4096);
|
config.censorship.fake_cert_len = rand::rng().gen_range(1024..4096);
|
||||||
|
|
||||||
// Migration: Populate listeners if empty
|
// Resolve listen_tcp: explicit value wins, otherwise auto-detect.
|
||||||
if config.server.listeners.is_empty() {
|
// If unix socket is set → TCP only when listen_addr_ipv4 or listeners are explicitly provided.
|
||||||
if let Ok(ipv4) = config.server.listen_addr_ipv4.parse::<IpAddr>() {
|
// If no unix socket → TCP always (backward compat).
|
||||||
|
let listen_tcp = config.server.listen_tcp.unwrap_or_else(|| {
|
||||||
|
if config.server.listen_unix_sock.is_some() {
|
||||||
|
// Unix socket present: TCP only if user explicitly set addresses or listeners
|
||||||
|
config.server.listen_addr_ipv4.is_some()
|
||||||
|
|| !config.server.listeners.is_empty()
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Migration: Populate listeners if empty (skip when listen_tcp = false)
|
||||||
|
if config.server.listeners.is_empty() && listen_tcp {
|
||||||
|
let ipv4_str = config.server.listen_addr_ipv4
|
||||||
|
.as_deref()
|
||||||
|
.unwrap_or("0.0.0.0");
|
||||||
|
if let Ok(ipv4) = ipv4_str.parse::<IpAddr>() {
|
||||||
config.server.listeners.push(ListenerConfig {
|
config.server.listeners.push(ListenerConfig {
|
||||||
ip: ipv4,
|
ip: ipv4,
|
||||||
announce_ip: None,
|
announce_ip: None,
|
||||||
@@ -679,6 +729,11 @@ impl ProxyConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Migration: show_link (top-level) → general.links.show
|
||||||
|
if !config.show_link.is_empty() && config.general.links.show.is_empty() {
|
||||||
|
config.general.links.show = config.show_link.clone();
|
||||||
|
}
|
||||||
|
|
||||||
// Migration: Populate upstreams if empty (Default Direct)
|
// Migration: Populate upstreams if empty (Default Direct)
|
||||||
if config.upstreams.is_empty() {
|
if config.upstreams.is_empty() {
|
||||||
config.upstreams.push(UpstreamConfig {
|
config.upstreams.push(UpstreamConfig {
|
||||||
|
|||||||
221
src/main.rs
221
src/main.rs
@@ -8,6 +8,8 @@ use tokio::signal;
|
|||||||
use tokio::sync::Semaphore;
|
use tokio::sync::Semaphore;
|
||||||
use tracing::{debug, error, info, warn};
|
use tracing::{debug, error, info, warn};
|
||||||
use tracing_subscriber::{EnvFilter, fmt, prelude::*, reload};
|
use tracing_subscriber::{EnvFilter, fmt, prelude::*, reload};
|
||||||
|
#[cfg(unix)]
|
||||||
|
use tokio::net::UnixListener;
|
||||||
|
|
||||||
mod cli;
|
mod cli;
|
||||||
mod config;
|
mod config;
|
||||||
@@ -100,6 +102,37 @@ fn parse_cli() -> (String, bool, Option<String>) {
|
|||||||
(config_path, silent, log_level)
|
(config_path, silent, log_level)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn print_proxy_links(host: &str, port: u16, config: &ProxyConfig) {
|
||||||
|
info!("--- Proxy Links ({}) ---", host);
|
||||||
|
for user_name in config.general.links.show.resolve_users(&config.access.users) {
|
||||||
|
if let Some(secret) = config.access.users.get(user_name) {
|
||||||
|
info!("User: {}", user_name);
|
||||||
|
if config.general.modes.classic {
|
||||||
|
info!(
|
||||||
|
" Classic: tg://proxy?server={}&port={}&secret={}",
|
||||||
|
host, port, secret
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if config.general.modes.secure {
|
||||||
|
info!(
|
||||||
|
" DD: tg://proxy?server={}&port={}&secret=dd{}",
|
||||||
|
host, port, secret
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if config.general.modes.tls {
|
||||||
|
let domain_hex = hex::encode(&config.censorship.tls_domain);
|
||||||
|
info!(
|
||||||
|
" EE-TLS: tg://proxy?server={}&port={}&secret=ee{}{}",
|
||||||
|
host, port, secret, domain_hex
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
warn!("User '{}' in show_link not found", user_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
info!("------------------------");
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
|
async fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
|
||||||
let (config_path, cli_silent, cli_log_level) = parse_cli();
|
let (config_path, cli_silent, cli_log_level) = parse_cli();
|
||||||
@@ -476,35 +509,10 @@ match crate::transport::middle_proxy::fetch_proxy_secret(proxy_secret_path).awai
|
|||||||
listener_conf.ip
|
listener_conf.ip
|
||||||
};
|
};
|
||||||
|
|
||||||
if !config.show_link.is_empty() {
|
// Show per-listener proxy links only when public_host is not set
|
||||||
info!("--- Proxy Links ({}) ---", public_ip);
|
if config.general.links.public_host.is_none() && !config.general.links.show.is_empty() {
|
||||||
for user_name in config.show_link.resolve_users(&config.access.users) {
|
let link_port = config.general.links.public_port.unwrap_or(config.server.port);
|
||||||
if let Some(secret) = config.access.users.get(user_name) {
|
print_proxy_links(&public_ip.to_string(), link_port, &config);
|
||||||
info!("User: {}", user_name);
|
|
||||||
if config.general.modes.classic {
|
|
||||||
info!(
|
|
||||||
" Classic: tg://proxy?server={}&port={}&secret={}",
|
|
||||||
public_ip, config.server.port, secret
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if config.general.modes.secure {
|
|
||||||
info!(
|
|
||||||
" DD: tg://proxy?server={}&port={}&secret=dd{}",
|
|
||||||
public_ip, config.server.port, secret
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if config.general.modes.tls {
|
|
||||||
let domain_hex = hex::encode(&config.censorship.tls_domain);
|
|
||||||
info!(
|
|
||||||
" EE-TLS: tg://proxy?server={}&port={}&secret=ee{}{}",
|
|
||||||
public_ip, config.server.port, secret, domain_hex
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
warn!("User '{}' in show_link not found", user_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
info!("------------------------");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
listeners.push(listener);
|
listeners.push(listener);
|
||||||
@@ -515,7 +523,104 @@ match crate::transport::middle_proxy::fetch_proxy_secret(proxy_secret_path).awai
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if listeners.is_empty() {
|
// Show proxy links once when public_host is set, OR when there are no TCP listeners
|
||||||
|
// (unix-only mode) — use detected IP as fallback
|
||||||
|
if !config.general.links.show.is_empty() && (config.general.links.public_host.is_some() || listeners.is_empty()) {
|
||||||
|
let (host, port) = if let Some(ref h) = config.general.links.public_host {
|
||||||
|
(h.clone(), config.general.links.public_port.unwrap_or(config.server.port))
|
||||||
|
} else {
|
||||||
|
let ip = detected_ip
|
||||||
|
.ipv4
|
||||||
|
.or(detected_ip.ipv6)
|
||||||
|
.map(|ip| ip.to_string());
|
||||||
|
if ip.is_none() {
|
||||||
|
warn!("show_link is configured but public IP could not be detected. Set public_host in config.");
|
||||||
|
}
|
||||||
|
(ip.unwrap_or_else(|| "UNKNOWN".to_string()), config.general.links.public_port.unwrap_or(config.server.port))
|
||||||
|
};
|
||||||
|
|
||||||
|
print_proxy_links(&host, port, &config);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unix socket setup (before listeners check so unix-only config works)
|
||||||
|
let mut has_unix_listener = false;
|
||||||
|
#[cfg(unix)]
|
||||||
|
if let Some(ref unix_path) = config.server.listen_unix_sock {
|
||||||
|
// Remove stale socket file if present (standard practice)
|
||||||
|
let _ = tokio::fs::remove_file(unix_path).await;
|
||||||
|
|
||||||
|
let unix_listener = UnixListener::bind(unix_path)?;
|
||||||
|
|
||||||
|
// Apply socket permissions if configured
|
||||||
|
if let Some(ref perm_str) = config.server.listen_unix_sock_perm {
|
||||||
|
match u32::from_str_radix(perm_str.trim_start_matches('0'), 8) {
|
||||||
|
Ok(mode) => {
|
||||||
|
use std::os::unix::fs::PermissionsExt;
|
||||||
|
let perms = std::fs::Permissions::from_mode(mode);
|
||||||
|
if let Err(e) = std::fs::set_permissions(unix_path, perms) {
|
||||||
|
error!("Failed to set unix socket permissions to {}: {}", perm_str, e);
|
||||||
|
} else {
|
||||||
|
info!("Listening on unix:{} (mode {})", unix_path, perm_str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
warn!("Invalid listen_unix_sock_perm '{}': {}. Ignoring.", perm_str, e);
|
||||||
|
info!("Listening on unix:{}", unix_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
info!("Listening on unix:{}", unix_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
has_unix_listener = true;
|
||||||
|
|
||||||
|
let config = config.clone();
|
||||||
|
let stats = stats.clone();
|
||||||
|
let upstream_manager = upstream_manager.clone();
|
||||||
|
let replay_checker = replay_checker.clone();
|
||||||
|
let buffer_pool = buffer_pool.clone();
|
||||||
|
let rng = rng.clone();
|
||||||
|
let me_pool = me_pool.clone();
|
||||||
|
let ip_tracker = ip_tracker.clone();
|
||||||
|
|
||||||
|
tokio::spawn(async move {
|
||||||
|
let unix_conn_counter = std::sync::Arc::new(std::sync::atomic::AtomicU64::new(1));
|
||||||
|
|
||||||
|
loop {
|
||||||
|
match unix_listener.accept().await {
|
||||||
|
Ok((stream, _)) => {
|
||||||
|
let conn_id = unix_conn_counter.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
|
||||||
|
let fake_peer = SocketAddr::from(([127, 0, 0, 1], (conn_id % 65535) as u16));
|
||||||
|
|
||||||
|
let config = config.clone();
|
||||||
|
let stats = stats.clone();
|
||||||
|
let upstream_manager = upstream_manager.clone();
|
||||||
|
let replay_checker = replay_checker.clone();
|
||||||
|
let buffer_pool = buffer_pool.clone();
|
||||||
|
let rng = rng.clone();
|
||||||
|
let me_pool = me_pool.clone();
|
||||||
|
let ip_tracker = ip_tracker.clone();
|
||||||
|
|
||||||
|
tokio::spawn(async move {
|
||||||
|
if let Err(e) = crate::proxy::client::handle_client_stream(
|
||||||
|
stream, fake_peer, config, stats,
|
||||||
|
upstream_manager, replay_checker, buffer_pool, rng,
|
||||||
|
me_pool, ip_tracker,
|
||||||
|
).await {
|
||||||
|
debug!(error = %e, "Unix socket connection error");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
error!("Unix socket accept error: {}", e);
|
||||||
|
tokio::time::sleep(Duration::from_millis(100)).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if listeners.is_empty() && !has_unix_listener {
|
||||||
error!("No listeners. Exiting.");
|
error!("No listeners. Exiting.");
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
@@ -582,62 +687,6 @@ match crate::transport::middle_proxy::fetch_proxy_secret(proxy_secret_path).awai
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(unix)]
|
|
||||||
if let Some(ref unix_path) = config.server.listen_unix_sock {
|
|
||||||
use tokio::net::UnixListener; // ← добавь импорт, если его нет выше
|
|
||||||
|
|
||||||
// Удаляем старые файлы сокета, если они есть (стандартная практика)
|
|
||||||
let _ = tokio::fs::remove_file(unix_path).await;
|
|
||||||
|
|
||||||
let unix_listener = UnixListener::bind(unix_path)?;
|
|
||||||
info!("Listening on unix:{}", unix_path);
|
|
||||||
|
|
||||||
let config = config.clone();
|
|
||||||
let stats = stats.clone();
|
|
||||||
let upstream_manager = upstream_manager.clone();
|
|
||||||
let replay_checker = replay_checker.clone();
|
|
||||||
let buffer_pool = buffer_pool.clone();
|
|
||||||
let rng = rng.clone();
|
|
||||||
let me_pool = me_pool.clone();
|
|
||||||
let ip_tracker = ip_tracker.clone();
|
|
||||||
|
|
||||||
tokio::spawn(async move {
|
|
||||||
let unix_conn_counter = std::sync::Arc::new(std::sync::atomic::AtomicU64::new(1));
|
|
||||||
|
|
||||||
loop {
|
|
||||||
match unix_listener.accept().await {
|
|
||||||
Ok((stream, _)) => {
|
|
||||||
let conn_id = unix_conn_counter.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
|
|
||||||
let fake_peer = SocketAddr::from(([127, 0, 0, 1], (conn_id % 65535) as u16)); // безопасный порт
|
|
||||||
|
|
||||||
let config = config.clone();
|
|
||||||
let stats = stats.clone();
|
|
||||||
let upstream_manager = upstream_manager.clone();
|
|
||||||
let replay_checker = replay_checker.clone();
|
|
||||||
let buffer_pool = buffer_pool.clone();
|
|
||||||
let rng = rng.clone();
|
|
||||||
let me_pool = me_pool.clone();
|
|
||||||
let ip_tracker = ip_tracker.clone();
|
|
||||||
|
|
||||||
tokio::spawn(async move {
|
|
||||||
if let Err(e) = crate::proxy::client::handle_client_stream(
|
|
||||||
stream, fake_peer, config, stats,
|
|
||||||
upstream_manager, replay_checker, buffer_pool, rng,
|
|
||||||
me_pool, ip_tracker,
|
|
||||||
).await {
|
|
||||||
debug!(error = %e, "Unix socket connection error");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
error!("Unix socket accept error: {}", e);
|
|
||||||
tokio::time::sleep(Duration::from_millis(100)).await;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
match signal::ctrl_c().await {
|
match signal::ctrl_c().await {
|
||||||
Ok(()) => info!("Shutting down..."),
|
Ok(()) => info!("Shutting down..."),
|
||||||
Err(e) => error!("Signal error: {}", e),
|
Err(e) => error!("Signal error: {}", e),
|
||||||
|
|||||||
Reference in New Issue
Block a user