fix: more bug fix
This commit is contained in:
parent
0dfd04005d
commit
c0208cb947
|
@ -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}
|
35
README.md
35
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)
|
![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 命令不存在解决
|
||||||
|
|
|
@ -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")
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
|
@ -6,5 +6,6 @@ package config
|
||||||
* @Date 20241108
|
* @Date 20241108
|
||||||
*/
|
*/
|
||||||
const (
|
const (
|
||||||
DnsServerPort = ":53"
|
DNSServerPort = ":53"
|
||||||
|
ForwardDNServer = "8.8.8.8:53" // Google的公共DNS服务器
|
||||||
)
|
)
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
2
main.go
2
main.go
|
@ -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 {
|
||||||
|
|
Loading…
Reference in New Issue