feat: extend announce_ip to accept hostnames

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.
This commit is contained in:
vladon
2026-02-16 17:26:46 +03:00
parent 303a6896bf
commit 16b5dc56f0
2 changed files with 27 additions and 6 deletions

View File

@@ -497,6 +497,12 @@ pub struct UpstreamConfig {
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ListenerConfig {
pub ip: IpAddr,
/// IP address or hostname to announce in proxy links.
/// Takes precedence over `announce_ip` if both are set.
#[serde(default)]
pub announce: Option<String>,
/// Deprecated: Use `announce` instead. IP address to announce in proxy links.
/// Migrated to `announce` automatically if `announce` is not set.
#[serde(default)]
pub announce_ip: Option<IpAddr>,
}
@@ -716,6 +722,7 @@ impl ProxyConfig {
if let Ok(ipv4) = ipv4_str.parse::<IpAddr>() {
config.server.listeners.push(ListenerConfig {
ip: ipv4,
announce: None,
announce_ip: None,
});
}
@@ -723,12 +730,20 @@ impl ProxyConfig {
if let Ok(ipv6) = ipv6_str.parse::<IpAddr>() {
config.server.listeners.push(ListenerConfig {
ip: ipv6,
announce: None,
announce_ip: None,
});
}
}
}
// Migration: announce_ip → announce for each listener
for listener in &mut config.server.listeners {
if listener.announce.is_none() && listener.announce_ip.is_some() {
listener.announce = Some(listener.announce_ip.unwrap().to_string());
}
}
// 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();

View File

@@ -563,22 +563,28 @@ match crate::transport::middle_proxy::fetch_proxy_secret(proxy_secret_path).awai
let listener = TcpListener::from_std(socket.into())?;
info!("Listening on {}", addr);
let public_ip = if let Some(ip) = listener_conf.announce_ip {
ip
// Resolve the public host for link generation
let public_host = if let Some(ref announce) = listener_conf.announce {
announce.clone() // Use announce (IP or hostname) if explicitly set
} else if listener_conf.ip.is_unspecified() {
// Auto-detect for unspecified addresses
if listener_conf.ip.is_ipv4() {
detected_ip.ipv4.unwrap_or(listener_conf.ip)
detected_ip.ipv4
.map(|ip| ip.to_string())
.unwrap_or_else(|| listener_conf.ip.to_string())
} else {
detected_ip.ipv6.unwrap_or(listener_conf.ip)
detected_ip.ipv6
.map(|ip| ip.to_string())
.unwrap_or_else(|| listener_conf.ip.to_string())
}
} else {
listener_conf.ip
listener_conf.ip.to_string()
};
// Show per-listener proxy links only when public_host is not set
if config.general.links.public_host.is_none() && !config.general.links.show.is_empty() {
let link_port = config.general.links.public_port.unwrap_or(config.server.port);
print_proxy_links(&public_ip.to_string(), link_port, &config);
print_proxy_links(&public_host, link_port, &config);
}
listeners.push(listener);