mirror of
https://github.com/kubenetworks/kubevpn.git
synced 2025-10-05 15:26:57 +08:00
feat: retry dns query
This commit is contained in:
@@ -12,7 +12,7 @@ import (
|
||||
)
|
||||
|
||||
// systemd-resolve --status, systemd-resolve --flush-caches
|
||||
func SetupDNS(config *miekgdns.ClientConfig) error {
|
||||
func SetupDNS(config *miekgdns.ClientConfig, _ []string) error {
|
||||
tunName := os.Getenv("tunName")
|
||||
if len(tunName) == 0 {
|
||||
tunName = "tun0"
|
||||
|
@@ -2,52 +2,72 @@ package dns
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
miekgdns "github.com/miekg/dns"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"k8s.io/apimachinery/pkg/util/cache"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
)
|
||||
|
||||
type server struct {
|
||||
// todo using cache to speed up dns resolve process
|
||||
dnsCache *cache.LRUExpireCache
|
||||
forwardDNS *miekgdns.ClientConfig
|
||||
c *miekgdns.Client
|
||||
}
|
||||
|
||||
func NewDNSServer(network, address string, forwardDNS *miekgdns.ClientConfig) error {
|
||||
return miekgdns.ListenAndServe(address, network, &server{
|
||||
dnsCache: cache.NewLRUExpireCache(1000),
|
||||
forwardDNS: forwardDNS,
|
||||
c: &miekgdns.Client{Net: "udp" /*, SingleInflight: true*/},
|
||||
})
|
||||
}
|
||||
|
||||
// ServeDNS consider using a cache
|
||||
func (s *server) ServeDNS(w miekgdns.ResponseWriter, r *miekgdns.Msg) {
|
||||
//defer w.Close()
|
||||
ctx, cancelFunc := context.WithTimeout(context.Background(), time.Second*3)
|
||||
if len(r.Question) == 0 {
|
||||
r.Response = true
|
||||
_ = w.WriteMsg(r)
|
||||
return
|
||||
}
|
||||
|
||||
get, b := s.dnsCache.Get(r.Question[0].Name)
|
||||
if b {
|
||||
r.Response = true
|
||||
r.Answer = get.([]miekgdns.RR)
|
||||
_ = w.WriteMsg(r)
|
||||
return
|
||||
}
|
||||
|
||||
ctx, cancelFunc := context.WithTimeout(context.Background(), time.Second*5)
|
||||
defer cancelFunc()
|
||||
|
||||
for _, dnsAddr := range s.forwardDNS.Servers {
|
||||
var msg = new(miekgdns.Msg)
|
||||
*msg = *r
|
||||
go func(r miekgdns.Msg, dnsAddr string) {
|
||||
var ok = &atomic.Value{}
|
||||
ok.Store(false)
|
||||
var q = r.Question[0]
|
||||
var originName = q.Name
|
||||
q.Name = fix(originName, s.forwardDNS.Search[0])
|
||||
for _, dnsAddr := range s.forwardDNS.Servers {
|
||||
for _, name := range fix(originName, s.forwardDNS.Search) {
|
||||
go func(name, dnsAddr string) {
|
||||
var msg = new(miekgdns.Msg)
|
||||
*msg = *r
|
||||
q.Name = name
|
||||
r.Question = []miekgdns.Question{q}
|
||||
answer, err := miekgdns.Exchange(&r, dnsAddr+":53")
|
||||
answer, _, err := s.c.ExchangeContext(ctx, msg, fmt.Sprintf("%s:%s", dnsAddr, s.forwardDNS.Port))
|
||||
if err == nil && len(answer.Answer) != 0 {
|
||||
if len(answer.Answer) != 0 {
|
||||
answer.Answer[0].Header().Name = originName
|
||||
for i := 0; i < len(answer.Answer); i++ {
|
||||
answer.Answer[i].Header().Name = originName
|
||||
}
|
||||
//answer.Answer[0].Header().Name = originName
|
||||
if len(answer.Question) != 0 {
|
||||
answer.Question[0].Name = originName
|
||||
}
|
||||
if ctx.Err() == nil {
|
||||
defer cancelFunc()
|
||||
ok.Store(true)
|
||||
err = w.WriteMsg(answer)
|
||||
if err != nil {
|
||||
log.Debugf(err.Error())
|
||||
@@ -58,19 +78,22 @@ func (s *server) ServeDNS(w miekgdns.ResponseWriter, r *miekgdns.Msg) {
|
||||
if err != nil {
|
||||
log.Debugf(err.Error())
|
||||
}
|
||||
}(*msg, dnsAddr)
|
||||
}(name, dnsAddr)
|
||||
}
|
||||
}
|
||||
<-ctx.Done()
|
||||
if ctx.Err() != context.Canceled {
|
||||
if !ok.Load().(bool) {
|
||||
r.Response = true
|
||||
_ = w.WriteMsg(r)
|
||||
} else {
|
||||
s.dnsCache.Add(r.Question[0].Name, r.Answer, time.Second*1)
|
||||
}
|
||||
}
|
||||
|
||||
func fix(domain, suffix string) string {
|
||||
namespace := strings.Split(suffix, ".")[0]
|
||||
if sets.NewString(strings.Split(domain, ".")...).Has(namespace) {
|
||||
domain = domain[0:strings.LastIndex(domain, namespace)]
|
||||
func fix(domain string, suffix []string) (result []string) {
|
||||
result = []string{domain}
|
||||
for _, s := range suffix {
|
||||
result = append(result, strings.TrimSuffix(domain, ".")+"."+s+".")
|
||||
}
|
||||
return strings.TrimSuffix(domain, ".") + "." + suffix + "."
|
||||
return
|
||||
}
|
||||
|
@@ -2,7 +2,7 @@ package dns
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
miekgdns "github.com/miekg/dns"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"io/fs"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
@@ -11,6 +11,8 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
miekgdns "github.com/miekg/dns"
|
||||
|
||||
"github.com/wencaiwulue/kubevpn/pkg/util"
|
||||
)
|
||||
|
||||
@@ -22,12 +24,7 @@ func TestSetupDnsServer(t *testing.T) {
|
||||
Port: "53",
|
||||
Ndots: 0,
|
||||
}
|
||||
go func() {
|
||||
err := NewDNSServer("udp", "127.0.0.1:"+strconv.Itoa(port), clientConfig)
|
||||
if err != nil {
|
||||
t.FailNow()
|
||||
}
|
||||
}()
|
||||
go func() { log.Fatal(NewDNSServer("udp", "127.0.0.1:"+strconv.Itoa(port), clientConfig)) }()
|
||||
config := miekgdns.ClientConfig{
|
||||
Servers: []string{"127.0.0.1"},
|
||||
Search: clientConfig.Search,
|
||||
@@ -73,68 +70,3 @@ func TestFull(t *testing.T) {
|
||||
|
||||
fmt.Println(p2.Question)
|
||||
}
|
||||
|
||||
func TestName(t *testing.T) {
|
||||
type name struct {
|
||||
input string
|
||||
output string
|
||||
}
|
||||
var data = []name{
|
||||
{
|
||||
input: "ry-server",
|
||||
output: "ry-server.vke-system.svc.cluster.local",
|
||||
},
|
||||
{
|
||||
input: "ry-server.",
|
||||
output: "ry-server.vke-system.svc.cluster.local",
|
||||
},
|
||||
{
|
||||
input: "ry-server.vke-system",
|
||||
output: "ry-server.vke-system.svc.cluster.local",
|
||||
}, {
|
||||
input: "ry-server.vke-system.",
|
||||
output: "ry-server.vke-system.svc.cluster.local",
|
||||
},
|
||||
{
|
||||
input: "ry-server.vke-system.svc",
|
||||
output: "ry-server.vke-system.svc.cluster.local",
|
||||
},
|
||||
{
|
||||
input: "ry-server.vke-system.svc.",
|
||||
output: "ry-server.vke-system.svc.cluster.local",
|
||||
},
|
||||
{
|
||||
input: "ry-server.vke-system.svc.cluster",
|
||||
output: "ry-server.vke-system.svc.cluster.local",
|
||||
},
|
||||
{
|
||||
input: "mongodb-1.mongodb-headless",
|
||||
output: "mongodb-1.mongodb-headless.vke-system.svc.cluster.local",
|
||||
}, {
|
||||
input: "mongodb-1.mongodb-headless.",
|
||||
output: "mongodb-1.mongodb-headless.vke-system.svc.cluster.local",
|
||||
},
|
||||
{
|
||||
input: "mongodb-1.mongodb-headless.vke-system",
|
||||
output: "mongodb-1.mongodb-headless.vke-system.svc.cluster.local",
|
||||
},
|
||||
{
|
||||
input: "mongodb-1.mongodb-headless.vke-system.",
|
||||
output: "mongodb-1.mongodb-headless.vke-system.svc.cluster.local",
|
||||
},
|
||||
{
|
||||
input: "mongodb-1.mongodb-headless.vke-system.svc",
|
||||
output: "mongodb-1.mongodb-headless.vke-system.svc.cluster.local",
|
||||
},
|
||||
{
|
||||
input: "mongodb-1.mongodb-headless.vke-system.svc.cluster",
|
||||
output: "mongodb-1.mongodb-headless.vke-system.svc.cluster.local",
|
||||
},
|
||||
}
|
||||
for _, datum := range data {
|
||||
if o := fix(datum.input, "vke-system.svc.cluster.local"); o != datum.output {
|
||||
t.Logf("output: %s, expected: %s", o, datum.output)
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -32,15 +32,15 @@ var resolv = "/etc/resolv.conf"
|
||||
// service.namespace.svc:port
|
||||
// service.namespace.svc.cluster:port
|
||||
// service.namespace.svc.cluster.local:port
|
||||
func SetupDNS(config *miekgdns.ClientConfig) error {
|
||||
usingResolver(config)
|
||||
func SetupDNS(config *miekgdns.ClientConfig, ns []string) error {
|
||||
usingResolver(config, ns)
|
||||
_ = exec.Command("killall", "mDNSResponderHelper").Run()
|
||||
_ = exec.Command("killall", "-HUP", "mDNSResponder").Run()
|
||||
_ = exec.Command("dscacheutil", "-flushcache").Run()
|
||||
return nil
|
||||
}
|
||||
|
||||
func usingResolver(clientConfig *miekgdns.ClientConfig) {
|
||||
func usingResolver(clientConfig *miekgdns.ClientConfig, ns []string) {
|
||||
var err error
|
||||
_ = os.RemoveAll(filepath.Join("/", "etc", "resolver"))
|
||||
if err = os.MkdirAll(filepath.Join("/", "etc", "resolver"), fs.ModePerm); err != nil {
|
||||
@@ -70,7 +70,7 @@ func usingResolver(clientConfig *miekgdns.ClientConfig) {
|
||||
Ndots: clientConfig.Ndots,
|
||||
Timeout: 1,
|
||||
}
|
||||
for _, s := range strings.Split(clientConfig.Search[0], ".") {
|
||||
for _, s := range sets.NewString(strings.Split(clientConfig.Search[0], ".")...).Insert(ns...).List() {
|
||||
filename = filepath.Join("/", "etc", "resolver", s)
|
||||
_ = ioutil.WriteFile(filename, []byte(toString(config)), 0644)
|
||||
}
|
||||
|
@@ -17,7 +17,7 @@ import (
|
||||
"golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
|
||||
)
|
||||
|
||||
func SetupDNS(config *miekgdns.ClientConfig) error {
|
||||
func SetupDNS(config *miekgdns.ClientConfig, _ []string) error {
|
||||
getenv := os.Getenv("luid")
|
||||
parseUint, err := strconv.ParseUint(getenv, 10, 64)
|
||||
if err != nil {
|
||||
|
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
@@ -289,6 +290,7 @@ func (c *ConnectOptions) detectConflictDevice() {
|
||||
}
|
||||
|
||||
func (c *ConnectOptions) setupDNS() {
|
||||
const port = 53
|
||||
pod, err := c.GetRunningPodList()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
@@ -297,7 +299,23 @@ func (c *ConnectOptions) setupDNS() {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if err = dns.SetupDNS(relovConf); err != nil {
|
||||
if relovConf.Port == "" {
|
||||
relovConf.Port = strconv.Itoa(port)
|
||||
}
|
||||
ns := sets.NewString()
|
||||
list, err := c.clientset.CoreV1().Namespaces().List(ctx, metav1.ListOptions{})
|
||||
if err == nil {
|
||||
for _, item := range list.Items {
|
||||
ns.Insert(item.Name)
|
||||
}
|
||||
}
|
||||
svc, err := c.clientset.CoreV1().Services(c.Namespace).List(ctx, metav1.ListOptions{})
|
||||
if err == nil {
|
||||
for _, item := range svc.Items {
|
||||
ns.Insert(item.Name)
|
||||
}
|
||||
}
|
||||
if err = dns.SetupDNS(relovConf, ns.List()); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user