Skip to content

Commit

Permalink
Merge pull request #179 from Control-D-Inc/release-branch-v1.3.9
Browse files Browse the repository at this point in the history
Release branch v1.3.9
  • Loading branch information
cuonglm authored Sep 18, 2024
2 parents e6586fd + 9cbd9b3 commit 7088df5
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 63 deletions.
1 change: 1 addition & 0 deletions cmd/cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -2661,6 +2661,7 @@ func resetDnsTask(p *prog, s service.Service) task {
iface = runningIface(s)
}
if isCtrldInstalled {
mainLog.Load().Debug().Msg("restore system DNS settings")
resetDnsNoLog(p)
}
iface = oldIface
Expand Down
91 changes: 30 additions & 61 deletions cmd/cli/os_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"fmt"
"net"
"os"
"os/exec"
"slices"
"strconv"
"strings"
"sync"
Expand All @@ -30,6 +30,14 @@ func setDnsIgnoreUnusableInterface(iface *net.Interface, nameservers []string) e
return setDNS(iface, nameservers)
}

func setDnsPowershellCmd(iface *net.Interface, nameservers []string) string {
nss := make([]string, 0, len(nameservers))
for _, ns := range nameservers {
nss = append(nss, strconv.Quote(ns))
}
return fmt.Sprintf("Set-DnsClientServerAddress -InterfaceIndex %d -ServerAddresses (%s)", iface.Index, strings.Join(nss, ","))
}

