diff --git a/internal/api/v1/helpers.go b/internal/api/v1/helpers.go index cc3d686..1ecf332 100644 --- a/internal/api/v1/helpers.go +++ b/internal/api/v1/helpers.go @@ -104,7 +104,12 @@ func (api *API) reconcileNetworking() { // DNS target IP depends on service type: // tcp-passthrough (k8s): DNS → k8s LB IP (LAN traffic goes direct to k8s) // http/static: DNS → Central IP (HAProxy terminates TLS) - centralIP, _ := network.GetWildCentralIP() + // Use the configured dnsmasq IP (eth0) as Central's IP, not auto-detected + // (auto-detect can pick wlan0 if that's the default route). + centralIP := globalCfg.Cloud.Dnsmasq.IP + if centralIP == "" { + centralIP, _ = network.GetWildCentralIP() + } if centralIP == "" { centralIP = "127.0.0.1" } diff --git a/internal/dnsmasq/config.go b/internal/dnsmasq/config.go index 5c89b3a..5ab0f83 100644 --- a/internal/dnsmasq/config.go +++ b/internal/dnsmasq/config.go @@ -36,12 +36,20 @@ func (g *ConfigGenerator) GetConfigPath() string { // Generate creates a dnsmasq configuration from the app config // It auto-detects the Wild Central server's IP address func (g *ConfigGenerator) Generate(cfg *config.GlobalConfig, clouds []config.InstanceConfig) string { - // Get the Wild Central IP address - dnsIP, err := network.GetWildCentralIP() - if err != nil { - slog.Error("failed to detect Wild Central IP", "component", "dnsmasq", "op", "generate", "error", err) - // Fall back to empty string if detection fails - dnsIP = "" + // Use configured dnsmasq IP (bound to eth0), falling back to auto-detect. + // Auto-detect can pick wlan0 if that's the default route, which is wrong + // when dnsmasq is only listening on eth0. + dnsIP := "" + if cfg != nil { + dnsIP = cfg.Cloud.Dnsmasq.IP + } + if dnsIP == "" { + var err error + dnsIP, err = network.GetWildCentralIP() + if err != nil { + slog.Error("failed to detect Wild Central IP", "component", "dnsmasq", "op", "generate", "error", err) + dnsIP = "" + } } resolution_section := ""