Added DNSCrypt upstreams support
Added DNS Stamps support
This commit is contained in:
Andrey Meshkov
2018-12-18 01:20:38 +03:00
parent 6e6c321871
commit b30b6b1d66
6 changed files with 118 additions and 12 deletions

View File

@@ -13,6 +13,9 @@ import (
"sync"
"time"
"github.com/jedisct1/go-dnsstamps"
"github.com/ameshkov/dnscrypt"
"github.com/joomcode/errorx"
"github.com/miekg/dns"
)
@@ -177,6 +180,51 @@ func (p *dnsOverHTTPS) Exchange(m *dns.Msg) (*dns.Msg, error) {
return &response, nil
}
//
// DNSCrypt
//
type dnsCrypt struct {
boot bootstrapper
client *dnscrypt.Client // DNSCrypt client properties
serverInfo *dnscrypt.ServerInfo // DNSCrypt server info
sync.RWMutex // protects DNSCrypt client
}
func (p *dnsCrypt) Address() string { return p.boot.address }
func (p *dnsCrypt) Exchange(m *dns.Msg) (*dns.Msg, error) {
var client *dnscrypt.Client
var serverInfo *dnscrypt.ServerInfo
p.RLock()
client = p.client
serverInfo = p.serverInfo
p.RUnlock()
if client == nil || serverInfo == nil {
p.Lock()
// Using "udp" for DNSCrypt upstreams by default
client = &dnscrypt.Client{Proto: "udp", Timeout: defaultTimeout}
si, _, err := client.Dial(p.boot.address)
if err != nil {
p.Unlock()
return nil, errorx.Decorate(err, "Failed to fetch certificate info from %s", p.Address())
}
p.client = client
p.serverInfo = si
serverInfo = si
p.Unlock()
}
reply, _, err := client.Exchange(m, serverInfo)
return reply, err
}
func (s *Server) chooseUpstream() Upstream {
upstreams := s.Upstreams
if upstreams == nil {
@@ -200,6 +248,20 @@ func AddressToUpstream(address string, bootstrap string) (Upstream, error) {
return nil, errorx.Decorate(err, "Failed to parse %s", address)
}
switch url.Scheme {
case "sdns":
stamp, err := dnsstamps.NewServerStampFromString(address)
if err != nil {
return nil, errorx.Decorate(err, "Failed to parse %s", address)
}
switch stamp.Proto {
case dnsstamps.StampProtoTypeDNSCrypt:
return &dnsCrypt{boot: toBoot(url.String(), bootstrap)}, nil
case dnsstamps.StampProtoTypeDoH:
return AddressToUpstream(fmt.Sprintf("https://%s%s", stamp.ProviderName, stamp.Path), bootstrap)
}
return nil, fmt.Errorf("Unsupported protocol %v in %s", stamp.Proto, address)
case "dns":
if url.Port() == "" {
url.Host += ":53"