From 24a97de5dc8b708676c9d81cbde27dd473c6c0f4 Mon Sep 17 00:00:00 2001 From: naison <895703375@qq.com> Date: Fri, 29 Nov 2024 20:25:26 +0800 Subject: [PATCH] hotfix: add more resolver on macOS (#382) --- cmd/kubevpn/cmds/daemon.go | 4 ++ pkg/daemon/action/quit.go | 14 +---- pkg/dns/dns.go | 7 ++- pkg/dns/dns_unix.go | 113 ++++++++++++++++++++++--------------- pkg/handler/connect.go | 22 +++++--- pkg/util/dns.go | 26 +++------ pkg/util/file.go | 10 ++++ 7 files changed, 107 insertions(+), 89 deletions(-) diff --git a/cmd/kubevpn/cmds/daemon.go b/cmd/kubevpn/cmds/daemon.go index 18af30b4f..9395c7900 100644 --- a/cmd/kubevpn/cmds/daemon.go +++ b/cmd/kubevpn/cmds/daemon.go @@ -17,6 +17,7 @@ import ( "github.com/wencaiwulue/kubevpn/v2/pkg/config" "github.com/wencaiwulue/kubevpn/v2/pkg/daemon" "github.com/wencaiwulue/kubevpn/v2/pkg/daemon/action" + "github.com/wencaiwulue/kubevpn/v2/pkg/dns" "github.com/wencaiwulue/kubevpn/v2/pkg/util" ) @@ -35,6 +36,9 @@ func CmdDaemon(_ cmdutil.Factory) *cobra.Command { if opt.IsSudo { go util.StartupPProf(config.SudoPProfPort) + _ = os.RemoveAll("/etc/resolver") + _ = dns.CleanupHosts() + _ = util.CleanupTempKubeConfigFile() } else { go util.StartupPProf(config.PProfPort) } diff --git a/pkg/daemon/action/quit.go b/pkg/daemon/action/quit.go index 9c2b0d8f1..ca815a4c1 100644 --- a/pkg/daemon/action/quit.go +++ b/pkg/daemon/action/quit.go @@ -3,10 +3,7 @@ package action import ( "context" "io" - "io/fs" "os" - "path/filepath" - "strings" log "github.com/sirupsen/logrus" @@ -57,7 +54,7 @@ func (svr *Server) Quit(req *rpc.QuitRequest, resp rpc.Daemon_QuitServer) error svr.Cancel = nil } - _ = cleanupTempKubeConfigFile() + _ = util.CleanupTempKubeConfigFile() return nil } @@ -78,12 +75,3 @@ func (r *quitWarp) Write(p []byte) (n int, err error) { func newQuitWarp(server rpc.Daemon_QuitServer) io.Writer { return &quitWarp{server: server} } - -func cleanupTempKubeConfigFile() error { - return filepath.Walk(os.TempDir(), func(path string, info fs.FileInfo, err error) error { - if strings.HasSuffix(path, ".kubeconfig") { - return os.Remove(path) - } - return err - }) -} diff --git a/pkg/dns/dns.go b/pkg/dns/dns.go index d35cb8968..a79a832dd 100644 --- a/pkg/dns/dns.go +++ b/pkg/dns/dns.go @@ -30,9 +30,10 @@ import ( ) type Config struct { - Config *miekgdns.ClientConfig - Ns []string - TunName string + Config *miekgdns.ClientConfig + Ns []string + Services []v12.Service + TunName string Hosts []Entry Lock *sync.Mutex diff --git a/pkg/dns/dns_unix.go b/pkg/dns/dns_unix.go index a2d2f7840..f1d4078a9 100644 --- a/pkg/dns/dns_unix.go +++ b/pkg/dns/dns_unix.go @@ -6,7 +6,6 @@ import ( "bytes" "context" "fmt" - "io/fs" "os" "os/exec" "path/filepath" @@ -16,6 +15,7 @@ import ( "github.com/fsnotify/fsnotify" miekgdns "github.com/miekg/dns" log "github.com/sirupsen/logrus" + v12 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/util/sets" ) @@ -38,7 +38,6 @@ func (c *Config) SetupDNS(ctx context.Context) error { func (c *Config) usingResolver(ctx context.Context) { var clientConfig = c.Config - var ns = c.Ns path := "/etc/resolver" if _, err := os.Stat(path); os.IsNotExist(err) { @@ -56,33 +55,28 @@ func (c *Config) usingResolver(ctx context.Context) { Ndots: clientConfig.Ndots, Timeout: clientConfig.Timeout, } - var searchDomain []string - for _, search := range clientConfig.Search { - for _, s := range strings.Split(search, ".") { - if s != "" { - searchDomain = append(searchDomain, s) - } - } - } - for _, s := range sets.New[string](searchDomain...).Insert(ns...).UnsortedList() { - filename := "/etc/resolver/" + s + for _, filename := range GetResolvers(c.Config.Search, c.Ns, c.Services) { content, err := os.ReadFile(filename) if os.IsNotExist(err) { _ = os.WriteFile(filename, []byte(toString(newConfig)), 0644) - } else if err == nil { - var conf *miekgdns.ClientConfig - conf, err = miekgdns.ClientConfigFromReader(bytes.NewBufferString(string(content))) - if err != nil { - log.Errorf("Parse resolver %s error: %v", filename, err) - continue - } - conf.Servers = append([]string{clientConfig.Servers[0]}, conf.Servers...) - err = os.WriteFile(filename, []byte(toString(*conf)), 0644) - if err != nil { - log.Errorf("Failed to write resovler %s error: %v", filename, err) - } - } else { + continue + } + if err != nil { log.Errorf("Failed to read resovler %s error: %v", filename, err) + continue + } + + var conf *miekgdns.ClientConfig + conf, err = miekgdns.ClientConfigFromReader(bytes.NewBufferString(string(content))) + if err != nil { + log.Errorf("Parse resolver %s error: %v", filename, err) + continue + } + // insert current name server to first location + conf.Servers = append([]string{clientConfig.Servers[0]}, conf.Servers...) + err = os.WriteFile(filename, []byte(toString(*conf)), 0644) + if err != nil { + log.Errorf("Failed to write resovler %s error: %v", filename, err) } } } @@ -164,28 +158,22 @@ func (c *Config) CancelDNS() { if cancel != nil { cancel() } - dir := "/etc/resolver" - _ = filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error { - if err != nil { - return err - } - if d.IsDir() { - return nil - } - content, err := os.ReadFile(path) + for _, filename := range GetResolvers(c.Config.Search, c.Ns, c.Services) { + content, err := os.ReadFile(filename) if err != nil { - return nil + continue } var conf *miekgdns.ClientConfig - conf, err = miekgdns.ClientConfigFromReader(bytes.NewBufferString(string(content))) + conf, err = miekgdns.ClientConfigFromReader(bytes.NewBufferString(strings.TrimSpace(string(content)))) if err != nil { - return nil + continue } // if not has this DNS server, do nothing if !sets.New[string](conf.Servers...).Has(c.Config.Servers[0]) { - return nil + continue } - for i := 0; i < len(conf.Servers); i++ { + // reverse delete + for i := len(conf.Servers) - 1; i >= 0; i-- { if conf.Servers[i] == c.Config.Servers[0] { conf.Servers = append(conf.Servers[:i], conf.Servers[i+1:]...) i-- @@ -195,17 +183,50 @@ func (c *Config) CancelDNS() { } } if len(conf.Servers) == 0 { - os.Remove(path) - return nil + _ = os.Remove(filename) + continue } - err = os.WriteFile(path, []byte(toString(*conf)), 0644) + err = os.WriteFile(filename, []byte(toString(*conf)), 0644) if err != nil { - log.Errorf("Failed to write resovler %s error: %v", path, err) + log.Errorf("Failed to write resovler %s error: %v", filename, err) } - return nil - }) + } //networkCancel() - c.removeHosts(sets.New[Entry]().Insert(c.Hosts...).UnsortedList()) + _ = c.removeHosts(sets.New[Entry]().Insert(c.Hosts...).UnsortedList()) +} + +// GetResolvers +// service name: authors +// namespace: test +// create resolvers suffix: +// [authors.test.svc.cluster.local] +// local +// cluster +// cluster.local +// svc.cluster +// test.svc +func GetResolvers(searchList []string, nsList []string, serviceName []v12.Service) []string { + result := sets.New[string]().Insert(searchList...).Insert(nsList...) + + const splitter = "." + // support default.svc, cluster.local + for _, s := range searchList { + split := strings.Split(s, splitter) + for i := range len(split) - 1 { + result.Insert(fmt.Sprintf("%s.%s", split[i], split[i+1])) + } + result.Insert(split...) + } + // authors.default + for _, service := range serviceName { + result.Insert(fmt.Sprintf("%s.%s", service.Name, service.Namespace)) + } + + var resolvers []string + for _, s := range sets.List(result) { + resolvers = append(resolvers, filepath.Join("/etc/resolver/", s)) + } + return resolvers } /* diff --git a/pkg/handler/connect.go b/pkg/handler/connect.go index 9755c262c..4bf41dbff 100644 --- a/pkg/handler/connect.go +++ b/pkg/handler/connect.go @@ -533,7 +533,6 @@ func (c *ConnectOptions) deleteFirewallRule(ctx context.Context) { } func (c *ConnectOptions) setupDNS(ctx context.Context) error { - const port = 53 const portTCP = 10800 pod, err := c.GetRunningPodList(ctx) if err != nil { @@ -546,9 +545,6 @@ func (c *ConnectOptions) setupDNS(ctx context.Context) error { log.Errorln(err) return err } - if relovConf.Port == "" { - relovConf.Port = strconv.Itoa(port) - } marshal, _ := json.Marshal(relovConf) log.Debugf("Get DNS service config: %v", string(marshal)) @@ -585,16 +581,24 @@ func (c *ConnectOptions) setupDNS(ctx context.Context) error { } } } + + var serviceList []v1.Service + services, err := c.clientset.CoreV1().Services(c.Namespace).List(ctx, metav1.ListOptions{}) + if err == nil { + serviceList = append(serviceList, services.Items...) + } + tunName, err := c.GetTunDeviceName() if err != nil { return err } c.dnsConfig = &dns.Config{ - Config: relovConf, - Ns: ns, - TunName: tunName, - Hosts: c.extraHost, - Lock: c.Lock, + Config: relovConf, + Ns: ns, + Services: serviceList, + TunName: tunName, + Hosts: c.extraHost, + Lock: c.Lock, } log.Debugf("Setup DNS...") if err = c.dnsConfig.SetupDNS(ctx); err != nil { diff --git a/pkg/util/dns.go b/pkg/util/dns.go index 4a6fff64b..e0298f207 100644 --- a/pkg/util/dns.go +++ b/pkg/util/dns.go @@ -3,7 +3,8 @@ package util import ( "bytes" "context" - "fmt" + "strconv" + "strings" "github.com/miekg/dns" "github.com/pkg/errors" @@ -16,30 +17,19 @@ import ( "github.com/wencaiwulue/kubevpn/v2/pkg/config" ) -func GetDNSServiceIPFromPod(ctx context.Context, clientset *kubernetes.Clientset, config *rest.Config, podName, namespace string) (*dns.ClientConfig, error) { - str, err := Shell(ctx, clientset, config, podName, "", namespace, []string{"cat", "/etc/resolv.conf"}) +func GetDNSServiceIPFromPod(ctx context.Context, clientset *kubernetes.Clientset, conf *rest.Config, podName, namespace string) (*dns.ClientConfig, error) { + str, err := Shell(ctx, clientset, conf, podName, config.ContainerSidecarVPN, namespace, []string{"cat", "/etc/resolv.conf"}) if err != nil { return nil, err } - resolvConf, err := dns.ClientConfigFromReader(bytes.NewBufferString(str)) - if err == nil { - return resolvConf, nil - } - - ips, err := GetDNSIPFromDnsPod(ctx, clientset) + resolvConf, err := dns.ClientConfigFromReader(bytes.NewBufferString(strings.TrimSpace(str))) if err != nil { return nil, err } - clientConfig := dns.ClientConfig{ - Servers: ips, - Search: []string{ - fmt.Sprintf("%s.svc.cluster.local", namespace), - "svc.cluster.local", - "cluster.local", - }, - Ndots: 5, + if resolvConf.Port == "" { + resolvConf.Port = strconv.Itoa(53) } - return &clientConfig, nil + return resolvConf, nil } func GetDNSIPFromDnsPod(ctx context.Context, clientset *kubernetes.Clientset) (ips []string, err error) { diff --git a/pkg/util/file.go b/pkg/util/file.go index 86b8440bb..1e12cf6d8 100644 --- a/pkg/util/file.go +++ b/pkg/util/file.go @@ -3,6 +3,7 @@ package util import ( "fmt" "io" + "io/fs" "math" "net/http" "os" @@ -120,3 +121,12 @@ func ParseDirMapping(dir string) (local, remote string, err error) { remote = dir[index+1:] return } + +func CleanupTempKubeConfigFile() error { + return filepath.Walk(os.TempDir(), func(path string, info fs.FileInfo, err error) error { + if strings.HasSuffix(path, ".kubeconfig") { + return os.Remove(path) + } + return err + }) +}