feat: dns server add rate limit

This commit is contained in:
fengcaiwen
2023-04-10 14:56:31 +08:00
parent 71ed7e6bdb
commit f2de9a8b1d
2 changed files with 32 additions and 10 deletions

4
go.mod
View File

@@ -49,7 +49,9 @@ require (
golang.org/x/crypto v0.2.0
golang.org/x/exp v0.0.0-20230113213754-f9f960f08ad4
golang.org/x/oauth2 v0.6.0
golang.org/x/sync v0.1.0
golang.org/x/text v0.8.0
golang.org/x/time v0.3.0
golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224
k8s.io/utils v0.0.0-20230313181309-38a27ef9d749
sigs.k8s.io/controller-runtime v0.14.5
@@ -132,9 +134,7 @@ require (
github.com/xlab/treeprint v1.1.0 // indirect
go.starlark.net v0.0.0-20230112144946-fae38c8a6d89 // indirect
golang.org/x/mod v0.8.0 // indirect
golang.org/x/sync v0.1.0 // indirect
golang.org/x/term v0.6.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/tools v0.6.0 // indirect
google.golang.org/genproto v0.0.0-20230113154510-dbe35b8444a5 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect

View File

@@ -5,6 +5,8 @@ import (
"encoding/json"
"errors"
"fmt"
"math"
"math/rand"
"os"
"strings"
"sync"
@@ -13,24 +15,38 @@ import (
miekgdns "github.com/miekg/dns"
log "github.com/sirupsen/logrus"
"golang.org/x/sync/semaphore"
"golang.org/x/time/rate"
"k8s.io/apimachinery/pkg/util/cache"
)
var (
maxConcurrent int64 = 1024
logInterval = 2 * time.Second
)
// github.com/docker/docker@v23.0.1+incompatible/libnetwork/network_windows.go:53
type server struct {
dnsCache *cache.LRUExpireCache
forwardDNS *miekgdns.ClientConfig
client *miekgdns.Client
fwdSem *semaphore.Weighted // Limit the number of concurrent external DNS requests in-flight
logInverval rate.Sometimes // Rate-limit logging about hitting the fwdSem limit
}
func NewDNSServer(network, address string, forwardDNS *miekgdns.ClientConfig) error {
return miekgdns.ListenAndServe(address, network, &server{
dnsCache: cache.NewLRUExpireCache(1000),
forwardDNS: forwardDNS,
client: &miekgdns.Client{Net: "udp", SingleInflight: true, Timeout: time.Second * 30},
dnsCache: cache.NewLRUExpireCache(1000),
forwardDNS: forwardDNS,
client: &miekgdns.Client{Net: "udp", SingleInflight: true, Timeout: time.Second * 30},
fwdSem: semaphore.NewWeighted(maxConcurrent),
logInverval: rate.Sometimes{Interval: logInterval},
})
}
// ServeDNS consider using a cache
// eg: nslookup -port=56571 code.byted.org 127.0.0.1
func (s *server) ServeDNS(w miekgdns.ResponseWriter, r *miekgdns.Msg) {
defer w.Close()
if len(r.Question) == 0 {
@@ -41,6 +57,16 @@ func (s *server) ServeDNS(w miekgdns.ResponseWriter, r *miekgdns.Msg) {
ctx, cancelFunc := context.WithTimeout(context.Background(), time.Second*5)
defer cancelFunc()
// limits the number of outstanding concurrent queries
err := s.fwdSem.Acquire(ctx, 1)
if err != nil {
s.logInverval.Do(func() {
log.Errorf("dns-server more than %v concurrent queries", maxConcurrent)
})
r.SetRcode(r, miekgdns.RcodeRefused)
return
}
defer s.fwdSem.Release(1)
var wg = &sync.WaitGroup{}
@@ -72,14 +98,10 @@ func (s *server) ServeDNS(w miekgdns.ResponseWriter, r *miekgdns.Msg) {
_ = json.Unmarshal(marshal, &msg)
for i := 0; i < len(msg.Question); i++ {
msg.Question[i].Name = name
msg.Question[i].Qtype = miekgdns.TypeA // IPV4
}
msg.Ns = nil
msg.Extra = nil
//msg.Id = uint16(rand.Intn(math.MaxUint16 + 1))
//client := miekgdns.Client{Net: "udp", Timeout: time.Second * 30}
//r, _, err = client.ExchangeContext(ctx, m, a)
msg.Id = uint16(rand.Intn(math.MaxUint16 + 1))
answer, _, err := s.client.ExchangeContext(context.Background(), &msg, fmt.Sprintf("%s:%s", dnsAddr, s.forwardDNS.Port))
if err == nil && len(answer.Answer) != 0 {