Skip to content

Commit 062dc53

Browse files
committed
Revert "Remove support for xsalsapoly"
Apparently, a bunch of popular resolvers such as adguard, cleanbrowsing and comodo still only support xsalsapoly o_O Add a lying resolver check for old DNSCrypt servers.
1 parent 14af44d commit 062dc53

File tree

15 files changed

+1924
-9
lines changed

15 files changed

+1924
-9
lines changed

dnscrypt-proxy/common.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ type CryptoConstruction uint16
1818

1919
const (
2020
UndefinedConstruction CryptoConstruction = iota
21+
XSalsa20Poly1305
2122
XChacha20Poly1305
2223
)
2324

dnscrypt-proxy/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ func newConfig() Config {
154154
BlockedQueryResponse: "hinfo",
155155
BrokenImplementations: BrokenImplementationsConfig{
156156
FragmentsBlocked: []string{
157+
"cisco", "cisco-ipv6", "cisco-familyshield", "cisco-familyshield-ipv6",
157158
"cleanbrowsing-adult", "cleanbrowsing-adult-ipv6", "cleanbrowsing-family", "cleanbrowsing-family-ipv6", "cleanbrowsing-security", "cleanbrowsing-security-ipv6",
158159
},
159160
},

dnscrypt-proxy/crypto.go

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import (
99
"github.com/jedisct1/dlog"
1010
"github.com/jedisct1/xsecretbox"
1111
"golang.org/x/crypto/curve25519"
12+
"golang.org/x/crypto/nacl/box"
13+
"golang.org/x/crypto/nacl/secretbox"
1214
)
1315

1416
const (
@@ -55,9 +57,19 @@ func ComputeSharedKey(
5557
dlog.Criticalf("[%v] Weak XChaCha20 public key", providerName)
5658
}
5759
} else {
58-
dlog.Criticalf("[%v] Unsupported encryption system", providerName)
60+
box.Precompute(&sharedKey, serverPk, secretKey)
61+
c := byte(0)
62+
for i := 0; i < 32; i++ {
63+
c |= sharedKey[i]
64+
}
65+
if c == 0 {
66+
dlog.Criticalf("[%v] Weak XSalsa20 public key", providerName)
67+
if _, err := crypto_rand.Read(sharedKey[:]); err != nil {
68+
dlog.Fatal(err)
69+
}
70+
}
5971
}
60-
return sharedKey
72+
return
6173
}
6274