// setDNS sets the dns server for the provided network interface
func setDNS(iface *net.Interface, nameservers []string) error {
if len(nameservers) == 0 {
Expand All @@ -41,22 +49,25 @@ func setDNS(iface *net.Interface, nameservers []string) error {
if windowsHasLocalDnsServerRunning() {
file := absHomeDir(windowsForwardersFilename)
oldForwardersContent, _ := os.ReadFile(file)
if err := os.WriteFile(file, []byte(strings.Join(nameservers, ",")), 0600); err != nil {
hasLocalIPv6Listener := needLocalIPv6Listener()
forwarders := slices.DeleteFunc(slices.Clone(nameservers), func(s string) bool {
if !hasLocalIPv6Listener {
return false
}
return s == "::1"
})
if err := os.WriteFile(file, []byte(strings.Join(forwarders, ",")), 0600); err != nil {
mainLog.Load().Warn().Err(err).Msg("could not save forwarders settings")
}
oldForwarders := strings.Split(string(oldForwardersContent), ",")
if err := addDnsServerForwarders(nameservers, oldForwarders); err != nil {
if err := addDnsServerForwarders(forwarders, oldForwarders); err != nil {
mainLog.Load().Warn().Err(err).Msg("could not set forwarders settings")
}
}
})
primaryDNS := nameservers[0]
if err := setPrimaryDNS(iface, primaryDNS, true); err != nil {
return err
}
if len(nameservers) > 1 {
secondaryDNS := nameservers[1]
_ = addSecondaryDNS(iface, secondaryDNS)
out, err := powershell(setDnsPowershellCmd(iface, nameservers))
if err != nil {
return fmt.Errorf("%w: %s", err, string(out))
}
return nil
}
Expand Down Expand Up @@ -85,17 +96,13 @@ func resetDNS(iface *net.Interface) error {
}
})

// Restoring ipv6 first.
if ctrldnet.SupportsIPv6ListenLocal() {
if output, err := netsh("interface", "ipv6", "set", "dnsserver", strconv.Itoa(iface.Index), "dhcp"); err != nil {
mainLog.Load().Warn().Err(err).Msgf("failed to reset ipv6 DNS: %s", string(output))
}
}
// Restoring ipv4 DHCP.
output, err := netsh("interface", "ipv4", "set", "dnsserver", strconv.Itoa(iface.Index), "dhcp")
// Restoring DHCP settings.
cmd := fmt.Sprintf("Set-DnsClientServerAddress -InterfaceIndex %d -ResetServerAddresses", iface.Index)
out, err := powershell(cmd)
if err != nil {
return fmt.Errorf("%s: %w", string(output), err)
return fmt.Errorf("%w: %s", err, string(out))
}

// If there's static DNS saved, restoring it.
if nss := savedStaticNameservers(iface); len(nss) > 0 {
v4ns := make([]string, 0, 2)
Expand All @@ -112,54 +119,14 @@ func resetDNS(iface *net.Interface) error {
if len(ns) == 0 {
continue
}
primaryDNS := ns[0]
if err := setPrimaryDNS(iface, primaryDNS, false); err != nil {
if err := setDNS(iface, ns); err != nil {
return err
}
if len(ns) > 1 {
secondaryDNS := ns[1]
_ = addSecondaryDNS(iface, secondaryDNS)
}
}
}
return nil
}

func setPrimaryDNS(iface *net.Interface, dns string, disablev6 bool) error {
ipVer := "ipv4"
if ctrldnet.IsIPv6(dns) {
ipVer = "ipv6"
}
idx := strconv.Itoa(iface.Index)
output, err := netsh("interface", ipVer, "set", "dnsserver", idx, "static", dns)
if err != nil {
mainLog.Load().Error().Err(err).Msgf("failed to set primary DNS: %s", string(output))
return err
}
if disablev6 && ipVer == "ipv4" && ctrldnet.SupportsIPv6ListenLocal() {
// Disable IPv6 DNS, so the query will be fallback to IPv4.
_, _ = netsh("interface", "ipv6", "set", "dnsserver", idx, "static", "::1", "primary")
}

return nil
}

func addSecondaryDNS(iface *net.Interface, dns string) error {
ipVer := "ipv4"
if ctrldnet.IsIPv6(dns) {
ipVer = "ipv6"
}
output, err := netsh("interface", ipVer, "add", "dns", strconv.Itoa(iface.Index), dns, "index=2")
if err != nil {
mainLog.Load().Warn().Err(err).Msgf("failed to add secondary DNS: %s", string(output))
}
return nil
}

func netsh(args ...string) ([]byte, error) {
return exec.Command("netsh", args...).Output()
}

func currentDNS(iface *net.Interface) []string {
luid, err := winipcfg.LUIDFromIndex(uint32(iface.Index))
if err != nil {
Expand Down Expand Up @@ -200,7 +167,9 @@ func currentStaticDNS(iface *net.Interface) ([]string, error) {
out, err := powershell(cmd)
if err == nil && len(out) > 0 {
found = true
ns = append(ns, strings.Split(string(out), ",")...)
for _, e := range strings.Split(string(out), ",") {
ns = append(ns, strings.TrimRight(e, "\x00"))
}
}
}
}
Expand Down
12 changes: 10 additions & 2 deletions cmd/cli/prog.go
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,10 @@ func (p *prog) setDNS() {
if needRFC1918Listeners(lc) {
nameservers = append(nameservers, ctrld.Rfc1918Addresses()...)
}
if needLocalIPv6Listener() {
nameservers = append(nameservers, "::1")
}
slices.Sort(nameservers)
if err := setDNS(netIface, nameservers); err != nil {
logger.Error().Err(err).Msgf("could not set DNS for interface")
return
Expand Down Expand Up @@ -665,7 +669,7 @@ func (p *prog) dnsWatchdog(iface *net.Interface, nameservers []string, allIfaces
}
}
if allIfaces {
withEachPhysicalInterfaces(iface.Name, "re-applying DNS", func(i *net.Interface) error {
withEachPhysicalInterfaces(iface.Name, "", func(i *net.Interface) error {
if dnsChanged(i, ns) {
if err := setDnsIgnoreUnusableInterface(i, nameservers); err != nil {
mainLog.Load().Error().Err(err).Str("iface", i.Name).Msgf("could not re-apply DNS settings")
Expand Down Expand Up @@ -977,7 +981,11 @@ func savedStaticNameservers(iface *net.Interface) []string {
func dnsChanged(iface *net.Interface, nameservers []string) bool {
curNameservers, _ := currentStaticDNS(iface)
slices.Sort(curNameservers)
return !slices.Equal(curNameservers, nameservers)
if !slices.Equal(curNameservers, nameservers) {
mainLog.Load().Debug().Msgf("interface %q current DNS settings: %v, expected: %v", iface.Name, curNameservers, nameservers)
return true
}
return false
}

// selfUninstallCheck checks if the error dues to controld.InvalidConfigCode, perform self-uninstall then.
Expand Down

0 comments on commit 7088df5

Please sign in to comment.