mirror of
https://github.com/Snawoot/opera-proxy.git
synced 2025-09-02 10:42:07 +00:00
implement concurrent bootstrap DNS resolver
This commit is contained in:
parent
34dde845dd
commit
9125854fa9
2 changed files with 33 additions and 69 deletions
15
main.go
15
main.go
|
@ -14,6 +14,7 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/netip"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -197,20 +198,28 @@ func run() int {
|
||||||
apiAddress = args.apiAddress
|
apiAddress = args.apiAddress
|
||||||
mainLogger.Info("Using fixed API host IP address = %s", apiAddress)
|
mainLogger.Info("Using fixed API host IP address = %s", apiAddress)
|
||||||
} else {
|
} else {
|
||||||
resolver, err := NewResolver(args.bootstrapDNS.values[0], args.timeout)
|
resolver, err := NewResolver(args.bootstrapDNS.values, args.timeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mainLogger.Critical("Unable to instantiate DNS resolver: %v", err)
|
mainLogger.Critical("Unable to instantiate DNS resolver: %v", err)
|
||||||
return 4
|
return 4
|
||||||
}
|
}
|
||||||
|
|
||||||
mainLogger.Info("Discovering API IP address...")
|
mainLogger.Info("Discovering API IP address...")
|
||||||
addrs := resolver.ResolveA(API_DOMAIN)
|
addrs, err := func() ([]netip.Addr, error) {
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), args.timeout)
|
||||||
|
defer cancel()
|
||||||
|
return resolver.LookupNetIP(ctx, "ip4", API_DOMAIN)
|
||||||
|
}()
|
||||||
|
if err != nil {
|
||||||
|
mainLogger.Critical("Unable to resolve API server address: %v", err)
|
||||||
|
return 14
|
||||||
|
}
|
||||||
if len(addrs) == 0 {
|
if len(addrs) == 0 {
|
||||||
mainLogger.Critical("Unable to resolve %s with specified bootstrap DNS", API_DOMAIN)
|
mainLogger.Critical("Unable to resolve %s with specified bootstrap DNS", API_DOMAIN)
|
||||||
return 14
|
return 14
|
||||||
}
|
}
|
||||||
|
|
||||||
apiAddress = addrs[0]
|
apiAddress = addrs[0].String()
|
||||||
mainLogger.Info("Discovered address of API host = %s", apiAddress)
|
mainLogger.Info("Discovered address of API host = %s", apiAddress)
|
||||||
}
|
}
|
||||||
seclientDialer = NewFixedDialer(apiAddress, dialer)
|
seclientDialer = NewFixedDialer(apiAddress, dialer)
|
||||||
|
|
87
resolver.go
87
resolver.go
|
@ -1,83 +1,38 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net/netip"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/AdguardTeam/dnsproxy/upstream"
|
"github.com/AdguardTeam/dnsproxy/upstream"
|
||||||
"github.com/miekg/dns"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Resolver struct {
|
type Resolver struct {
|
||||||
upstream upstream.Upstream
|
resolvers upstream.ParallelResolver
|
||||||
|
timeout time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
const DOT = 0x2e
|
func NewResolver(addresses []string, timeout time.Duration) (*Resolver, error) {
|
||||||
|
resolvers := make([]upstream.Resolver, 0, len(addresses))
|
||||||
func NewResolver(address string, timeout time.Duration) (*Resolver, error) {
|
opts := &upstream.Options{
|
||||||
opts := &upstream.Options{Timeout: timeout}
|
Timeout: timeout,
|
||||||
u, err := upstream.AddressToUpstream(address, opts)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
return &Resolver{upstream: u}, nil
|
for _, addr := range addresses {
|
||||||
}
|
u, err := upstream.AddressToUpstream(addr, opts)
|
||||||
|
if err != nil {
|
||||||
func (r *Resolver) ResolveA(domain string) []string {
|
return nil, fmt.Errorf("unable to construct upstream resolver from string %q: %w",
|
||||||
res := make([]string, 0)
|
addr, err)
|
||||||
if len(domain) == 0 {
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
if domain[len(domain)-1] != DOT {
|
|
||||||
domain = domain + "."
|
|
||||||
}
|
|
||||||
req := dns.Msg{}
|
|
||||||
req.Id = dns.Id()
|
|
||||||
req.RecursionDesired = true
|
|
||||||
req.Question = []dns.Question{
|
|
||||||
{Name: domain, Qtype: dns.TypeA, Qclass: dns.ClassINET},
|
|
||||||
}
|
|
||||||
reply, err := r.upstream.Exchange(&req)
|
|
||||||
if err != nil {
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
for _, rr := range reply.Answer {
|
|
||||||
if a, ok := rr.(*dns.A); ok {
|
|
||||||
res = append(res, a.A.String())
|
|
||||||
}
|
}
|
||||||
|
resolvers = append(resolvers, &upstream.UpstreamResolver{Upstream: u})
|
||||||
}
|
}
|
||||||
return res
|
return &Resolver{
|
||||||
|
resolvers: resolvers,
|
||||||
|
timeout: timeout,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Resolver) ResolveAAAA(domain string) []string {
|
func (r *Resolver) LookupNetIP(ctx context.Context, network string, host string) (addrs []netip.Addr, err error) {
|
||||||
res := make([]string, 0)
|
return r.resolvers.LookupNetIP(ctx, network, host)
|
||||||
if len(domain) == 0 {
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
if domain[len(domain)-1] != DOT {
|
|
||||||
domain = domain + "."
|
|
||||||
}
|
|
||||||
req := dns.Msg{}
|
|
||||||
req.Id = dns.Id()
|
|
||||||
req.RecursionDesired = true
|
|
||||||
req.Question = []dns.Question{
|
|
||||||
{Name: domain, Qtype: dns.TypeAAAA, Qclass: dns.ClassINET},
|
|
||||||
}
|
|
||||||
reply, err := r.upstream.Exchange(&req)
|
|
||||||
if err != nil {
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
for _, rr := range reply.Answer {
|
|
||||||
if a, ok := rr.(*dns.AAAA); ok {
|
|
||||||
res = append(res, a.AAAA.String())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Resolver) Resolve(domain string) []string {
|
|
||||||
res := r.ResolveA(domain)
|
|
||||||
if len(res) == 0 {
|
|
||||||
res = r.ResolveAAAA(domain)
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue