LAN opt-in, mDNS migration, security hardening, path-based routing
- LAN discovery disabled by default (opt-in via [lan] enabled = true)
- Replace custom JSON multicast (239.255.70.78:5390) with standard mDNS
(_numa._tcp.local on 224.0.0.251:5353) using existing DNS parser
- Instance ID in TXT record for multi-instance self-filtering
- API and proxy bind to 127.0.0.1 by default (0.0.0.0 when LAN enabled)
- Path-based routing: longest prefix match with optional prefix stripping
via [[services]] routes = [{path, port, strip?}]
- REST API: GET/POST/DELETE /services/{name}/routes
- Dashboard shows route lines per service when configured
- Segment-boundary route matching (prevents /api matching /apiary)
- Route path validation (rejects path traversal)
Closes #11
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -35,6 +35,8 @@ pub struct ServerConfig {
|
||||
pub bind_addr: String,
|
||||
#[serde(default = "default_api_port")]
|
||||
pub api_port: u16,
|
||||
#[serde(default = "default_api_bind_addr")]
|
||||
pub api_bind_addr: String,
|
||||
}
|
||||
|
||||
impl Default for ServerConfig {
|
||||
@@ -42,10 +44,15 @@ impl Default for ServerConfig {
|
||||
ServerConfig {
|
||||
bind_addr: default_bind_addr(),
|
||||
api_port: default_api_port(),
|
||||
api_bind_addr: default_api_bind_addr(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn default_api_bind_addr() -> String {
|
||||
"127.0.0.1".to_string()
|
||||
}
|
||||
|
||||
fn default_bind_addr() -> String {
|
||||
"0.0.0.0:53".to_string()
|
||||
}
|
||||
@@ -172,6 +179,8 @@ pub struct ProxyConfig {
|
||||
pub tls_port: u16,
|
||||
#[serde(default = "default_proxy_tld")]
|
||||
pub tld: String,
|
||||
#[serde(default = "default_proxy_bind_addr")]
|
||||
pub bind_addr: String,
|
||||
}
|
||||
|
||||
impl Default for ProxyConfig {
|
||||
@@ -181,10 +190,15 @@ impl Default for ProxyConfig {
|
||||
port: default_proxy_port(),
|
||||
tls_port: default_proxy_tls_port(),
|
||||
tld: default_proxy_tld(),
|
||||
bind_addr: default_proxy_bind_addr(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn default_proxy_bind_addr() -> String {
|
||||
"127.0.0.1".to_string()
|
||||
}
|
||||
|
||||
fn default_proxy_enabled() -> bool {
|
||||
true
|
||||
}
|
||||
@@ -202,16 +216,14 @@ fn default_proxy_tld() -> String {
|
||||
pub struct ServiceConfig {
|
||||
pub name: String,
|
||||
pub target_port: u16,
|
||||
#[serde(default)]
|
||||
pub routes: Vec<crate::service_store::RouteEntry>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Clone)]
|
||||
pub struct LanConfig {
|
||||
#[serde(default = "default_lan_enabled")]
|
||||
pub enabled: bool,
|
||||
#[serde(default = "default_lan_multicast_group")]
|
||||
pub multicast_group: String,
|
||||
#[serde(default = "default_lan_port")]
|
||||
pub port: u16,
|
||||
#[serde(default = "default_lan_broadcast_interval")]
|
||||
pub broadcast_interval_secs: u64,
|
||||
#[serde(default = "default_lan_peer_timeout")]
|
||||
@@ -222,8 +234,6 @@ impl Default for LanConfig {
|
||||
fn default() -> Self {
|
||||
LanConfig {
|
||||
enabled: default_lan_enabled(),
|
||||
multicast_group: default_lan_multicast_group(),
|
||||
port: default_lan_port(),
|
||||
broadcast_interval_secs: default_lan_broadcast_interval(),
|
||||
peer_timeout_secs: default_lan_peer_timeout(),
|
||||
}
|
||||
@@ -231,13 +241,7 @@ impl Default for LanConfig {
|
||||
}
|
||||
|
||||
fn default_lan_enabled() -> bool {
|
||||
true
|
||||
}
|
||||
fn default_lan_multicast_group() -> String {
|
||||
"239.255.70.78".to_string()
|
||||
}
|
||||
fn default_lan_port() -> u16 {
|
||||
5390
|
||||
false
|
||||
}
|
||||
fn default_lan_broadcast_interval() -> u64 {
|
||||
30
|
||||
|
||||
Reference in New Issue
Block a user