Correct IP:port/public-host:public-port in API

This commit is contained in:
Alexey 2026-03-09 23:37:29 +03:00
parent b950987229
commit 100ef0fa28
No known key found for this signature in database
3 changed files with 63 additions and 43 deletions

View File

@ -75,8 +75,7 @@ pub(super) struct ApiShared {
pub(super) me_pool: Arc<RwLock<Option<Arc<MePool>>>>, pub(super) me_pool: Arc<RwLock<Option<Arc<MePool>>>>,
pub(super) upstream_manager: Arc<UpstreamManager>, pub(super) upstream_manager: Arc<UpstreamManager>,
pub(super) config_path: PathBuf, pub(super) config_path: PathBuf,
pub(super) startup_detected_ip_v4: Option<IpAddr>, pub(super) detected_ips_rx: watch::Receiver<(Option<IpAddr>, Option<IpAddr>)>,
pub(super) startup_detected_ip_v6: Option<IpAddr>,
pub(super) mutation_lock: Arc<Mutex<()>>, pub(super) mutation_lock: Arc<Mutex<()>>,
pub(super) minimal_cache: Arc<Mutex<Option<MinimalCacheEntry>>>, pub(super) minimal_cache: Arc<Mutex<Option<MinimalCacheEntry>>>,
pub(super) runtime_edge_connections_cache: Arc<Mutex<Option<EdgeConnectionsCacheEntry>>>, pub(super) runtime_edge_connections_cache: Arc<Mutex<Option<EdgeConnectionsCacheEntry>>>,
@ -91,6 +90,10 @@ impl ApiShared {
fn next_request_id(&self) -> u64 { fn next_request_id(&self) -> u64 {
self.request_id.fetch_add(1, Ordering::Relaxed) self.request_id.fetch_add(1, Ordering::Relaxed)
} }
fn detected_link_ips(&self) -> (Option<IpAddr>, Option<IpAddr>) {
*self.detected_ips_rx.borrow()
}
} }
pub async fn serve( pub async fn serve(
@ -102,8 +105,7 @@ pub async fn serve(
config_rx: watch::Receiver<Arc<ProxyConfig>>, config_rx: watch::Receiver<Arc<ProxyConfig>>,
admission_rx: watch::Receiver<bool>, admission_rx: watch::Receiver<bool>,
config_path: PathBuf, config_path: PathBuf,
startup_detected_ip_v4: Option<IpAddr>, detected_ips_rx: watch::Receiver<(Option<IpAddr>, Option<IpAddr>)>,
startup_detected_ip_v6: Option<IpAddr>,
process_started_at_epoch_secs: u64, process_started_at_epoch_secs: u64,
startup_tracker: Arc<StartupTracker>, startup_tracker: Arc<StartupTracker>,
) { ) {
@ -134,8 +136,7 @@ pub async fn serve(
me_pool, me_pool,
upstream_manager, upstream_manager,
config_path, config_path,
startup_detected_ip_v4, detected_ips_rx,
startup_detected_ip_v6,
mutation_lock: Arc::new(Mutex::new(())), mutation_lock: Arc::new(Mutex::new(())),
minimal_cache: Arc::new(Mutex::new(None)), minimal_cache: Arc::new(Mutex::new(None)),
runtime_edge_connections_cache: Arc::new(Mutex::new(None)), runtime_edge_connections_cache: Arc::new(Mutex::new(None)),
@ -356,12 +357,13 @@ async fn handle(
} }
("GET", "/v1/stats/users") | ("GET", "/v1/users") => { ("GET", "/v1/stats/users") | ("GET", "/v1/users") => {
let revision = current_revision(&shared.config_path).await?; let revision = current_revision(&shared.config_path).await?;
let (detected_ip_v4, detected_ip_v6) = shared.detected_link_ips();
let users = users_from_config( let users = users_from_config(
&cfg, &cfg,
&shared.stats, &shared.stats,
&shared.ip_tracker, &shared.ip_tracker,
shared.startup_detected_ip_v4, detected_ip_v4,
shared.startup_detected_ip_v6, detected_ip_v6,
) )
.await; .await;
Ok(success_response(StatusCode::OK, users, revision)) Ok(success_response(StatusCode::OK, users, revision))
@ -399,12 +401,13 @@ async fn handle(
{ {
if method == Method::GET { if method == Method::GET {
let revision = current_revision(&shared.config_path).await?; let revision = current_revision(&shared.config_path).await?;
let (detected_ip_v4, detected_ip_v6) = shared.detected_link_ips();
let users = users_from_config( let users = users_from_config(
&cfg, &cfg,
&shared.stats, &shared.stats,
&shared.ip_tracker, &shared.ip_tracker,
shared.startup_detected_ip_v4, detected_ip_v4,
shared.startup_detected_ip_v6, detected_ip_v6,
) )
.await; .await;
if let Some(user_info) = users.into_iter().find(|entry| entry.username == user) if let Some(user_info) = users.into_iter().find(|entry| entry.username == user)

View File

@ -90,13 +90,14 @@ pub(super) async fn create_user(
if let Some(limit) = updated_limit { if let Some(limit) = updated_limit {
shared.ip_tracker.set_user_limit(&body.username, limit).await; shared.ip_tracker.set_user_limit(&body.username, limit).await;
} }
let (detected_ip_v4, detected_ip_v6) = shared.detected_link_ips();
let users = users_from_config( let users = users_from_config(
&cfg, &cfg,
&shared.stats, &shared.stats,
&shared.ip_tracker, &shared.ip_tracker,
shared.startup_detected_ip_v4, detected_ip_v4,
shared.startup_detected_ip_v6, detected_ip_v6,
) )
.await; .await;
let user = users let user = users
@ -118,8 +119,8 @@ pub(super) async fn create_user(
links: build_user_links( links: build_user_links(
&cfg, &cfg,
&secret, &secret,
shared.startup_detected_ip_v4, detected_ip_v4,
shared.startup_detected_ip_v6, detected_ip_v6,
), ),
}); });
@ -185,12 +186,13 @@ pub(super) async fn patch_user(
if let Some(limit) = updated_limit { if let Some(limit) = updated_limit {
shared.ip_tracker.set_user_limit(user, limit).await; shared.ip_tracker.set_user_limit(user, limit).await;
} }
let (detected_ip_v4, detected_ip_v6) = shared.detected_link_ips();
let users = users_from_config( let users = users_from_config(
&cfg, &cfg,
&shared.stats, &shared.stats,
&shared.ip_tracker, &shared.ip_tracker,
shared.startup_detected_ip_v4, detected_ip_v4,
shared.startup_detected_ip_v6, detected_ip_v6,
) )
.await; .await;
let user_info = users let user_info = users
@ -232,12 +234,13 @@ pub(super) async fn rotate_secret(
let revision = save_config_to_disk(&shared.config_path, &cfg).await?; let revision = save_config_to_disk(&shared.config_path, &cfg).await?;
drop(_guard); drop(_guard);
let (detected_ip_v4, detected_ip_v6) = shared.detected_link_ips();
let users = users_from_config( let users = users_from_config(
&cfg, &cfg,
&shared.stats, &shared.stats,
&shared.ip_tracker, &shared.ip_tracker,
shared.startup_detected_ip_v4, detected_ip_v4,
shared.startup_detected_ip_v6, detected_ip_v6,
) )
.await; .await;
let user_info = users let user_info = users
@ -418,17 +421,6 @@ fn resolve_link_hosts(
return vec![host.to_string()]; return vec![host.to_string()];
} }
let mut startup_hosts = Vec::new();
if let Some(ip) = startup_detected_ip_v4 {
push_unique_host(&mut startup_hosts, &ip.to_string());
}
if let Some(ip) = startup_detected_ip_v6 {
push_unique_host(&mut startup_hosts, &ip.to_string());
}
if !startup_hosts.is_empty() {
return startup_hosts;
}
let mut hosts = Vec::new(); let mut hosts = Vec::new();
for listener in &cfg.server.listeners { for listener in &cfg.server.listeners {
if let Some(host) = listener if let Some(host) = listener
@ -443,24 +435,44 @@ fn resolve_link_hosts(
if let Some(ip) = listener.announce_ip { if let Some(ip) = listener.announce_ip {
if !ip.is_unspecified() { if !ip.is_unspecified() {
push_unique_host(&mut hosts, &ip.to_string()); push_unique_host(&mut hosts, &ip.to_string());
continue;
}
}
if listener.ip.is_unspecified() {
let detected_ip = if listener.ip.is_ipv4() {
startup_detected_ip_v4
} else {
startup_detected_ip_v6
};
if let Some(ip) = detected_ip {
push_unique_host(&mut hosts, &ip.to_string());
} else {
push_unique_host(&mut hosts, &listener.ip.to_string());
} }
continue; continue;
} }
if !listener.ip.is_unspecified() {
push_unique_host(&mut hosts, &listener.ip.to_string()); push_unique_host(&mut hosts, &listener.ip.to_string());
} }
if !hosts.is_empty() {
return hosts;
}
if let Some(ip) = startup_detected_ip_v4.or(startup_detected_ip_v6) {
return vec![ip.to_string()];
} }
if hosts.is_empty() {
if let Some(host) = cfg.server.listen_addr_ipv4.as_deref() { if let Some(host) = cfg.server.listen_addr_ipv4.as_deref() {
push_host_from_legacy_listen(&mut hosts, host); push_host_from_legacy_listen(&mut hosts, host);
} }
if let Some(host) = cfg.server.listen_addr_ipv6.as_deref() { if let Some(host) = cfg.server.listen_addr_ipv6.as_deref() {
push_host_from_legacy_listen(&mut hosts, host); push_host_from_legacy_listen(&mut hosts, host);
} }
if !hosts.is_empty() {
return hosts;
} }
hosts vec!["UNKNOWN".to_string()]
} }
fn push_host_from_legacy_listen(hosts: &mut Vec<String>, raw: &str) { fn push_host_from_legacy_listen(hosts: &mut Vec<String>, raw: &str) {

View File

@ -20,7 +20,7 @@ mod runtime_tasks;
mod shutdown; mod shutdown;
mod tls_bootstrap; mod tls_bootstrap;
use std::net::SocketAddr; use std::net::{IpAddr, SocketAddr};
use std::sync::Arc; use std::sync::Arc;
use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH}; use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
use tokio::sync::{RwLock, Semaphore, watch}; use tokio::sync::{RwLock, Semaphore, watch};
@ -189,6 +189,7 @@ pub async fn run() -> std::result::Result<(), Box<dyn std::error::Error>> {
} }
let (api_config_tx, api_config_rx) = watch::channel(Arc::new(config.clone())); let (api_config_tx, api_config_rx) = watch::channel(Arc::new(config.clone()));
let (detected_ips_tx, detected_ips_rx) = watch::channel((None::<IpAddr>, None::<IpAddr>));
let initial_admission_open = !config.general.use_middle_proxy; let initial_admission_open = !config.general.use_middle_proxy;
let (admission_tx, admission_rx) = watch::channel(initial_admission_open); let (admission_tx, admission_rx) = watch::channel(initial_admission_open);
let initial_route_mode = if config.general.use_middle_proxy { let initial_route_mode = if config.general.use_middle_proxy {
@ -223,6 +224,7 @@ pub async fn run() -> std::result::Result<(), Box<dyn std::error::Error>> {
let admission_rx_api = admission_rx.clone(); let admission_rx_api = admission_rx.clone();
let config_path_api = std::path::PathBuf::from(&config_path); let config_path_api = std::path::PathBuf::from(&config_path);
let startup_tracker_api = startup_tracker.clone(); let startup_tracker_api = startup_tracker.clone();
let detected_ips_rx_api = detected_ips_rx.clone();
tokio::spawn(async move { tokio::spawn(async move {
api::serve( api::serve(
listen, listen,
@ -233,8 +235,7 @@ pub async fn run() -> std::result::Result<(), Box<dyn std::error::Error>> {
config_rx_api, config_rx_api,
admission_rx_api, admission_rx_api,
config_path_api, config_path_api,
None, detected_ips_rx_api,
None,
process_started_at_epoch_secs, process_started_at_epoch_secs,
startup_tracker_api, startup_tracker_api,
) )
@ -288,6 +289,10 @@ pub async fn run() -> std::result::Result<(), Box<dyn std::error::Error>> {
config.general.stun_nat_probe_concurrency, config.general.stun_nat_probe_concurrency,
) )
.await?; .await?;
detected_ips_tx.send_replace((
probe.detected_ipv4.map(IpAddr::V4),
probe.detected_ipv6.map(IpAddr::V6),
));
let decision = decide_network_capabilities(&config.network, &probe); let decision = decide_network_capabilities(&config.network, &probe);
log_probe_result(&probe, &decision); log_probe_result(&probe, &decision);
startup_tracker startup_tracker