From b30b6b1d66c69f37cd97725f18d797a7ff2395d2 Mon Sep 17 00:00:00 2001 From: Andrey Meshkov Date: Tue, 18 Dec 2018 01:20:38 +0300 Subject: [PATCH] Fix #284 Added DNSCrypt upstreams support Added DNS Stamps support --- client/src/__locales/en.json | 1 + client/src/components/Settings/Upstream.js | 3 ++ dnsforward/upstream.go | 62 ++++++++++++++++++++++ dnsforward/upstream_test.go | 27 ++++++++++ go.mod | 9 ++-- go.sum | 28 +++++++--- 6 files changed, 118 insertions(+), 12 deletions(-) diff --git a/client/src/__locales/en.json b/client/src/__locales/en.json index 57aad1a6..e0eed4ea 100644 --- a/client/src/__locales/en.json +++ b/client/src/__locales/en.json @@ -89,6 +89,7 @@ "example_upstream_regular": "regular DNS (over UDP)", "example_upstream_dot": "encrypted DNS-over-TLS<\/a>", "example_upstream_doh": "encrypted DNS-over-HTTPS<\/a>", + "example_upstream_sdns": "you can use DNS Stamps for DNSCrypt or DNS-over-HTTPS resolvers", "example_upstream_tcp": "regular DNS (over TCP)", "all_filters_up_to_date_toast": "All filters are already up-to-date", "updated_upstream_dns_toast": "Updated the upstream DNS servers", diff --git a/client/src/components/Settings/Upstream.js b/client/src/components/Settings/Upstream.js index c0d0abf3..4ae0598a 100644 --- a/client/src/components/Settings/Upstream.js +++ b/client/src/components/Settings/Upstream.js @@ -73,6 +73,9 @@ class Upstream extends Component {
  • tcp://1.1.1.1 - { t('example_upstream_tcp') }
  • +
  • + sdns://... - +
  • diff --git a/dnsforward/upstream.go b/dnsforward/upstream.go index 89016951..a1bdd1a2 100644 --- a/dnsforward/upstream.go +++ b/dnsforward/upstream.go @@ -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" diff --git a/dnsforward/upstream_test.go b/dnsforward/upstream_test.go index 0b83670f..3db97fbe 100644 --- a/dnsforward/upstream_test.go +++ b/dnsforward/upstream_test.go @@ -8,6 +8,7 @@ import ( ) func TestUpstreams(t *testing.T) { + upstreams := []struct { address string bootstrap string @@ -56,8 +57,34 @@ func TestUpstreams(t *testing.T) { address: "https://doh.cleanbrowsing.org/doh/security-filter/", bootstrap: "", }, + { + // AdGuard DNS (DNSCrypt) + address: "sdns://AQIAAAAAAAAAFDE3Ni4xMDMuMTMwLjEzMDo1NDQzINErR_JS3PLCu_iZEIbq95zkSV2LFsigxDIuUso_OQhzIjIuZG5zY3J5cHQuZGVmYXVsdC5uczEuYWRndWFyZC5jb20", + bootstrap: "", + }, + { + // Cisco OpenDNS (DNSCrypt) + address: "sdns://AQAAAAAAAAAADjIwOC42Ny4yMjAuMjIwILc1EUAgbyJdPivYItf9aR6hwzzI1maNDL4Ev6vKQ_t5GzIuZG5zY3J5cHQtY2VydC5vcGVuZG5zLmNvbQ", + bootstrap: "8.8.8.8:53", + }, + { + // Cloudflare DNS (DoH) + address: "sdns://AgcAAAAAAAAABzEuMC4wLjGgENk8mGSlIfMGXMOlIlCcKvq7AVgcrZxtjon911-ep0cg63Ul-I8NlFj4GplQGb_TTLiczclX57DvMV8Q-JdjgRgSZG5zLmNsb3VkZmxhcmUuY29tCi9kbnMtcXVlcnk", + bootstrap: "8.8.8.8:53", + }, + { + // doh-cleanbrowsing-security (https://doh.cleanbrowsing.org/doh/security-filter/) + address: "sdns://AgMAAAAAAAAAAAAVZG9oLmNsZWFuYnJvd3Npbmcub3JnFS9kb2gvc2VjdXJpdHktZmlsdGVyLw", + bootstrap: "8.8.8.8:53", + }, + { + // Google (DNS-over-HTTPS) + address: "sdns://AgUAAAAAAAAAACAe9iTP_15r07rd8_3b_epWVGfjdymdx-5mdRZvMAzBuQ5kbnMuZ29vZ2xlLmNvbQ0vZXhwZXJpbWVudGFs", + bootstrap: "8.8.8.8:53", + }, } for _, test := range upstreams { + t.Run(test.address, func(t *testing.T) { u, err := AddressToUpstream(test.address, test.bootstrap) if err != nil { diff --git a/go.mod b/go.mod index 166e3cce..9acaa0dc 100644 --- a/go.mod +++ b/go.mod @@ -2,20 +2,21 @@ module github.com/AdguardTeam/AdGuardHome require ( github.com/StackExchange/wmi v0.0.0-20180725035823-b12b22c5341f // indirect + github.com/ameshkov/dnscrypt v0.0.0-20181217090431-1215bb8b150f github.com/beefsack/go-rate v0.0.0-20180408011153-efa7637bb9b6 github.com/bluele/gcache v0.0.0-20171010155617-472614239ac7 github.com/go-ole/go-ole v1.2.1 // indirect github.com/go-test/deep v1.0.1 github.com/gobuffalo/packr v1.19.0 + github.com/jedisct1/go-dnsstamps v0.0.0-20180418170050-1e4999280f86 github.com/joomcode/errorx v0.1.0 - github.com/miekg/dns v1.0.15 + github.com/miekg/dns v1.1.1 github.com/patrickmn/go-cache v2.1.0+incompatible github.com/shirou/gopsutil v2.18.10+incompatible github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4 // indirect go.uber.org/goleak v0.10.0 - golang.org/x/crypto v0.0.0-20181106171534-e4dc69e5b2fd - golang.org/x/net v0.0.0-20181108082009-03003ca0c849 - golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8 // indirect + golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9 + golang.org/x/net v0.0.0-20181213202711-891ebc4b82d6 gopkg.in/asaskevich/govalidator.v4 v4.0.0-20160518190739-766470278477 gopkg.in/yaml.v2 v2.2.1 ) diff --git a/go.sum b/go.sum index af10df24..33ffb8cf 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,11 @@ github.com/StackExchange/wmi v0.0.0-20180725035823-b12b22c5341f h1:5ZfJxyXo8KyX8DgGXC5B7ILL8y51fci/qYz2B4j8iLY= github.com/StackExchange/wmi v0.0.0-20180725035823-b12b22c5341f/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= +github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da h1:KjTM2ks9d14ZYCvmHS9iAKVt9AyzRSqNU1qabPih5BY= +github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da/go.mod h1:eHEWzANqSiWQsof+nXEI9bUVUyV6F53Fp89EuCh2EAA= +github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635 h1:52m0LGchQBBVqJRyYYufQuIbVqRawmubW3OFGqK1ekw= +github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635/go.mod h1:lmLxL+FV291OopO93Bwf9fQLQeLyt33VJRUg5VJ30us= +github.com/ameshkov/dnscrypt v0.0.0-20181217090431-1215bb8b150f h1:vOaSvI9B3wqzV1g8raDeVzRJnq5RHQxsz0MVXudxdNU= +github.com/ameshkov/dnscrypt v0.0.0-20181217090431-1215bb8b150f/go.mod h1:EC7Z1GguyEEwhuLXrcgkRTE3GdyPDSWq2OXefhydGWo= github.com/beefsack/go-rate v0.0.0-20180408011153-efa7637bb9b6 h1:KXlsf+qt/X5ttPGEjR0tPH1xaWWoKBEg9Q1THAj2h3I= github.com/beefsack/go-rate v0.0.0-20180408011153-efa7637bb9b6/go.mod h1:6YNgTHLutezwnBvyneBbwvB8C82y3dcoOj5EQJIdGXA= github.com/bluele/gcache v0.0.0-20171010155617-472614239ac7 h1:NpQ+gkFOH27AyDypSCJ/LdsIi/b4rdnEb1N5+IpFfYs= @@ -17,14 +23,18 @@ github.com/gobuffalo/packd v0.0.0-20181031195726-c82734870264/go.mod h1:Yf2toFaI github.com/gobuffalo/packr v1.19.0 h1:3UDmBDxesCOPF8iZdMDBBWKfkBoYujIMIZePnobqIUI= github.com/gobuffalo/packr v1.19.0/go.mod h1:MstrNkfCQhd5o+Ct4IJ0skWlxN8emOq8DsoT1G98VIU= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/jedisct1/go-dnsstamps v0.0.0-20180418170050-1e4999280f86 h1:Olj4M6T1omUfx7yTTcnhLf4xo6gYMmRHSJIfeA1NZy0= +github.com/jedisct1/go-dnsstamps v0.0.0-20180418170050-1e4999280f86/go.mod h1:j/ONpSHHmPgDwmFKXg9vhQvIjADe/ft1X4a3TVOmp9g= +github.com/jedisct1/xsecretbox v0.0.0-20180508184500-7a679c0bcd9a h1:2nyBWKszM41RO/gt5ElUXigAFiRgJ9KifHDlWOlw0lc= +github.com/jedisct1/xsecretbox v0.0.0-20180508184500-7a679c0bcd9a/go.mod h1:YlN58h704uRFD0BwsEGTq+7Wx+WG2i7P49bc+HwHyAY= github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= github.com/joomcode/errorx v0.1.0 h1:QmJMiI1DE1UFje2aI1ZWO/VMT5a32qBoXUclGOt8vsc= github.com/joomcode/errorx v0.1.0/go.mod h1:kgco15ekB6cs+4Xjzo7SPeXzx38PbJzBwbnu9qfVNHQ= github.com/markbates/oncer v0.0.0-20181014194634-05fccaae8fc4 h1:Mlji5gkcpzkqTROyE4ZxZ8hN7osunMb2RuGVrbvMvCc= github.com/markbates/oncer v0.0.0-20181014194634-05fccaae8fc4/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE= -github.com/miekg/dns v1.0.15 h1:9+UupePBQCG6zf1q/bGmTO1vumoG13jsrbWOSX1W6Tw= -github.com/miekg/dns v1.0.15/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.1 h1:DVkblRdiScEnEr0LR9nTnEQqHYycjkXW9bOjd+2EL2o= +github.com/miekg/dns v1.1.1/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw= @@ -43,15 +53,17 @@ github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1 github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= go.uber.org/goleak v0.10.0 h1:G3eWbSNIskeRqtsN/1uI5B+eP73y3JUuBsv9AZjehb4= go.uber.org/goleak v0.10.0/go.mod h1:VCZuO8V8mFPlL0F5J5GK1rtHV3DrFcQ1R8ryq7FK0aI= -golang.org/x/crypto v0.0.0-20181106171534-e4dc69e5b2fd h1:VtIkGDhk0ph3t+THbvXHfMZ8QHgsBO39Nh52+74pq7w= -golang.org/x/crypto v0.0.0-20181106171534-e4dc69e5b2fd/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9 h1:mKdxBk7AujPs8kU4m80U72y/zjbZ3UcXC7dClwKbUI0= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/net v0.0.0-20181102091132-c10e9556a7bc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181108082009-03003ca0c849 h1:FSqE2GGG7wzsYUsWiQ8MZrvEd1EOyU3NCF0AW3Wtltg= -golang.org/x/net v0.0.0-20181108082009-03003ca0c849/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181213202711-891ebc4b82d6 h1:gT0Y6H7hbVPUtvtk0YGxMXPgN+p8fYlqWkgJeUCZcaQ= +golang.org/x/net v0.0.0-20181213202711-891ebc4b82d6/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8 h1:YoY1wS6JYVRpIfFngRf2HHo9R9dAne3xbkGOQ5rJXjU= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f h1:Bl/8QSvNqXvPGPGXa2z5xUTmV7VDcZyvRZ+QQXkXTZQ= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20181213200352-4d1cda033e06 h1:0oC8rFnE+74kEmuHZ46F6KHsMr5Gx2gUQPuNz28iQZM= +golang.org/x/sys v0.0.0-20181213200352-4d1cda033e06/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= gopkg.in/asaskevich/govalidator.v4 v4.0.0-20160518190739-766470278477 h1:5xUJw+lg4zao9W4HIDzlFbMYgSgtvNVHh00MEHvbGpQ= gopkg.in/asaskevich/govalidator.v4 v4.0.0-20160518190739-766470278477/go.mod h1:QDV1vrFSrowdoOba0UM8VJPUZONT7dnfdLsM+GG53Z8= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=