mirror of
https://github.com/kubenetworks/kubevpn.git
synced 2025-10-22 15:00:35 +08:00
141 lines
4.0 KiB
Go
141 lines
4.0 KiB
Go
//go:build linux
|
|
|
|
package dns
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/docker/docker/libnetwork/resolvconf"
|
|
miekgdns "github.com/miekg/dns"
|
|
log "github.com/sirupsen/logrus"
|
|
|
|
"github.com/coredns/caddy"
|
|
_ "github.com/coredns/coredns/core/dnsserver"
|
|
_ "github.com/coredns/coredns/core/plugin"
|
|
)
|
|
|
|
// systemd-resolve --status, systemd-resolve --flush-caches
|
|
func (c *Config) SetupDNS() error {
|
|
clientConfig := c.Config
|
|
useLocalDNS := c.UseLocalDNS
|
|
tunName := c.TunName
|
|
|
|
existNameservers := make([]string, 0)
|
|
existSearches := make([]string, 0)
|
|
filename := filepath.Join("/", "etc", "resolv.conf")
|
|
readFile, err := os.ReadFile(filename)
|
|
if err == nil {
|
|
resolvConf, err := miekgdns.ClientConfigFromReader(bytes.NewBufferString(string(readFile)))
|
|
if err == nil {
|
|
if len(resolvConf.Servers) != 0 {
|
|
existNameservers = append(existNameservers, resolvConf.Servers...)
|
|
}
|
|
if len(resolvConf.Search) != 0 {
|
|
existSearches = append(existSearches, resolvConf.Search...)
|
|
}
|
|
}
|
|
}
|
|
|
|
if useLocalDNS {
|
|
if err = SetupLocalDNS(clientConfig, existNameservers); err != nil {
|
|
return err
|
|
}
|
|
clientConfig.Servers[0] = "127.0.0.1"
|
|
}
|
|
|
|
// TODO consider use https://wiki.debian.org/NetworkManager and nmcli to config DNS
|
|
// try to solve:
|
|
// sudo systemd-resolve --set-dns 172.28.64.10 --interface tun0 --set-domain=vke-system.svc.cluster.local --set-domain=svc.cluster.local --set-domain=cluster.local
|
|
//Failed to set DNS configuration: Unit dbus-org.freedesktop.resolve1.service not found.
|
|
// ref: https://superuser.com/questions/1427311/activation-via-systemd-failed-for-unit-dbus-org-freedesktop-resolve1-service
|
|
// systemctl enable systemd-resolved.service
|
|
_ = exec.Command("systemctl", "enable", "systemd-resolved.service").Run()
|
|
// systemctl start systemd-resolved.service
|
|
_ = exec.Command("systemctl", "start", "systemd-resolved.service").Run()
|
|
//systemctl status systemd-resolved.service
|
|
_ = exec.Command("systemctl", "status", "systemd-resolved.service").Run()
|
|
|
|
cmd := exec.Command("systemd-resolve", []string{
|
|
"--set-dns",
|
|
clientConfig.Servers[0],
|
|
"--interface",
|
|
tunName,
|
|
"--set-domain=" + clientConfig.Search[0],
|
|
"--set-domain=" + clientConfig.Search[1],
|
|
"--set-domain=" + clientConfig.Search[2],
|
|
}...)
|
|
output, err := cmd.CombinedOutput()
|
|
if err != nil {
|
|
log.Debugf("failed to exec cmd: %s, message: %s, ignore", strings.Join(cmd.Args, " "), string(output))
|
|
}
|
|
|
|
if len(existNameservers) != 0 {
|
|
clientConfig.Servers = append(clientConfig.Servers, existNameservers...)
|
|
}
|
|
if len(existSearches) != 0 {
|
|
clientConfig.Search = append(clientConfig.Search, existSearches...)
|
|
}
|
|
|
|
return WriteResolvConf(*clientConfig)
|
|
}
|
|
|
|
func SetupLocalDNS(clientConfig *miekgdns.ClientConfig, existNameservers []string) error {
|
|
corefile, err := BuildCoreFile(CoreFileTmpl{
|
|
UpstreamDNS: clientConfig.Servers[0],
|
|
Nameservers: strings.Join(existNameservers, " "),
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
log.Debugf("corefile content: %s", string(corefile.Body()))
|
|
|
|
// Start your engines
|
|
instance, err := caddy.Start(corefile)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Twiddle your thumbs
|
|
go instance.Wait()
|
|
return nil
|
|
}
|
|
|
|
func (c *Config) CancelDNS() {
|
|
c.updateHosts("")
|
|
|
|
filename := filepath.Join("/", "etc", "resolv.conf")
|
|
_ = os.Rename(getBackupFilename(filename), filename)
|
|
}
|
|
|
|
func GetHostFile() string {
|
|
return "/etc/hosts"
|
|
}
|
|
|
|
func WriteResolvConf(config miekgdns.ClientConfig) error {
|
|
var options []string
|
|
if config.Ndots != 0 {
|
|
options = append(options, fmt.Sprintf("ndots:%d", config.Ndots))
|
|
}
|
|
if config.Attempts != 0 {
|
|
options = append(options, fmt.Sprintf("attempts:%d", config.Attempts))
|
|
}
|
|
if config.Timeout != 0 {
|
|
options = append(options, fmt.Sprintf("timeout:%d", config.Timeout))
|
|
}
|
|
|
|
filename := filepath.Join("/", "etc", "resolv.conf")
|
|
_ = os.Rename(filename, getBackupFilename(filename))
|
|
_, err := resolvconf.Build(filename, config.Servers, config.Search, options)
|
|
return err
|
|
}
|
|
|
|
func getBackupFilename(filename string) string {
|
|
return filename + ".kubevpn_backup"
|
|
}
|