From c0208cb94712b66e4fbe64d285ca7c2b90984e01 Mon Sep 17 00:00:00 2001 From: odboy Date: Tue, 12 Nov 2024 20:34:02 +0800 Subject: [PATCH] fix: more bug fix --- PodCurlName.md | 10 ++++ README.md | 35 +++++++++++ cache/resolve_record.go | 9 +++ common/set.go | 53 +++++++++++++++++ config/dns_server.go | 3 +- core/{handler.go => dns_handler.go} | 92 +++++++++++++++++++++++++---- dao/resolve_record.go | 2 +- main.go | 2 +- 8 files changed, 193 insertions(+), 13 deletions(-) create mode 100644 PodCurlName.md create mode 100644 common/set.go rename core/{handler.go => dns_handler.go} (71%) diff --git a/PodCurlName.md b/PodCurlName.md new file mode 100644 index 0000000..80299b5 --- /dev/null +++ b/PodCurlName.md @@ -0,0 +1,10 @@ +curl www.odboy.cn + +{"www.odboy.cn.springboot-standard-demo.svc.cluster.local", "A", 2} +{"www.odboy.cn.springboot-standard-demo.svc.cluster.local", "AAAA", 2} +{"www.odboy.cn.cluster.local", "A", 2} +{"www.odboy.cn.cluster.local", "AAAA", 2} +{"www.odboy.cn.io.local", "A", 2} +{"www.odboy.cn.io.local", "AAAA", 2} +{"www.odboy.cn", "A", 2} +{"www.odboy.cn", "AAAA", 2} diff --git a/README.md b/README.md index 6e0ae8c..48a2ece 100644 --- a/README.md +++ b/README.md @@ -131,6 +131,41 @@ DNS服务所在的ip地址为 192.168.43.130 ![rollback1](https://oss.odboy.cn/blog/files/onlinedoc/kenaito-dns/rollback_func.png) ![rollback2](https://oss.odboy.cn/blog/files/onlinedoc/kenaito-dns/rollback_func2.png) +## k8s集群中使用 + +```shell +# 使用的是CoreDNS,并且配置上游DNS服务器 +kubectl edit configmap coredns -n kube-system +# --------------------------------------------------- +apiVersion: v1 +data: + Corefile: | + .:53 { + errors + health + lameduck 5s + ready + kubernetes cluster.local in-addr.arpa ip6.arpa { + pods insecure + upstream 192.168.1.103 + fallthrough in-addr.arpa ip6.arpa cluster.local io.local + ttl 30 + } + prometheus :9153 + cache 30 + loop + reload + loadbalance + } +kind: ConfigMap +# --------------------------------------------------- + +# 逐个重启 coredns pod +kubectl get pod -A|grep coredns|awk '{print $2}'|xargs -I{} kubectl delete pod {} -n kube-system + +# 进入容器验证 +``` + ## 常见问题 #### nslookup 命令不存在解决 diff --git a/cache/resolve_record.go b/cache/resolve_record.go index d4fa9c5..e8c3b29 100644 --- a/cache/resolve_record.go +++ b/cache/resolve_record.go @@ -1,7 +1,13 @@ package cache +/* + * @Description 缓存 + * @Author www.odboy.cn + * @Date 20241107 + */ import ( "fmt" + "kenaito-dns/common" "kenaito-dns/config" "kenaito-dns/dao" "sync" @@ -10,11 +16,13 @@ import ( var KeyResolveRecordMap sync.Map var IdResolveRecordMap sync.Map +var NameSet *common.Set func ReloadCache() { fmt.Println("[app] [info] " + time.Now().Format(config.AppTimeFormat) + " [Cache] Reload cache start") KeyResolveRecordMap.Range(cleanKeyCache) IdResolveRecordMap.Range(cleanIdCache) + NameSet = common.NewSet() resolveRecords := dao.FindResolveRecordByVersion(dao.GetResolveVersion(), false) for _, record := range resolveRecords { // id -> resolveRecord @@ -31,6 +39,7 @@ func ReloadCache() { records = append(newRecords, record) KeyResolveRecordMap.Store(cacheKey, records) } + NameSet.Add(record.Name) } fmt.Println("[app] [info] " + time.Now().Format(config.AppTimeFormat) + " [Cache] Reload cache end") } diff --git a/common/set.go b/common/set.go new file mode 100644 index 0000000..0468f9f --- /dev/null +++ b/common/set.go @@ -0,0 +1,53 @@ +package common + +/* + * @Description 自定义Set结构 + * @Author www.odboy.cn + * @Date 20241112 + */ +import ( + "fmt" + "strings" +) + +type Set struct { + m map[string]struct{} +} + +func NewSet() *Set { + return &Set{m: make(map[string]struct{})} +} + +func (s *Set) Add(val string) { + s.m[val] = struct{}{} +} + +func (s *Set) Remove(val string) { + delete(s.m, val) +} + +func (s *Set) Contains(val string) bool { + _, exists := s.m[val] + return exists +} + +func (s *Set) Size() int { + return len(s.m) +} + +func (s *Set) GetSimilarityValue(text string) string { + for key := range s.m { + if strings.HasPrefix(text, key+".") { + return key + } + } + return "" +} + +func main() { + set := NewSet() + set.Add("bad") + set.Add("man") + fmt.Println(set.Contains("man")) // 输出: true + fmt.Println(set.Size()) // 输出: 2 +} diff --git a/config/dns_server.go b/config/dns_server.go index f71ea0a..17ec5b3 100644 --- a/config/dns_server.go +++ b/config/dns_server.go @@ -6,5 +6,6 @@ package config * @Date 20241108 */ const ( - DnsServerPort = ":53" + DNSServerPort = ":53" + ForwardDNServer = "8.8.8.8:53" // Google的公共DNS服务器 ) diff --git a/core/handler.go b/core/dns_handler.go similarity index 71% rename from core/handler.go rename to core/dns_handler.go index e94bfab..78ed125 100644 --- a/core/handler.go +++ b/core/dns_handler.go @@ -27,19 +27,34 @@ func HandleDNSRequest(w dns.ResponseWriter, r *dns.Msg) { for _, question := range r.Question { switch question.Qtype { case dns.TypeA: - handleARecord(question, msg) + isFound := handleARecord(question, msg) + if !isFound { + forwardGlobalServer(question.Name, dns.TypeA, msg) + } break case dns.TypeAAAA: - handleAAAARecord(question, msg) + isFound := handleAAAARecord(question, msg) + if !isFound { + forwardGlobalServer(question.Name, dns.TypeAAAA, msg) + } break case dns.TypeCNAME: - handleCNAMERecord(question, msg) + isFound := handleCNAMERecord(question, msg) + if !isFound { + forwardGlobalServer(question.Name, dns.TypeCNAME, msg) + } break case dns.TypeMX: - handleMXRecord(question, msg) + isFound := handleMXRecord(question, msg) + if !isFound { + forwardGlobalServer(question.Name, dns.TypeMX, msg) + } break case dns.TypeTXT: - handleTXTRecord(question, msg) + isFound := handleTXTRecord(question, msg) + if !isFound { + forwardGlobalServer(question.Name, dns.TypeTXT, msg) + } break } } @@ -50,8 +65,43 @@ func HandleDNSRequest(w dns.ResponseWriter, r *dns.Msg) { } } +// 发送DNS请求到公共DNS服务器 +func forwardGlobalServer(name string, rrType uint16, msg *dns.Msg) { + m := new(dns.Msg) + m.Authoritative = true + m.RecursionAvailable = true + m.SetQuestion(name, rrType) + c := new(dns.Client) + r, _, err := c.Exchange(m, config.ForwardDNServer) + if err != nil { + fmt.Printf("[dns] [error] "+time.Now().Format(config.AppTimeFormat)+" [DNS] Lookup Failed: %s\n", err.Error()) + } + if r.Rcode != dns.RcodeSuccess { + fmt.Printf("[dns] [error] " + time.Now().Format(config.AppTimeFormat) + " [DNS] Lookup Failed \n") + } + for _, record := range r.Answer { + switch r := record.(type) { + case *dns.A: + msg.Answer = append(msg.Answer, r) + break + case *dns.AAAA: + msg.Answer = append(msg.Answer, r) + break + case *dns.MX: + msg.Answer = append(msg.Answer, r) + break + case *dns.TXT: + msg.Answer = append(msg.Answer, r) + break + case *dns.CNAME: + msg.Answer = append(msg.Answer, r) + break + } + } +} + // 构建 A 记录 IPV4 -func handleARecord(q dns.Question, msg *dns.Msg) { +func handleARecord(q dns.Question, msg *dns.Msg) bool { name := q.Name queryName := name[0 : len(name)-1] var records []dao.ResolveRecord @@ -62,7 +112,13 @@ func handleARecord(q dns.Question, msg *dns.Msg) { records = value.([]dao.ResolveRecord) fmt.Println("[app] [info] " + time.Now().Format(config.AppTimeFormat) + " [Cache] Query cache end") } else { + //// 支持pod内置域名解析 + //similarityValue := cache.NameSet.GetSimilarityValue(queryName) + //if similarityValue != "" { + // records = dao.FindResolveRecordByNameType(similarityValue, constant.R_A) + //} else { records = dao.FindResolveRecordByNameType(queryName, constant.R_A) + //} } if len(records) > 0 { for _, record := range records { @@ -79,11 +135,13 @@ func handleARecord(q dns.Question, msg *dns.Msg) { } msg.Answer = append(msg.Answer, rr) } + return true } + return false } // 构建 AAAA 记录 IPV6 -func handleAAAARecord(q dns.Question, msg *dns.Msg) { +func handleAAAARecord(q dns.Question, msg *dns.Msg) bool { name := q.Name queryName := name[0 : len(name)-1] var records []dao.ResolveRecord @@ -94,7 +152,13 @@ func handleAAAARecord(q dns.Question, msg *dns.Msg) { records = value.([]dao.ResolveRecord) fmt.Println("[app] [info] " + time.Now().Format(config.AppTimeFormat) + " [Cache] Query cache end") } else { + //// 支持pod内置域名解析 + //similarityValue := cache.NameSet.GetSimilarityValue(queryName) + //if similarityValue != "" { + // records = dao.FindResolveRecordByNameType(similarityValue, constant.R_AAAA) + //} else { records = dao.FindResolveRecordByNameType(queryName, constant.R_AAAA) + //} } if len(records) > 0 { for _, record := range records { @@ -111,11 +175,13 @@ func handleAAAARecord(q dns.Question, msg *dns.Msg) { } msg.Answer = append(msg.Answer, rr) } + return true } + return false } // 构建 CNAME 记录 -func handleCNAMERecord(q dns.Question, msg *dns.Msg) { +func handleCNAMERecord(q dns.Question, msg *dns.Msg) bool { name := q.Name queryName := name[0 : len(name)-1] var records []dao.ResolveRecord @@ -142,11 +208,13 @@ func handleCNAMERecord(q dns.Question, msg *dns.Msg) { } msg.Answer = append(msg.Answer, rr) } + return true } + return false } // 构建 MX 记录 -func handleMXRecord(q dns.Question, msg *dns.Msg) { +func handleMXRecord(q dns.Question, msg *dns.Msg) bool { name := q.Name queryName := name[0 : len(name)-1] var records []dao.ResolveRecord @@ -174,11 +242,13 @@ func handleMXRecord(q dns.Question, msg *dns.Msg) { } msg.Answer = append(msg.Answer, rr) } + return true } + return false } // 构建 TXT 记录 -func handleTXTRecord(q dns.Question, msg *dns.Msg) { +func handleTXTRecord(q dns.Question, msg *dns.Msg) bool { name := q.Name queryName := name[0 : len(name)-1] var records []dao.ResolveRecord @@ -205,5 +275,7 @@ func handleTXTRecord(q dns.Question, msg *dns.Msg) { } msg.Answer = append(msg.Answer, rr) } + return true } + return false } diff --git a/dao/resolve_record.go b/dao/resolve_record.go index f20285e..a98749b 100644 --- a/dao/resolve_record.go +++ b/dao/resolve_record.go @@ -71,7 +71,7 @@ func FindResolveRecordByVersion(version int, isAll bool) []ResolveRecord { func FindResolveRecordByNameType(name string, recordType string) []ResolveRecord { var records []ResolveRecord - err := Engine.Table("resolve_record").Where("`name` = ? and `record_type` = ? and `version` = ?", name, recordType, GetResolveVersion()).Find(&records) + err := Engine.Table("resolve_record").Where("`name` = ? and `record_type` = ? and `version` = ? and `enabled` = ?", name, recordType, GetResolveVersion(), 1).Find(&records) if err != nil { fmt.Println(err) } diff --git a/main.go b/main.go index 32239d7..84fffc2 100644 --- a/main.go +++ b/main.go @@ -28,7 +28,7 @@ func initDNSServer() { // 注册 DNS 请求处理函数 dns.HandleFunc(".", core.HandleDNSRequest) // 设置服务器地址和协议 - server := &dns.Server{Addr: config.DnsServerPort, Net: "udp"} + server := &dns.Server{Addr: config.DNSServerPort, Net: "udp"} // 开始监听 fmt.Printf("[dns] [info] "+time.Now().Format(config.AppTimeFormat)+" Starting DNS server on %s\n", server.Addr) if err := server.ListenAndServe(); err != nil {