6375
func (proxy *Proxy) Encrypt(
@@ -112,7 +124,9 @@ func (proxy *Proxy) Encrypt(
112124
if serverInfo.CryptoConstruction == XChacha20Poly1305 {
113125
encrypted = xsecretbox.Seal(encrypted, nonce, padded, sharedKey[:])
114126
} else {
115-
err = errors.New("Unsupported encryption system")
127+
var xsalsaNonce [24]byte
128+
copy(xsalsaNonce[:], nonce)
129+
encrypted = secretbox.Seal(encrypted, padded, &xsalsaNonce, sharedKey)
116130
}
117131
return
118132
}
@@ -139,7 +153,13 @@ func (proxy *Proxy) Decrypt(
139153
if serverInfo.CryptoConstruction == XChacha20Poly1305 {
140154
packet, err = xsecretbox.Open(nil, serverNonce, encrypted[responseHeaderLen:], sharedKey[:])
141155
} else {
142-
err = errors.New("Unsupported encryption system")
156+
var xsalsaServerNonce [24]byte
157+
copy(xsalsaServerNonce[:], serverNonce)
158+
var ok bool
159+
packet, ok = secretbox.Open(nil, encrypted[responseHeaderLen:], &xsalsaServerNonce, sharedKey)
160+
if !ok {
161+
err = errors.New("Incorrect tag")
162+
}
143163
}
144164
if err != nil {
145165
return encrypted, err

dnscrypt-proxy/dnscrypt_certs.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,12 +95,12 @@ func FetchCurrentDNSCryptCert(
9595
cryptoConstruction := CryptoConstruction(0)
9696
switch esVersion := binary.BigEndian.Uint16(binCert[4:6]); esVersion {
9797
case 0x0001:
98-
dlog.Noticef("[%v] Deprecated, now unsupported encryption system", *serverName)
99-
continue
98+
cryptoConstruction = XSalsa20Poly1305
99+
dlog.Noticef("[%v] should upgrade to XChaCha20 for encryption", *serverName)
100100
case 0x0002:
101101
cryptoConstruction = XChacha20Poly1305
102102
default:
103-
dlog.Noticef("[%v] Unsupported encryption system", *serverName)
103+
dlog.Debugf("[%v] uses an unsupported encryption system", *serverName)
104104
continue
105105
}
106106
signature := binCert[8:72]
@@ -164,7 +164,7 @@ func FetchCurrentDNSCryptCert(
164164
dlog.Debugf("[%v] Upgrading the construction from %v to %v", *serverName, certInfo.CryptoConstruction, cryptoConstruction)
165165
}
166166
}
167-
if cryptoConstruction != XChacha20Poly1305 {
167+
if cryptoConstruction != XChacha20Poly1305 && cryptoConstruction != XSalsa20Poly1305 {
168168
dlog.Noticef("[%v] Cryptographic construction %v not supported", *serverName, cryptoConstruction)
169169
continue
170170
}

dnscrypt-proxy/example-dnscrypt-proxy.toml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -774,14 +774,18 @@ format = 'tsv'
774774

775775
[broken_implementations]
776776

777+
## Cisco servers currently cannot handle queries larger than 1472 bytes, and don't
778+
## truncate responses larger than questions as expected by the DNSCrypt protocol.
779+
## This prevents large responses from being received over UDP and over relays.
780+
##
777781
## Older versions of the `dnsdist` server software had a bug with queries larger
778782
## than 1500 bytes. This is fixed since `dnsdist` version 1.5.0, but
779783
## some server may still run an outdated version.
780784
##
781785
## The list below enables workarounds to make non-relayed usage more reliable
782786
## until the servers are fixed.
783787

784-
fragments_blocked = ['cleanbrowsing-adult', 'cleanbrowsing-adult-ipv6', 'cleanbrowsing-family', 'cleanbrowsing-family-ipv6', 'cleanbrowsing-security', 'cleanbrowsing-security-ipv6']
788+
fragments_blocked = ['cisco', 'cisco-ipv6', 'cisco-familyshield', 'cisco-familyshield-ipv6', 'cisco-sandbox', 'cleanbrowsing-adult', 'cleanbrowsing-adult-ipv6', 'cleanbrowsing-family', 'cleanbrowsing-family-ipv6', 'cleanbrowsing-security', 'cleanbrowsing-security-ipv6']
785789

786790

787791

dnscrypt-proxy/serversInfo.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -608,6 +608,27 @@ func fetchDNSCryptServerInfo(proxy *Proxy, name string, stamp stamps.ServerStamp
608608
if err != nil {
609609
return ServerInfo{}, err
610610
}
611+
612+
if certInfo.CryptoConstruction == XSalsa20Poly1305 {
613+
query := plainNXTestPacket(0xcafe)
614+
msg, _, _, err := DNSExchange(
615+
proxy,
616+
proxy.mainProto,
617+
&query,
618+
stamp.ServerAddrStr,
619+
dnscryptRelay,
620+
&name,
621+
false,
622+
)
623+
if err == nil {
624+
if msg.Rcode != dns.RcodeNameError && msg.Id == 0xcafe {
625+
dlog.Warnf("[%s] may be a lying resolver -- skipping", name)
626+
return ServerInfo{}, fmt.Errorf("[%s] unexpected catchall response", name)
627+
}
628+
dlog.Debugf("[%s] seems to be also accessible over plain DNS", name)
629+
}
630+
}
631+
611632
return ServerInfo{
612633
Proto: stamps.StampProtoTypeDNSCrypt,
613634
MagicQuery: certInfo.MagicQuery,
@@ -665,6 +686,19 @@ func dohNXTestPacket(msgID uint16) []byte {
665686
return body
666687
}
667688

689+
func plainNXTestPacket(msgID uint16) dns.Msg {
690+
msg := dns.Msg{}
691+
qName := make([]byte, 16)
692+
charset := "abcdefghijklmnopqrstuvwxyz"
693+
for i := range qName {
694+
qName[i] = charset[rand.Intn(len(charset))]
695+
}
696+
msg.SetQuestion(string(qName)+".test.dnscrypt.", dns.TypeNS)
697+
msg.Id = msgID
698+
msg.MsgHdr.RecursionDesired = true
699+
return msg
700+
}
701+
668702
func fetchDoHServerInfo(proxy *Proxy, name string, stamp stamps.ServerStamp, isNew bool) (ServerInfo, error) {
669703
// If an IP has been provided, use it forever.
670704
// Or else, if the fallback server and the DoH server are operated

vendor/golang.org/x/crypto/nacl/box/box.go

Lines changed: 182 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)