fix: more bug fix

This commit is contained in:
骑着蜗牛追导弹 2024-11-12 20:34:02 +08:00
parent 0dfd04005d
commit c0208cb947
8 changed files with 193 additions and 13 deletions

10
PodCurlName.md Normal file
View File

@ -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}

View File

@ -131,6 +131,41 @@ DNS服务所在的ip地址为 192.168.43.130
![rollback1](https://oss.odboy.cn/blog/files/onlinedoc/kenaito-dns/rollback_func.png) ![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) ![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 命令不存在解决 #### nslookup 命令不存在解决

View File

@ -1,7 +1,13 @@
package cache package cache
/*
* @Description 缓存
* @Author www.odboy.cn
* @Date 20241107
*/
import ( import (
"fmt" "fmt"
"kenaito-dns/common"
"kenaito-dns/config" "kenaito-dns/config"
"kenaito-dns/dao" "kenaito-dns/dao"
"sync" "sync"
@ -10,11 +16,13 @@ import (
var KeyResolveRecordMap sync.Map var KeyResolveRecordMap sync.Map
var IdResolveRecordMap sync.Map var IdResolveRecordMap sync.Map
var NameSet *common.Set
func ReloadCache() { func ReloadCache() {
fmt.Println("[app] [info] " + time.Now().Format(config.AppTimeFormat) + " [Cache] Reload cache start") fmt.Println("[app] [info] " + time.Now().Format(config.AppTimeFormat) + " [Cache] Reload cache start")
KeyResolveRecordMap.Range(cleanKeyCache) KeyResolveRecordMap.Range(cleanKeyCache)
IdResolveRecordMap.Range(cleanIdCache) IdResolveRecordMap.Range(cleanIdCache)
NameSet = common.NewSet()
resolveRecords := dao.FindResolveRecordByVersion(dao.GetResolveVersion(), false) resolveRecords := dao.FindResolveRecordByVersion(dao.GetResolveVersion(), false)
for _, record := range resolveRecords { for _, record := range resolveRecords {
// id -> resolveRecord // id -> resolveRecord
@ -31,6 +39,7 @@ func ReloadCache() {
records = append(newRecords, record) records = append(newRecords, record)
KeyResolveRecordMap.Store(cacheKey, records) KeyResolveRecordMap.Store(cacheKey, records)
} }
NameSet.Add(record.Name)
} }
fmt.Println("[app] [info] " + time.Now().Format(config.AppTimeFormat) + " [Cache] Reload cache end") fmt.Println("[app] [info] " + time.Now().Format(config.AppTimeFormat) + " [Cache] Reload cache end")
} }

53
common/set.go Normal file
View File

@ -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
}

View File

@ -6,5 +6,6 @@ package config
* @Date 20241108 * @Date 20241108
*/ */
const ( const (
DnsServerPort = ":53" DNSServerPort = ":53"
ForwardDNServer = "8.8.8.8:53" // Google的公共DNS服务器
) )

View File

@ -27,19 +27,34 @@ func HandleDNSRequest(w dns.ResponseWriter, r *dns.Msg) {
for _, question := range r.Question { for _, question := range r.Question {
switch question.Qtype { switch question.Qtype {
case dns.TypeA: case dns.TypeA:
handleARecord(question, msg) isFound := handleARecord(question, msg)
if !isFound {
forwardGlobalServer(question.Name, dns.TypeA, msg)
}
break break
case dns.TypeAAAA: case dns.TypeAAAA:
handleAAAARecord(question, msg) isFound := handleAAAARecord(question, msg)
if !isFound {
forwardGlobalServer(question.Name, dns.TypeAAAA, msg)
}
break break
case dns.TypeCNAME: case dns.TypeCNAME:
handleCNAMERecord(question, msg) isFound := handleCNAMERecord(question, msg)
if !isFound {
forwardGlobalServer(question.Name, dns.TypeCNAME, msg)
}
break break
case dns.TypeMX: case dns.TypeMX:
handleMXRecord(question, msg) isFound := handleMXRecord(question, msg)
if !isFound {
forwardGlobalServer(question.Name, dns.TypeMX, msg)
}
break break
case dns.TypeTXT: case dns.TypeTXT:
handleTXTRecord(question, msg) isFound := handleTXTRecord(question, msg)
if !isFound {
forwardGlobalServer(question.Name, dns.TypeTXT, msg)
}
break 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 // 构建 A 记录 IPV4
func handleARecord(q dns.Question, msg *dns.Msg) { func handleARecord(q dns.Question, msg *dns.Msg) bool {
name := q.Name name := q.Name
queryName := name[0 : len(name)-1] queryName := name[0 : len(name)-1]
var records []dao.ResolveRecord var records []dao.ResolveRecord
@ -62,7 +112,13 @@ func handleARecord(q dns.Question, msg *dns.Msg) {
records = value.([]dao.ResolveRecord) records = value.([]dao.ResolveRecord)
fmt.Println("[app] [info] " + time.Now().Format(config.AppTimeFormat) + " [Cache] Query cache end") fmt.Println("[app] [info] " + time.Now().Format(config.AppTimeFormat) + " [Cache] Query cache end")
} else { } else {
//// 支持pod内置域名解析
//similarityValue := cache.NameSet.GetSimilarityValue(queryName)
//if similarityValue != "" {
// records = dao.FindResolveRecordByNameType(similarityValue, constant.R_A)
//} else {
records = dao.FindResolveRecordByNameType(queryName, constant.R_A) records = dao.FindResolveRecordByNameType(queryName, constant.R_A)
//}
} }
if len(records) > 0 { if len(records) > 0 {
for _, record := range records { for _, record := range records {
@ -79,11 +135,13 @@ func handleARecord(q dns.Question, msg *dns.Msg) {
} }
msg.Answer = append(msg.Answer, rr) msg.Answer = append(msg.Answer, rr)
} }
return true
} }
return false
} }
// 构建 AAAA 记录 IPV6 // 构建 AAAA 记录 IPV6
func handleAAAARecord(q dns.Question, msg *dns.Msg) { func handleAAAARecord(q dns.Question, msg *dns.Msg) bool {
name := q.Name name := q.Name
queryName := name[0 : len(name)-1] queryName := name[0 : len(name)-1]
var records []dao.ResolveRecord var records []dao.ResolveRecord
@ -94,7 +152,13 @@ func handleAAAARecord(q dns.Question, msg *dns.Msg) {
records = value.([]dao.ResolveRecord) records = value.([]dao.ResolveRecord)
fmt.Println("[app] [info] " + time.Now().Format(config.AppTimeFormat) + " [Cache] Query cache end") fmt.Println("[app] [info] " + time.Now().Format(config.AppTimeFormat) + " [Cache] Query cache end")
} else { } else {
//// 支持pod内置域名解析
//similarityValue := cache.NameSet.GetSimilarityValue(queryName)
//if similarityValue != "" {
// records = dao.FindResolveRecordByNameType(similarityValue, constant.R_AAAA)
//} else {
records = dao.FindResolveRecordByNameType(queryName, constant.R_AAAA) records = dao.FindResolveRecordByNameType(queryName, constant.R_AAAA)
//}
} }
if len(records) > 0 { if len(records) > 0 {
for _, record := range records { for _, record := range records {
@ -111,11 +175,13 @@ func handleAAAARecord(q dns.Question, msg *dns.Msg) {
} }
msg.Answer = append(msg.Answer, rr) msg.Answer = append(msg.Answer, rr)
} }
return true
} }
return false
} }
// 构建 CNAME 记录 // 构建 CNAME 记录
func handleCNAMERecord(q dns.Question, msg *dns.Msg) { func handleCNAMERecord(q dns.Question, msg *dns.Msg) bool {
name := q.Name name := q.Name
queryName := name[0 : len(name)-1] queryName := name[0 : len(name)-1]
var records []dao.ResolveRecord var records []dao.ResolveRecord
@ -142,11 +208,13 @@ func handleCNAMERecord(q dns.Question, msg *dns.Msg) {
} }
msg.Answer = append(msg.Answer, rr) msg.Answer = append(msg.Answer, rr)
} }
return true
} }
return false
} }
// 构建 MX 记录 // 构建 MX 记录
func handleMXRecord(q dns.Question, msg *dns.Msg) { func handleMXRecord(q dns.Question, msg *dns.Msg) bool {
name := q.Name name := q.Name
queryName := name[0 : len(name)-1] queryName := name[0 : len(name)-1]
var records []dao.ResolveRecord var records []dao.ResolveRecord
@ -174,11 +242,13 @@ func handleMXRecord(q dns.Question, msg *dns.Msg) {
} }
msg.Answer = append(msg.Answer, rr) msg.Answer = append(msg.Answer, rr)
} }
return true
} }
return false
} }
// 构建 TXT 记录 // 构建 TXT 记录
func handleTXTRecord(q dns.Question, msg *dns.Msg) { func handleTXTRecord(q dns.Question, msg *dns.Msg) bool {
name := q.Name name := q.Name
queryName := name[0 : len(name)-1] queryName := name[0 : len(name)-1]
var records []dao.ResolveRecord var records []dao.ResolveRecord
@ -205,5 +275,7 @@ func handleTXTRecord(q dns.Question, msg *dns.Msg) {
} }
msg.Answer = append(msg.Answer, rr) msg.Answer = append(msg.Answer, rr)
} }
return true
} }
return false
} }

View File

@ -71,7 +71,7 @@ func FindResolveRecordByVersion(version int, isAll bool) []ResolveRecord {
func FindResolveRecordByNameType(name string, recordType string) []ResolveRecord { func FindResolveRecordByNameType(name string, recordType string) []ResolveRecord {
var records []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 { if err != nil {
fmt.Println(err) fmt.Println(err)
} }

View File

@ -28,7 +28,7 @@ func initDNSServer() {
// 注册 DNS 请求处理函数 // 注册 DNS 请求处理函数
dns.HandleFunc(".", core.HandleDNSRequest) 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) fmt.Printf("[dns] [info] "+time.Now().Format(config.AppTimeFormat)+" Starting DNS server on %s\n", server.Addr)
if err := server.ListenAndServe(); err != nil { if err := server.ListenAndServe(); err != nil {