Skip to content

Commit

Permalink
Support non-openresolv for DNS on Linux
Browse files Browse the repository at this point in the history
  • Loading branch information
lixmal committed Jan 11, 2025
1 parent 168ea95 commit f90c9c9
Showing 1 changed file with 66 additions and 6 deletions.
72 changes: 66 additions & 6 deletions client/internal/dns/resolvconf_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"fmt"
"net/netip"
"os/exec"
"strings"

log "github.com/sirupsen/logrus"

Expand All @@ -15,23 +16,64 @@ import (

const resolvconfCommand = "resolvconf"

// resolvconfType represents the type of resolvconf implementation
type resolvconfType int

func (r resolvconfType) String() string {
switch r {
case typeOpenresolv:
return "openresolv"
case typeResolvconf:
return "resolvconf"
default:
return "unknown"
}
}

const (
typeOpenresolv resolvconfType = iota
typeResolvconf
)

type resolvconf struct {
ifaceName string
implType resolvconfType

originalSearchDomains []string
originalNameServers []string
othersConfigs []string
}

// supported "openresolv" only
func detectResolvconfType() (resolvconfType, error) {
cmd := exec.Command(resolvconfCommand, "--version")
out, err := cmd.Output()
if err != nil {
return typeOpenresolv, fmt.Errorf("failed to determine resolvconf type: %w", err)
}

if strings.Contains(string(out), "openresolv") {
return typeOpenresolv, nil
}
return typeResolvconf, nil
}

func newResolvConfConfigurator(wgInterface string) (*resolvconf, error) {
resolvConfEntries, err := parseDefaultResolvConf()
if err != nil {
log.Errorf("could not read original search domains from %s: %s", defaultResolvConfPath, err)
}

implType, err := detectResolvconfType()
if err != nil {
log.Warnf("failed to detect resolvconf type, defaulting to openresolv: %v", err)
implType = typeOpenresolv
} else {
log.Infof("detected resolvconf type: %v", implType)
}

return &resolvconf{
ifaceName: wgInterface,
implType: implType,
originalSearchDomains: resolvConfEntries.searchDomains,
originalNameServers: resolvConfEntries.nameServers,
othersConfigs: resolvConfEntries.others,
Expand Down Expand Up @@ -80,8 +122,15 @@ func (r *resolvconf) applyDNSConfig(config HostDNSConfig, stateManager *stateman
}

func (r *resolvconf) restoreHostDNS() error {
// openresolv only, debian resolvconf doesn't support "-f"
cmd := exec.Command(resolvconfCommand, "-f", "-d", r.ifaceName)
var cmd *exec.Cmd

switch r.implType {
case typeOpenresolv:
cmd = exec.Command(resolvconfCommand, "-f", "-d", r.ifaceName)
case typeResolvconf:
cmd = exec.Command(resolvconfCommand, "-d", r.ifaceName)
}

_, err := cmd.Output()
if err != nil {
return fmt.Errorf("removing resolvconf configuration for %s interface: %w", r.ifaceName, err)
Expand All @@ -91,10 +140,21 @@ func (r *resolvconf) restoreHostDNS() error {
}

func (r *resolvconf) applyConfig(content bytes.Buffer) error {
// openresolv only, debian resolvconf doesn't support "-x"
cmd := exec.Command(resolvconfCommand, "-x", "-a", r.ifaceName)
var cmd *exec.Cmd

switch r.implType {
case typeOpenresolv:
// OpenResolv supports exclusive mode with -x
cmd = exec.Command(resolvconfCommand, "-x", "-a", r.ifaceName)
case typeResolvconf:
cmd = exec.Command(resolvconfCommand, "-a", r.ifaceName)
default:
return fmt.Errorf("unsupported resolvconf type: %v", r.implType)
}

cmd.Stdin = &content
_, err := cmd.Output()
out, err := cmd.Output()
log.Tracef("resolvconf output: %s", out)
if err != nil {
return fmt.Errorf("applying resolvconf configuration for %s interface: %w", r.ifaceName, err)
}
Expand Down

0 comments on commit f90c9c9

Please sign in to comment.