feat: resolve .numa services to LAN IP for remote clients #23
@@ -54,7 +54,7 @@ enabled = true
|
|||||||
port = 80
|
port = 80
|
||||||
tls_port = 443
|
tls_port = 443
|
||||||
tld = "numa"
|
tld = "numa"
|
||||||
# bind_addr = "127.0.0.1" # default; auto 0.0.0.0 when [lan] enabled
|
# bind_addr = "127.0.0.1" # default; set to "0.0.0.0" for LAN access to .numa services
|
||||||
|
|
||||||
# Pre-configured services (numa.numa is always added automatically)
|
# Pre-configured services (numa.numa is always added automatically)
|
||||||
# [[services]]
|
# [[services]]
|
||||||
|
|||||||
@@ -108,12 +108,17 @@ pub async fn handle_query(
|
|||||||
} else if !ctx.proxy_tld_suffix.is_empty()
|
} else if !ctx.proxy_tld_suffix.is_empty()
|
||||||
&& (qname.ends_with(&ctx.proxy_tld_suffix) || qname == ctx.proxy_tld)
|
&& (qname.ends_with(&ctx.proxy_tld_suffix) || qname == ctx.proxy_tld)
|
||||||
{
|
{
|
||||||
// Resolve .numa: local services → 127.0.0.1, LAN peers → peer IP
|
// Resolve .numa: remote clients get LAN IP (can't reach 127.0.0.1), local get loopback
|
||||||
let service_name = qname.strip_suffix(&ctx.proxy_tld_suffix).unwrap_or(&qname);
|
let service_name = qname.strip_suffix(&ctx.proxy_tld_suffix).unwrap_or(&qname);
|
||||||
|
let is_remote = !src_addr.ip().is_loopback();
|
||||||
let resolve_ip = {
|
let resolve_ip = {
|
||||||
let local = ctx.services.lock().unwrap();
|
let local = ctx.services.lock().unwrap();
|
||||||
if local.lookup(service_name).is_some() {
|
if local.lookup(service_name).is_some() {
|
||||||
std::net::Ipv4Addr::LOCALHOST
|
if is_remote {
|
||||||
|
*ctx.lan_ip.lock().unwrap()
|
||||||
|
} else {
|
||||||
|
std::net::Ipv4Addr::LOCALHOST
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
let mut peers = ctx.lan_peers.lock().unwrap();
|
let mut peers = ctx.lan_peers.lock().unwrap();
|
||||||
peers
|
peers
|
||||||
|
|||||||
27
src/main.rs
27
src/main.rs
@@ -208,7 +208,6 @@ async fn main() -> numa::Result<()> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let zone_count: usize = ctx.zone_map.values().map(|m| m.len()).sum();
|
let zone_count: usize = ctx.zone_map.values().map(|m| m.len()).sum();
|
||||||
|
|
||||||
// Build banner rows, then size the box to fit the longest value
|
// Build banner rows, then size the box to fit the longest value
|
||||||
let api_url = format!("http://localhost:{}", api_port);
|
let api_url = format!("http://localhost:{}", api_port);
|
||||||
let proxy_label = if config.proxy.enabled {
|
let proxy_label = if config.proxy.enabled {
|
||||||
@@ -308,6 +307,17 @@ async fn main() -> numa::Result<()> {
|
|||||||
);
|
);
|
||||||
if let Some(ref label) = proxy_label {
|
if let Some(ref label) = proxy_label {
|
||||||
row("Proxy", g, label);
|
row("Proxy", g, label);
|
||||||
|
if config.proxy.bind_addr == "127.0.0.1" {
|
||||||
|
let y = "\x1b[38;2;204;176;59m"; // yellow
|
||||||
|
row(
|
||||||
|
"",
|
||||||
|
y,
|
||||||
|
&format!(
|
||||||
|
"⚠ proxy on 127.0.0.1 — .{} not LAN reachable",
|
||||||
|
config.proxy.tld
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if config.lan.enabled {
|
if config.lan.enabled {
|
||||||
row("LAN", g, "mDNS (_numa._tcp.local)");
|
row("LAN", g, "mDNS (_numa._tcp.local)");
|
||||||
@@ -375,16 +385,11 @@ async fn main() -> numa::Result<()> {
|
|||||||
axum::serve(listener, app).await.unwrap();
|
axum::serve(listener, app).await.unwrap();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Proxy binds 0.0.0.0 when LAN is enabled (cross-machine access), otherwise config value
|
let proxy_bind: std::net::Ipv4Addr = config
|
||||||
let proxy_bind: std::net::Ipv4Addr = if config.lan.enabled {
|
.proxy
|
||||||
std::net::Ipv4Addr::UNSPECIFIED
|
.bind_addr
|
||||||
} else {
|
.parse()
|
||||||
config
|
.unwrap_or(std::net::Ipv4Addr::LOCALHOST);
|
||||||
.proxy
|
|
||||||
.bind_addr
|
|
||||||
.parse()
|
|
||||||
.unwrap_or(std::net::Ipv4Addr::LOCALHOST)
|
|
||||||
};
|
|
||||||
|
|
||||||
// Spawn HTTP reverse proxy for .numa domains
|
// Spawn HTTP reverse proxy for .numa domains
|
||||||
if config.proxy.enabled {
|
if config.proxy.enabled {
|
||||||
|
|||||||
Reference in New Issue
Block a user