all: guarding against DNS forwarding loop

Based on how dnsmasq "--dns-loop-detect" mechanism.

See: https://thekelleys.org.uk/dnsmasq/docs/dnsmasq-man.html
This commit is contained in:
Cuong Manh Le
2023-09-21 06:10:21 +00:00
committed by Cuong Manh Le
parent 511c4e696f
commit a9959a6f3d
5 changed files with 136 additions and 0 deletions
+21
View File
@@ -2,8 +2,10 @@ package ctrld
import (
"context"
crand "crypto/rand"
"crypto/tls"
"crypto/x509"
"encoding/hex"
"errors"
"io"
"math/rand"
@@ -217,6 +219,7 @@ type UpstreamConfig struct {
http3RoundTripper6 http.RoundTripper
certPool *x509.CertPool
u *url.URL
uid string
}
// ListenerConfig specifies the networks configuration that ctrld will run on.
@@ -261,6 +264,7 @@ type Rule map[string][]string
// Init initialized necessary values for an UpstreamConfig.
func (uc *UpstreamConfig) Init() {
uc.uid = upstreamUID()
if u, err := url.Parse(uc.Endpoint); err == nil {
uc.Domain = u.Host
switch uc.Type {
@@ -341,6 +345,11 @@ func (uc *UpstreamConfig) SetupBootstrapIP() {
uc.setupBootstrapIP(true)
}
// UID returns the unique identifier of the upstream.
func (uc *UpstreamConfig) UID() string {
return uc.uid
}
// SetupBootstrapIP manually find all available IPs of the upstream.
// The first usable IP will be used as bootstrap IP of the upstream.
func (uc *UpstreamConfig) setupBootstrapIP(withBootstrapDNS bool) {
@@ -680,3 +689,15 @@ func ResolverTypeFromEndpoint(endpoint string) string {
func pick(s []string) string {
return s[rand.Intn(len(s))]
}
// upstreamUID generates an unique identifier for an upstream.
func upstreamUID() string {
b := make([]byte, 4)
for {
if _, err := crand.Read(b); err != nil {
ProxyLogger.Load().Warn().Err(err).Msg("could not generate uid for upstream, retrying...")
continue
}
return hex.EncodeToString(b)
}
}