From ed0691d56f663f7a6f3dfe4fce455356e0e0c087 Mon Sep 17 00:00:00 2001 From: Paul Payne Date: Thu, 9 Jul 2026 15:46:35 +0000 Subject: [PATCH] feat: Split DNS with correct IPs per service type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix dnsmasq reconciliation to use the correct DNS target IP: - tcp-passthrough (k8s instances): DNS → k8s LB IP (LAN direct) - http/static (Central apps): DNS → Central IP (HAProxy terminates) Also handle ExtraDomains properly: - Internal domains (internal.cloud.payne.io) get local=/ entries to prevent upstream DNS forwarding - Extra domains get their own dnsmasq address= entries - HAProxy already propagated ExtraDomains for SNI ACLs Verified: cloud.payne.io → 192.168.8.240 (direct to k8s), cloud2.payne.io → 192.168.8.80, central.payne.io → 192.168.8.151. SNI routing through HAProxy works for both instances. Co-Authored-By: Claude Opus 4.6 (1M context) --- internal/api/v1/helpers.go | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/internal/api/v1/helpers.go b/internal/api/v1/helpers.go index 274e060..cc3d686 100644 --- a/internal/api/v1/helpers.go +++ b/internal/api/v1/helpers.go @@ -101,8 +101,9 @@ func (api *API) reconcileNetworking() { } // Generate dnsmasq DNS entries from registered services. - // All service domains resolve to Central's IP (where HAProxy listens). - // HAProxy then routes to the actual backend based on SNI or Host header. + // 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() if centralIP == "" { centralIP = "127.0.0.1" @@ -113,9 +114,27 @@ func (api *API) reconcileNetworking() { if svc.Reach == services.ReachOff || svc.Domain == "" { continue } + + // Choose the DNS target IP based on service type + dnsIP := centralIP + if svc.Backend.Type == services.BackendTCPPassthrough { + // k8s instances: LAN clients connect directly to the k8s LB + dnsIP = extractHost(svc.Backend.Address) + } + + // Primary domain ic := config.InstanceConfig{} ic.Cloud.Domain = svc.Domain - ic.Cluster.LoadBalancerIp = centralIP // DNS points to Central, not the backend + ic.Cluster.LoadBalancerIp = dnsIP + + // Extra domains (e.g., internal.cloud.payne.io) + for _, extra := range svc.ExtraDomains { + if strings.HasPrefix(extra, "internal.") { + // Internal-only domain: local=/ prevents upstream DNS forwarding + ic.Cloud.InternalDomain = extra + } + } + instanceConfigs = append(instanceConfigs, ic) }