Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 46 additions & 11 deletions common/httpclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,29 @@ var (
"service.dogsdogs.xyz", // Used in replica
}

configDir atomic.Value
configDir atomic.Value

dohResolvers = []string{
"https://dns.google/dns-query",
"https://cloudflare-dns.com/dns-query",
"https://dns.quad9.net/dns-query",
"https://doh.opendns.com/dns-query",
"https://doh.libredns.gr/dns-query",
"https://jp.tiar.app/dns-query",
"https://doh.dns.sb/dns-query",
"https://dns.pub/dns-query",
"https://resolver2.absolight.net/dns-query",
"https://dns.alidns.com/dns-query",
}
dotResolvers = []string{
"8888.google",
"dns.quad9.net",
"dns.sb",
"dns.alidns.com",
"dns.comss.one",
"dns.kernel-error.de",
}

dnsttConfig atomic.Value // Holds the DNSTTConfig

defaultDNSTTConfig = &DNSTTConfig{
Expand Down Expand Up @@ -97,10 +119,12 @@ func GetHTTPClient() *http.Client {
} else {
kOptions = append(kOptions, kindling.WithDomainFronting(f))
}
if d, err := newDNSTT(); err != nil {
if ds, err := newDNSTTs(); err != nil {
log.Errorf("Failed to create DNSTT: %v", err)
} else {
kOptions = append(kOptions, kindling.WithDNSTunnel(d))
for _, d := range ds {
kOptions = append(kOptions, kindling.WithDNSTunnel(d))
}
}
k = kindling.NewKindling("flashlight", kOptions...)
httpClient = k.NewHTTPClient()
Expand Down Expand Up @@ -154,7 +178,7 @@ func (c *DNSTTConfig) Validate() error {
return nil
}

func newDNSTT() (dnstt.DNSTT, error) {
func newDNSTTs() ([]dnstt.DNSTT, error) {
cfg := dnsttConfig.Load().(*DNSTTConfig)
if err := cfg.Validate(); err != nil {
return nil, fmt.Errorf("invalid DNSTT configuration: %w", err)
Expand All @@ -164,14 +188,25 @@ func newDNSTT() (dnstt.DNSTT, error) {
dnstt.WithPublicKey(cfg.PublicKey),
dnstt.WithTunnelDomain(cfg.Domain),
}
switch {
case cfg.DoHResolver != "":
options = append(options, dnstt.WithDoH(cfg.DoHResolver))
case cfg.DoTResolver != "":
options = append(options, dnstt.WithDoT(cfg.DoTResolver))
}
if cfg.UTLSDistribution != "" {
options = append(options, dnstt.WithUTLSDistribution(cfg.UTLSDistribution))
}
return dnstt.NewDNSTT(options...)
dnstts := make([]dnstt.DNSTT, 0, len(dotResolvers)+len(dohResolvers))
for _, resolver := range dohResolvers {
opts := append([]dnstt.Option{dnstt.WithDoH(resolver)}, options...)
d, err := dnstt.NewDNSTT(opts...)
if err != nil {
return nil, fmt.Errorf("failed to create DNSTT with DoH resolver %s: %w", resolver, err)
}
dnstts = append(dnstts, d)
}
for _, resolver := range dotResolvers {
opts := append([]dnstt.Option{dnstt.WithDoT(resolver)}, options...)
d, err := dnstt.NewDNSTT(opts...)
if err != nil {
return nil, fmt.Errorf("failed to create DNSTT with DoT resolver %s: %w", resolver, err)
}
dnstts = append(dnstts, d)
}
return dnstts, nil
}
64 changes: 64 additions & 0 deletions common/httpclient_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package common

import (
"context"
"crypto/tls"
"io"
"net"
"net/http"
"testing"
"time"

"github.com/stretchr/testify/assert"
)

func TestDNSResolvers(t *testing.T) {
t.Skip("Skipping DNS resolver tests for github")

t.Run("DNS over HTTPS", func(t *testing.T) {
client := &http.Client{Timeout: 5 * time.Second}
failed := []string{}
for _, host := range dohResolvers {
req, err := http.NewRequest("GET", host+"?dns=AAABAAABAAAAAAAAB2V4YW1wbGUDY29tAAABAAE", nil)
req.Header.Set("Accept", "application/dns-message")
resp, err := client.Do(req)
if !assert.NoError(t, err) {
failed = append(failed, host)
continue
}
_, err = io.ReadAll(resp.Body)
if !assert.NoError(t, err) {
resp.Body.Close()
continue
}
resp.Body.Close()
}
assert.Empty(t, failed, "All DNS over TLS resolvers failed")
})
t.Run("DNS over TLS", func(t *testing.T) {
t.Skip("")
failed := []string{}
for _, host := range dotResolvers {
t.Logf("Testing DNS over TLS resolver: %s", host)
resolver := net.Resolver{
PreferGo: true,
Dial: func(ctx context.Context, network, addr string) (net.Conn, error) {
cfg := &tls.Config{
ServerName: host,
InsecureSkipVerify: true,
}
addr = net.JoinHostPort(host, "853")
return tls.DialWithDialer(new(net.Dialer), "tcp", addr, cfg)
},
}
ctx, _ := context.WithTimeout(context.Background(), 5*time.Second)
resp, err := resolver.LookupHost(ctx, "google.com")
if !assert.NoError(t, err) {
failed = append(failed, host)
continue
}
assert.Greater(t, len(resp), 0, "Expected at least one answer from %s", host)
}
assert.Empty(t, failed, "All DNS over TLS resolvers failed")
})
}
Loading