v0.21.0: agent-managed split-horizon LAN resolver (internal/lanresolver)
Host-side dnsmasq the agent manages so LAN clients reach their guest directly (same hostname + real wildcard cert, no Cloudflare hairpin). Renders local=/ +address=/ per customer (AAAA->NODATA via authoritative zone, wildcard A -> live guest IP), forwards everything else. Manager ensures dnsmasq+base config, discovers guest IP (pct exec ip) + domain (controller.yaml), write-if-changed + reload. Loop (7th daemon goroutine) tracks DHCP IP changes per provisioned guest. --selftest=lanresolver. FELHOM_DNSMASQ sudoers. Spiked live on felhom-pve. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -28,9 +28,44 @@ type Config struct {
|
||||
Hub HubConfig `json:"hub"`
|
||||
Storage StorageConfig `json:"storage"`
|
||||
Backup BackupConfig `json:"backup"`
|
||||
Escrow EscrowConfig `json:"escrow"`
|
||||
LocalAPI LocalAPIConfig `json:"local_api"`
|
||||
LogLevel string `json:"log_level"` // debug|info|warn|error (default info)
|
||||
Escrow EscrowConfig `json:"escrow"`
|
||||
LocalAPI LocalAPIConfig `json:"local_api"`
|
||||
LANResolver LANResolverConfig `json:"lan_resolver"`
|
||||
LogLevel string `json:"log_level"` // debug|info|warn|error (default info)
|
||||
}
|
||||
|
||||
// LANResolverConfig configures the host-level split-horizon DNS resolver (internal/lanresolver): a
|
||||
// dnsmasq the agent manages so LAN clients reach their guest DIRECTLY at the same hostname + real cert.
|
||||
// Disabled unless Enable is set. HostIP defaults to the local-API bridge IP (the host LAN anchor);
|
||||
// Upstreams default to public resolvers; the loop re-checks the guest's live IP every interval.
|
||||
type LANResolverConfig struct {
|
||||
Enable bool `json:"enable"`
|
||||
HostIP string `json:"host_ip"` // dnsmasq listen-address; default = LocalAPI bridge IP
|
||||
Upstreams []string `json:"upstreams"` // forward targets for non-customer names
|
||||
IntervalSeconds int `json:"interval_seconds"` // IP-freshness re-check cadence; default 300
|
||||
StateDir string `json:"state_dir"` // provisioned guests under <StateDir>/guests/; default /var/lib/felhom-agent
|
||||
}
|
||||
|
||||
// Enabled reports whether the split-horizon resolver should run.
|
||||
func (l LANResolverConfig) Enabled() bool { return l.Enable }
|
||||
|
||||
// WithDefaults fills upstreams/interval/state-dir and derives HostIP from the local-API bind addr.
|
||||
func (l LANResolverConfig) WithDefaults(localAPIListen string) LANResolverConfig {
|
||||
if len(l.Upstreams) == 0 {
|
||||
l.Upstreams = []string{"1.1.1.1", "8.8.8.8"}
|
||||
}
|
||||
if l.IntervalSeconds == 0 {
|
||||
l.IntervalSeconds = 300
|
||||
}
|
||||
if l.StateDir == "" {
|
||||
l.StateDir = "/var/lib/felhom-agent"
|
||||
}
|
||||
if strings.TrimSpace(l.HostIP) == "" && localAPIListen != "" {
|
||||
if h, _, err := net.SplitHostPort(localAPIListen); err == nil && h != "" && h != "0.0.0.0" {
|
||||
l.HostIP = h
|
||||
}
|
||||
}
|
||||
return l
|
||||
}
|
||||
|
||||
// LocalAPIConfig configures the per-guest local API server (doc 03 §6, slice 8A). The
|
||||
|
||||
Reference in New Issue
Block a user