mirror of
https://github.com/DNSCrypt/dnscrypt-proxy.git
synced 2025-03-04 02:14:40 +01:00
Try harder to work around Cisco and Quad9 bugs
This commit is contained in:
parent
64935c9b92
commit
7424f1a8b7
7 changed files with 116 additions and 85 deletions
|
@ -1,9 +1,7 @@
|
||||||
* Version 2.0.42
|
* Version 2.0.42
|
||||||
- Quad9 was put back into the list of broken implementations. They
|
- Quad9 was put back into the list of broken implementations. They
|
||||||
drop responses larger than questions instead of truncating them.
|
drop responses larger than questions instead of truncating them.
|
||||||
- Queries for servers that don't properly handle padding are now
|
- More workarounds were implemented for servers dropping UDP fragments.
|
||||||
padded to 1472 bytes. This mitigates the issue with Quad9 while
|
|
||||||
still working around the limitations of Cisco resolvers.
|
|
||||||
|
|
||||||
* Version 2.0.41
|
* Version 2.0.41
|
||||||
- Precompiled ARM binaries are compatible with ARMv5 CPUs. The
|
- Precompiled ARM binaries are compatible with ARMv5 CPUs. The
|
||||||
|
|
|
@ -134,7 +134,8 @@ func newConfig() Config {
|
||||||
LBEstimator: true,
|
LBEstimator: true,
|
||||||
BlockedQueryResponse: "hinfo",
|
BlockedQueryResponse: "hinfo",
|
||||||
BrokenImplementations: BrokenImplementationsConfig{
|
BrokenImplementations: BrokenImplementationsConfig{
|
||||||
BrokenQueryPadding: []string{"cisco", "cisco-ipv6", "cisco-familyshield", "quad9-dnscrypt-ip4-filter-alt", "quad9-dnscrypt-ip4-filter-pri", "quad9-dnscrypt-ip4-nofilter-alt", "quad9-dnscrypt-ip4-nofilter-pri", "quad9-dnscrypt-ip6-filter-alt", "quad9-dnscrypt-ip6-filter-pri", "quad9-dnscrypt-ip6-nofilter-alt", "quad9-dnscrypt-ip6-nofilter-pri"},
|
FragmentsBlocked: []string{"cisco", "cisco-ipv6", "cisco-familyshield", "quad9-dnscrypt-ip4-filter-alt", "quad9-dnscrypt-ip4-filter-pri", "quad9-dnscrypt-ip4-nofilter-alt", "quad9-dnscrypt-ip4-nofilter-pri", "quad9-dnscrypt-ip6-filter-alt", "quad9-dnscrypt-ip6-filter-pri", "quad9-dnscrypt-ip6-nofilter-alt", "quad9-dnscrypt-ip6-nofilter-pri"},
|
||||||
|
LargerResponsesDropped: []string{"quad9-dnscrypt-ip4-filter-alt", "quad9-dnscrypt-ip4-filter-pri", "quad9-dnscrypt-ip4-nofilter-alt", "quad9-dnscrypt-ip4-nofilter-pri", "quad9-dnscrypt-ip6-filter-alt", "quad9-dnscrypt-ip6-filter-pri", "quad9-dnscrypt-ip6-nofilter-alt", "quad9-dnscrypt-ip6-nofilter-pri"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -192,7 +193,9 @@ type AnonymizedDNSConfig struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type BrokenImplementationsConfig struct {
|
type BrokenImplementationsConfig struct {
|
||||||
BrokenQueryPadding []string `toml:"broken_query_padding"`
|
BrokenQueryPadding []string `toml:"broken_query_padding"`
|
||||||
|
FragmentsBlocked []string `toml:"fragments_blocked"`
|
||||||
|
LargerResponsesDropped []string `toml:"larger_responses_dropped"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type LocalDoHConfig struct {
|
type LocalDoHConfig struct {
|
||||||
|
@ -502,7 +505,12 @@ func ConfigLoad(proxy *Proxy, flags *ConfigFlags) error {
|
||||||
}
|
}
|
||||||
proxy.dohCreds = &creds
|
proxy.dohCreds = &creds
|
||||||
|
|
||||||
proxy.serversWithBrokenQueryPadding = config.BrokenImplementations.BrokenQueryPadding
|
// Backwards compatibility
|
||||||
|
config.BrokenImplementations.FragmentsBlocked = append(config.BrokenImplementations.FragmentsBlocked, config.BrokenImplementations.BrokenQueryPadding...)
|
||||||
|
config.BrokenImplementations.LargerResponsesDropped = append(config.BrokenImplementations.LargerResponsesDropped, config.BrokenImplementations.BrokenQueryPadding...)
|
||||||
|
|
||||||
|
proxy.serversBlockingFragments = config.BrokenImplementations.FragmentsBlocked
|
||||||
|
proxy.serversDroppingLargerResponses = config.BrokenImplementations.LargerResponsesDropped
|
||||||
|
|
||||||
if *flags.ListAll {
|
if *flags.ListAll {
|
||||||
config.ServerNames = nil
|
config.ServerNames = nil
|
||||||
|
|
|
@ -80,18 +80,24 @@ func (proxy *Proxy) Encrypt(serverInfo *ServerInfo, packet []byte, proto string)
|
||||||
}
|
}
|
||||||
minQuestionSize := QueryOverhead + len(packet)
|
minQuestionSize := QueryOverhead + len(packet)
|
||||||
if proto == "udp" {
|
if proto == "udp" {
|
||||||
if serverInfo.knownBugs.incorrectPadding {
|
minQuestionSize = Max(proxy.questionSizeEstimator.MinQuestionSize(), minQuestionSize)
|
||||||
// XXX - Note: Cisco's broken implementation doesn't accept more than 1472 bytes
|
|
||||||
minQuestionSize = Max(1472, minQuestionSize)
|
|
||||||
} else {
|
|
||||||
minQuestionSize = Max(proxy.questionSizeEstimator.MinQuestionSize(), minQuestionSize)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
var xpad [1]byte
|
var xpad [1]byte
|
||||||
rand.Read(xpad[:])
|
rand.Read(xpad[:])
|
||||||
minQuestionSize += int(xpad[0])
|
minQuestionSize += int(xpad[0])
|
||||||
}
|
}
|
||||||
paddedLength := Min(MaxDNSUDPPacketSize, (Max(minQuestionSize, QueryOverhead)+1+63) & ^63)
|
paddedLength := Min(MaxDNSUDPPacketSize, (Max(minQuestionSize, QueryOverhead)+1+63) & ^63)
|
||||||
|
if proto == "udp" {
|
||||||
|
if serverInfo.knownBugs.fragmentsBlocked {
|
||||||
|
if serverInfo.knownBugs.largerQueriesDropped {
|
||||||
|
paddedLength = MaxDNSUDPSafePacketSize
|
||||||
|
} else {
|
||||||
|
paddedLength = Min(MaxDNSUDPSafePacketSize, paddedLength)
|
||||||
|
}
|
||||||
|
} else if serverInfo.knownBugs.largerQueriesDropped {
|
||||||
|
paddedLength = MaxDNSUDPPacketSize
|
||||||
|
}
|
||||||
|
}
|
||||||
if serverInfo.RelayUDPAddr != nil && proto == "tcp" {
|
if serverInfo.RelayUDPAddr != nil && proto == "tcp" {
|
||||||
paddedLength = MaxDNSPacketSize
|
paddedLength = MaxDNSPacketSize
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ func FetchCurrentDNSCryptCert(proxy *Proxy, serverName *string, proto string, pk
|
||||||
relayUDPAddr, relayTCPAddr = nil, nil
|
relayUDPAddr, relayTCPAddr = nil, nil
|
||||||
}
|
}
|
||||||
tryFragmentsSupport := true
|
tryFragmentsSupport := true
|
||||||
if knownBugs.incorrectPadding {
|
if knownBugs.fragmentsBlocked {
|
||||||
tryFragmentsSupport = false
|
tryFragmentsSupport = false
|
||||||
}
|
}
|
||||||
in, rtt, fragmentsBlocked, err := dnsExchange(proxy, proto, &query, serverAddress, relayUDPAddr, relayTCPAddr, serverName, tryFragmentsSupport)
|
in, rtt, fragmentsBlocked, err := dnsExchange(proxy, proto, &query, serverAddress, relayUDPAddr, relayTCPAddr, serverName, tryFragmentsSupport)
|
||||||
|
|
|
@ -624,14 +624,19 @@ cache_neg_max_ttl = 600
|
||||||
|
|
||||||
# Cisco servers currently cannot handle queries larger than 1472 bytes, and don't
|
# Cisco servers currently cannot handle queries larger than 1472 bytes, and don't
|
||||||
# truncate reponses larger than questions as expected by the DNSCrypt protocol.
|
# truncate reponses larger than questions as expected by the DNSCrypt protocol.
|
||||||
# Quad9 ignores the query instead of sending a truncated response when the
|
|
||||||
# response is larger than the question.
|
|
||||||
# This prevents large responses from being received over UDP, and breaks relaying.
|
# This prevents large responses from being received over UDP, and breaks relaying.
|
||||||
# A workaround for the first issue will be applied to servers in list below.
|
# A workaround for the first issue will be applied to servers in list below.
|
||||||
# Relaying cannot be reliable until the servers are fixed.
|
# Relaying cannot be reliable until the servers are fixed.
|
||||||
# Do not change that list until the bugs are fixed server-side.
|
# Do not change that list until the bugs are fixed server-side.
|
||||||
|
|
||||||
broken_query_padding = ['cisco', 'cisco-ipv6', 'cisco-familyshield', 'quad9-dnscrypt-ip4-filter-alt', 'quad9-dnscrypt-ip4-filter-pri', 'quad9-dnscrypt-ip4-nofilter-alt', 'quad9-dnscrypt-ip4-nofilter-pri', 'quad9-dnscrypt-ip6-filter-alt', 'quad9-dnscrypt-ip6-filter-pri', 'quad9-dnscrypt-ip6-nofilter-alt', 'quad9-dnscrypt-ip6-nofilter-pri']
|
fragments_blocked = ['cisco', 'cisco-ipv6', 'cisco-familyshield', 'quad9-dnscrypt-ip4-filter-alt', 'quad9-dnscrypt-ip4-filter-pri', 'quad9-dnscrypt-ip4-nofilter-alt', 'quad9-dnscrypt-ip4-nofilter-pri', 'quad9-dnscrypt-ip6-filter-alt', 'quad9-dnscrypt-ip6-filter-pri', 'quad9-dnscrypt-ip6-nofilter-alt', 'quad9-dnscrypt-ip6-nofilter-pri']
|
||||||
|
|
||||||
|
# Quad9 ignores the query instead of sending a truncated response when the
|
||||||
|
# response is larger than the question.
|
||||||
|
# Do not change that list until the bugs are fixed server-side.
|
||||||
|
|
||||||
|
larger_responses_dropped = ['quad9-dnscrypt-ip4-filter-alt', 'quad9-dnscrypt-ip4-filter-pri', 'quad9-dnscrypt-ip4-nofilter-alt', 'quad9-dnscrypt-ip4-nofilter-pri', 'quad9-dnscrypt-ip6-filter-alt', 'quad9-dnscrypt-ip6-filter-pri', 'quad9-dnscrypt-ip6-nofilter-alt', 'quad9-dnscrypt-ip6-nofilter-pri']
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -16,68 +16,69 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Proxy struct {
|
type Proxy struct {
|
||||||
userName string
|
userName string
|
||||||
child bool
|
child bool
|
||||||
proxyPublicKey [32]byte
|
proxyPublicKey [32]byte
|
||||||
proxySecretKey [32]byte
|
proxySecretKey [32]byte
|
||||||
ephemeralKeys bool
|
ephemeralKeys bool
|
||||||
questionSizeEstimator QuestionSizeEstimator
|
questionSizeEstimator QuestionSizeEstimator
|
||||||
serversInfo ServersInfo
|
serversInfo ServersInfo
|
||||||
timeout time.Duration
|
timeout time.Duration
|
||||||
certRefreshDelay time.Duration
|
certRefreshDelay time.Duration
|
||||||
certRefreshDelayAfterFailure time.Duration
|
certRefreshDelayAfterFailure time.Duration
|
||||||
certIgnoreTimestamp bool
|
certIgnoreTimestamp bool
|
||||||
mainProto string
|
mainProto string
|
||||||
listenAddresses []string
|
listenAddresses []string
|
||||||
localDoHListenAddresses []string
|
localDoHListenAddresses []string
|
||||||
localDoHPath string
|
localDoHPath string
|
||||||
localDoHCertFile string
|
localDoHCertFile string
|
||||||
localDoHCertKeyFile string
|
localDoHCertKeyFile string
|
||||||
daemonize bool
|
daemonize bool
|
||||||
registeredServers []RegisteredServer
|
registeredServers []RegisteredServer
|
||||||
registeredRelays []RegisteredServer
|
registeredRelays []RegisteredServer
|
||||||
pluginBlockIPv6 bool
|
pluginBlockIPv6 bool
|
||||||
pluginBlockUnqualified bool
|
pluginBlockUnqualified bool
|
||||||
pluginBlockUndelegated bool
|
pluginBlockUndelegated bool
|
||||||
cache bool
|
cache bool
|
||||||
cacheSize int
|
cacheSize int
|
||||||
cacheNegMinTTL uint32
|
cacheNegMinTTL uint32
|
||||||
cacheNegMaxTTL uint32
|
cacheNegMaxTTL uint32
|
||||||
cacheMinTTL uint32
|
cacheMinTTL uint32
|
||||||
cacheMaxTTL uint32
|
cacheMaxTTL uint32
|
||||||
rejectTTL uint32
|
rejectTTL uint32
|
||||||
cloakTTL uint32
|
cloakTTL uint32
|
||||||
queryLogFile string
|
queryLogFile string
|
||||||
queryLogFormat string
|
queryLogFormat string
|
||||||
queryLogIgnoredQtypes []string
|
queryLogIgnoredQtypes []string
|
||||||
nxLogFile string
|
nxLogFile string
|
||||||
nxLogFormat string
|
nxLogFormat string
|
||||||
blockNameFile string
|
blockNameFile string
|
||||||
whitelistNameFile string
|
whitelistNameFile string
|
||||||
blockNameLogFile string
|
blockNameLogFile string
|
||||||
whitelistNameLogFile string
|
whitelistNameLogFile string
|
||||||
blockNameFormat string
|
blockNameFormat string
|
||||||
whitelistNameFormat string
|
whitelistNameFormat string
|
||||||
blockIPFile string
|
blockIPFile string
|
||||||
blockIPLogFile string
|
blockIPLogFile string
|
||||||
blockIPFormat string
|
blockIPFormat string
|
||||||
forwardFile string
|
forwardFile string
|
||||||
cloakFile string
|
cloakFile string
|
||||||
pluginsGlobals PluginsGlobals
|
pluginsGlobals PluginsGlobals
|
||||||
sources []*Source
|
sources []*Source
|
||||||
clientsCount uint32
|
clientsCount uint32
|
||||||
maxClients uint32
|
maxClients uint32
|
||||||
xTransport *XTransport
|
xTransport *XTransport
|
||||||
allWeeklyRanges *map[string]WeeklyRanges
|
allWeeklyRanges *map[string]WeeklyRanges
|
||||||
logMaxSize int
|
logMaxSize int
|
||||||
logMaxAge int
|
logMaxAge int
|
||||||
logMaxBackups int
|
logMaxBackups int
|
||||||
blockedQueryResponse string
|
blockedQueryResponse string
|
||||||
queryMeta []string
|
queryMeta []string
|
||||||
routes *map[string][]string
|
routes *map[string][]string
|
||||||
serversWithBrokenQueryPadding []string
|
serversBlockingFragments []string
|
||||||
showCerts bool
|
serversDroppingLargerResponses []string
|
||||||
dohCreds *map[string]DOHClientCreds
|
showCerts bool
|
||||||
|
dohCreds *map[string]DOHClientCreds
|
||||||
}
|
}
|
||||||
|
|
||||||
func (proxy *Proxy) addDNSListener(listenAddrStr string) {
|
func (proxy *Proxy) addDNSListener(listenAddrStr string) {
|
||||||
|
@ -473,6 +474,11 @@ func (proxy *Proxy) processIncomingQuery(clientProto string, serverProto string,
|
||||||
pluginsState.serverName = serverName
|
pluginsState.serverName = serverName
|
||||||
if serverInfo.Proto == stamps.StampProtoTypeDNSCrypt {
|
if serverInfo.Proto == stamps.StampProtoTypeDNSCrypt {
|
||||||
sharedKey, encryptedQuery, clientNonce, err := proxy.Encrypt(serverInfo, query, serverProto)
|
sharedKey, encryptedQuery, clientNonce, err := proxy.Encrypt(serverInfo, query, serverProto)
|
||||||
|
if err != nil && serverProto == "udp" {
|
||||||
|
dlog.Debug("Unable to pad for UDP, re-encrypting query for TCP")
|
||||||
|
serverProto = "tcp"
|
||||||
|
sharedKey, encryptedQuery, clientNonce, err = proxy.Encrypt(serverInfo, query, serverProto)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
pluginsState.returnCode = PluginsReturnCodeParseError
|
pluginsState.returnCode = PluginsReturnCodeParseError
|
||||||
pluginsState.ApplyLoggingPlugins(&proxy.pluginsGlobals)
|
pluginsState.ApplyLoggingPlugins(&proxy.pluginsGlobals)
|
||||||
|
|
|
@ -32,7 +32,8 @@ type RegisteredServer struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type ServerBugs struct {
|
type ServerBugs struct {
|
||||||
incorrectPadding bool
|
fragmentsBlocked bool
|
||||||
|
largerQueriesDropped bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type DOHClientCreds struct {
|
type DOHClientCreds struct {
|
||||||
|
@ -319,10 +320,17 @@ func fetchDNSCryptServerInfo(proxy *Proxy, name string, stamp stamps.ServerStamp
|
||||||
stamp.ServerPk = serverPk
|
stamp.ServerPk = serverPk
|
||||||
}
|
}
|
||||||
knownBugs := ServerBugs{}
|
knownBugs := ServerBugs{}
|
||||||
for _, buggyServerName := range proxy.serversWithBrokenQueryPadding {
|
for _, buggyServerName := range proxy.serversBlockingFragments {
|
||||||
if buggyServerName == name {
|
if buggyServerName == name {
|
||||||
knownBugs.incorrectPadding = true
|
knownBugs.fragmentsBlocked = true
|
||||||
dlog.Infof("Known bug in [%v]: padding is not correctly handled", name)
|
dlog.Infof("Known bug in [%v]: fragmented questions over UDP are blocked", name)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, buggyServerName := range proxy.serversDroppingLargerResponses {
|
||||||
|
if buggyServerName == name {
|
||||||
|
knownBugs.largerQueriesDropped = true
|
||||||
|
dlog.Infof("Known bug in [%v]: truncated responses are not sent when a response is larger than the query", name)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -331,11 +339,11 @@ func fetchDNSCryptServerInfo(proxy *Proxy, name string, stamp stamps.ServerStamp
|
||||||
return ServerInfo{}, err
|
return ServerInfo{}, err
|
||||||
}
|
}
|
||||||
certInfo, rtt, fragmentsBlocked, err := FetchCurrentDNSCryptCert(proxy, &name, proxy.mainProto, stamp.ServerPk, stamp.ServerAddrStr, stamp.ProviderName, isNew, relayUDPAddr, relayTCPAddr, knownBugs)
|
certInfo, rtt, fragmentsBlocked, err := FetchCurrentDNSCryptCert(proxy, &name, proxy.mainProto, stamp.ServerPk, stamp.ServerAddrStr, stamp.ProviderName, isNew, relayUDPAddr, relayTCPAddr, knownBugs)
|
||||||
if !knownBugs.incorrectPadding && fragmentsBlocked {
|
if !knownBugs.fragmentsBlocked && fragmentsBlocked {
|
||||||
dlog.Debugf("[%v] drops fragmented queries", name)
|
dlog.Debugf("[%v] drops fragmented queries", name)
|
||||||
knownBugs.incorrectPadding = true
|
knownBugs.fragmentsBlocked = true
|
||||||
}
|
}
|
||||||
if knownBugs.incorrectPadding && (relayUDPAddr != nil || relayTCPAddr != nil) {
|
if knownBugs.fragmentsBlocked && (relayUDPAddr != nil || relayTCPAddr != nil) {
|
||||||
dlog.Warnf("[%v] is incompatible with anonymization", name)
|
dlog.Warnf("[%v] is incompatible with anonymization", name)
|
||||||
relayTCPAddr, relayUDPAddr = nil, nil
|
relayTCPAddr, relayUDPAddr = nil, nil
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue