mirror of
https://github.com/Control-D-Inc/ctrld.git
synced 2026-07-16 13:17:19 +02:00
fix(windows): include domainless VPN DNS adapters in discovery
This commit is contained in:
committed by
Cuong Manh Le
parent
f281466118
commit
6c5489873b
+39
-10
@@ -32,28 +32,45 @@ func DiscoverVPNDNS(ctx context.Context) []VPNDNSConfig {
|
|||||||
var vpnConfigs []VPNDNSConfig
|
var vpnConfigs []VPNDNSConfig
|
||||||
|
|
||||||
for _, aa := range aas {
|
for _, aa := range aas {
|
||||||
// Skip adapters that are not up
|
|
||||||
if aa.OperStatus != winipcfg.IfOperStatusUp {
|
if aa.OperStatus != winipcfg.IfOperStatusUp {
|
||||||
Log(ctx, logger.Debug(), "Skipping adapter %s - not up, status: %d",
|
Log(ctx, logger.Debug(), "Skipping adapter %s - not up, status: %d",
|
||||||
aa.FriendlyName(), aa.OperStatus)
|
aa.FriendlyName(), aa.OperStatus)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip software loopback
|
|
||||||
if aa.IfType == winipcfg.IfTypeSoftwareLoopback {
|
if aa.IfType == winipcfg.IfTypeSoftwareLoopback {
|
||||||
Log(ctx, logger.Debug(), "Skipping %s (software loopback)", aa.FriendlyName())
|
Log(ctx, logger.Debug(), "Skipping %s (software loopback)", aa.FriendlyName())
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// INVERT the ValidInterfaces filter: we want non-physical/non-hardware adapters
|
// INVERT the ValidInterfaces filter: we want non-physical/non-hardware adapters.
|
||||||
// that are UP and have DNS servers AND DNS suffixes
|
|
||||||
_, isValidPhysical := validInterfacesMap[aa.FriendlyName()]
|
_, isValidPhysical := validInterfacesMap[aa.FriendlyName()]
|
||||||
if isValidPhysical {
|
if isValidPhysical {
|
||||||
Log(ctx, logger.Debug(), "Skipping %s (physical/hardware adapter)", aa.FriendlyName())
|
Log(ctx, logger.Debug(), "Skipping %s (physical/hardware adapter)", aa.FriendlyName())
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collect DNS servers
|
// Skip adapters that have no routable unicast addresses. An adapter
|
||||||
|
// with only link-local (fe80::) or APIPA (169.254.x.x) addresses is
|
||||||
|
// not actually connected — its DNS servers are stale. This prevents
|
||||||
|
// picking up e.g. Tailscale's adapter when the app is installed but
|
||||||
|
// disconnected (OperStatus reports Up but only APIPA addresses exist).
|
||||||
|
hasRoutableAddr := false
|
||||||
|
for a := aa.FirstUnicastAddress; a != nil; a = a.Next {
|
||||||
|
ip := a.Address.IP()
|
||||||
|
if ip == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !ip.IsLinkLocalUnicast() {
|
||||||
|
hasRoutableAddr = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !hasRoutableAddr {
|
||||||
|
Log(ctx, logger.Debug(), "Skipping %s - no routable addresses (likely disconnected)", aa.FriendlyName())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
var servers []string
|
var servers []string
|
||||||
for dns := aa.FirstDNSServerAddress; dns != nil; dns = dns.Next {
|
for dns := aa.FirstDNSServerAddress; dns != nil; dns = dns.Next {
|
||||||
ip := dns.Address.IP()
|
ip := dns.Address.IP()
|
||||||
@@ -69,8 +86,18 @@ func DiscoverVPNDNS(ctx context.Context) []VPNDNSConfig {
|
|||||||
servers = append(servers, ipStr)
|
servers = append(servers, ipStr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collect DNS suffixes (search/match domains)
|
// Check adapter-specific (connection-specific) DNS suffix first,
|
||||||
|
// since we want to map per-adapter DNS servers to per-adapter suffixes.
|
||||||
|
// This is what most traditional VPNs set (F5, Cisco AnyConnect, GlobalProtect).
|
||||||
var domains []string
|
var domains []string
|
||||||
|
if connSuffix := strings.TrimSpace(aa.DNSSuffix()); connSuffix != "" {
|
||||||
|
domains = append(domains, connSuffix)
|
||||||
|
Log(ctx, logger.Debug(), "Using connection-specific DNS suffix for %s: %s",
|
||||||
|
aa.FriendlyName(), connSuffix)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then check supplemental DNS suffix list (used by Tailscale and
|
||||||
|
// VPN clients that register search domains via the DNS Client API).
|
||||||
for suffix := aa.FirstDNSSuffix; suffix != nil; suffix = suffix.Next {
|
for suffix := aa.FirstDNSSuffix; suffix != nil; suffix = suffix.Next {
|
||||||
domain := strings.TrimSpace(suffix.String())
|
domain := strings.TrimSpace(suffix.String())
|
||||||
if domain != "" {
|
if domain != "" {
|
||||||
@@ -78,8 +105,10 @@ func DiscoverVPNDNS(ctx context.Context) []VPNDNSConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only include interfaces that have BOTH DNS servers AND search domains
|
// Accept VPN adapters with DNS servers even without domains.
|
||||||
if len(servers) > 0 && len(domains) > 0 {
|
// Domain-less configs still provide useful DNS server IPs that
|
||||||
|
// can serve existing split-rules and OS resolver queries.
|
||||||
|
if len(servers) > 0 {
|
||||||
config := VPNDNSConfig{
|
config := VPNDNSConfig{
|
||||||
InterfaceName: aa.FriendlyName(),
|
InterfaceName: aa.FriendlyName(),
|
||||||
Servers: servers,
|
Servers: servers,
|
||||||
@@ -91,8 +120,8 @@ func DiscoverVPNDNS(ctx context.Context) []VPNDNSConfig {
|
|||||||
Log(ctx, logger.Debug(), "Found VPN DNS config - Interface: %s, Servers: %v, Domains: %v",
|
Log(ctx, logger.Debug(), "Found VPN DNS config - Interface: %s, Servers: %v, Domains: %v",
|
||||||
config.InterfaceName, config.Servers, config.Domains)
|
config.InterfaceName, config.Servers, config.Domains)
|
||||||
} else {
|
} else {
|
||||||
Log(ctx, logger.Debug(), "Skipping %s - insufficient DNS config (servers: %d, domains: %d)",
|
Log(ctx, logger.Debug(), "Skipping %s - no DNS servers found",
|
||||||
aa.FriendlyName(), len(servers), len(domains))
|
aa.FriendlyName())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user