mirror of
https://github.com/Control-D-Inc/ctrld.git
synced 2026-03-13 10:26:06 +00:00
101 lines
2.8 KiB
Go
101 lines
2.8 KiB
Go
//go:build windows
|
|
|
|
package ctrld
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
"syscall"
|
|
|
|
"golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
|
|
)
|
|
|
|
// DiscoverVPNDNS discovers DNS servers and search domains from non-physical (VPN) interfaces.
|
|
// Only called when dnsIntercept is active.
|
|
func DiscoverVPNDNS(ctx context.Context) []VPNDNSConfig {
|
|
logger := LoggerFromCtx(ctx)
|
|
|
|
Log(ctx, logger.Debug(), "Discovering VPN DNS configurations on Windows")
|
|
|
|
flags := winipcfg.GAAFlagIncludeGateways | winipcfg.GAAFlagIncludePrefix
|
|
aas, err := winipcfg.GetAdaptersAddresses(syscall.AF_UNSPEC, flags)
|
|
if err != nil {
|
|
Log(ctx, logger.Error().Err(err), "Failed to get adapters addresses")
|
|
return nil
|
|
}
|
|
|
|
Log(ctx, logger.Debug(), "Found %d network adapters", len(aas))
|
|
|
|
// Get valid (physical/hardware) interfaces to filter them out
|
|
validInterfacesMap := ValidInterfaces(ctx)
|
|
|
|
var vpnConfigs []VPNDNSConfig
|
|
|
|
for _, aa := range aas {
|
|
// Skip adapters that are not up
|
|
if aa.OperStatus != winipcfg.IfOperStatusUp {
|
|
Log(ctx, logger.Debug(), "Skipping adapter %s - not up, status: %d",
|
|
aa.FriendlyName(), aa.OperStatus)
|
|
continue
|
|
}
|
|
|
|
// Skip software loopback
|
|
if aa.IfType == winipcfg.IfTypeSoftwareLoopback {
|
|
Log(ctx, logger.Debug(), "Skipping %s (software loopback)", aa.FriendlyName())
|
|
continue
|
|
}
|
|
|
|
// 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()]
|
|
if isValidPhysical {
|
|
Log(ctx, logger.Debug(), "Skipping %s (physical/hardware adapter)", aa.FriendlyName())
|
|
continue
|
|
}
|
|
|
|
// Collect DNS servers
|
|
var servers []string
|
|
for dns := aa.FirstDNSServerAddress; dns != nil; dns = dns.Next {
|
|
ip := dns.Address.IP()
|
|
if ip == nil {
|
|
continue
|
|
}
|
|
|
|
ipStr := ip.String()
|
|
if ip.IsLoopback() {
|
|
continue
|
|
}
|
|
|
|
servers = append(servers, ipStr)
|
|
}
|
|
|
|
// Collect DNS suffixes (search/match domains)
|
|
var domains []string
|
|
for suffix := aa.FirstDNSSuffix; suffix != nil; suffix = suffix.Next {
|
|
domain := strings.TrimSpace(suffix.String())
|
|
if domain != "" {
|
|
domains = append(domains, domain)
|
|
}
|
|
}
|
|
|
|
// Only include interfaces that have BOTH DNS servers AND search domains
|
|
if len(servers) > 0 && len(domains) > 0 {
|
|
config := VPNDNSConfig{
|
|
InterfaceName: aa.FriendlyName(),
|
|
Servers: servers,
|
|
Domains: domains,
|
|
}
|
|
|
|
vpnConfigs = append(vpnConfigs, config)
|
|
|
|
Log(ctx, logger.Debug(), "Found VPN DNS config - Interface: %s, Servers: %v, Domains: %v",
|
|
config.InterfaceName, config.Servers, config.Domains)
|
|
} else {
|
|
Log(ctx, logger.Debug(), "Skipping %s - insufficient DNS config (servers: %d, domains: %d)",
|
|
aa.FriendlyName(), len(servers), len(domains))
|
|
}
|
|
}
|
|
|
|
Log(ctx, logger.Debug(), "VPN DNS discovery completed: found %d VPN interfaces", len(vpnConfigs))
|
|
return vpnConfigs
|
|
} |