Skip to content

Commit 99220ae

Browse files
authored
Merge pull request #2986 from MegaManSec/noticeFailure
Better handle server failures and stale responses
2 parents 91db52f + cc62985 commit 99220ae

File tree

1 file changed

+26
-18
lines changed

1 file changed

+26
-18
lines changed

dnscrypt-proxy/query_processing.go

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ func processDNSCryptQuery(
7575
if err != nil {
7676
pluginsState.returnCode = PluginsReturnCodeParseError
7777
pluginsState.ApplyLoggingPlugins(&proxy.pluginsGlobals)
78+
serverInfo.noticeFailure(proxy)
7879
return nil, err
7980
}
8081
response, err = proxy.exchangeWithTCPServer(serverInfo, sharedKey, encryptedQuery, clientNonce)
@@ -87,7 +88,10 @@ func processDNSCryptQuery(
8788
if err != nil {
8889
if stale, ok := pluginsState.sessionData["stale"]; ok {
8990
dlog.Debug("Serving stale response")
90-
response, err = (stale.(*dns.Msg)).Pack()
91+
serverInfo.noticeFailure(proxy)
92+
if staleResponse, err := (stale.(*dns.Msg)).Pack(); err == nil {
93+
return staleResponse, nil
94+
}
9195
}
9296
}
9397

@@ -119,29 +123,30 @@ func processDoHQuery(
119123
serverResponse, _, tls, _, err := proxy.xTransport.DoHQuery(serverInfo.useGet, serverInfo.URL, query, proxy.timeout)
120124
SetTransactionID(query, tid)
121125

122-
// Check for stale response if there was an error
123-
if err != nil || tls == nil || !tls.HandshakeComplete {
124-
if stale, ok := pluginsState.sessionData["stale"]; ok {
125-
dlog.Debug("Serving stale response")
126-
return (stale.(*dns.Msg)).Pack()
126+
// A response was received, and the TLS handshake was complete.
127+
if err == nil && tls != nil && tls.HandshakeComplete {
128+
// Restore the original transaction ID
129+
response := serverResponse
130+
if len(response) >= MinDNSPacketSize {
131+
SetTransactionID(response, tid)
127132
}
133+
return response, nil
128134
}
129135

130-
// Handle error cases
131-
if err != nil {
132-
pluginsState.returnCode = PluginsReturnCodeNetworkError
133-
pluginsState.ApplyLoggingPlugins(&proxy.pluginsGlobals)
134-
serverInfo.noticeFailure(proxy)
135-
return nil, err
136-
}
136+
serverInfo.noticeFailure(proxy)
137137

138-
// Restore the original transaction ID
139-
response := serverResponse
140-
if len(response) >= MinDNSPacketSize {
141-
SetTransactionID(response, tid)
138+
// Attempt to serve a stale response as a fallback.
139+
if stale, ok := pluginsState.sessionData["stale"]; ok {
140+
dlog.Debug("Serving stale response")
141+
if staleResponse, packErr := (stale.(*dns.Msg)).Pack(); packErr == nil {
142+
return staleResponse, nil
143+
}
142144
}
143145

144-
return response, nil
146+
// If no stale response was served, return the original error.
147+
pluginsState.returnCode = PluginsReturnCodeNetworkError
148+
pluginsState.ApplyLoggingPlugins(&proxy.pluginsGlobals)
149+
return nil, err
145150
}
146151

147152
// processODoHQuery - Processes a query using the ODoH protocol
@@ -156,6 +161,8 @@ func processODoHQuery(
156161
return nil, nil
157162
}
158163

164+
serverInfo.noticeBegin(proxy)
165+
159166
target := serverInfo.odohTargetConfigs[rand.Intn(len(serverInfo.odohTargetConfigs))]
160167
odohQuery, err := target.encryptQuery(query)
161168
if err != nil {
@@ -175,6 +182,7 @@ func processODoHQuery(
175182
response, err := odohQuery.decryptResponse(responseBody)
176183
if err != nil {
177184
dlog.Warnf("Failed to decrypt response from [%v]", serverInfo.Name)
185+
serverInfo.noticeFailure(proxy)
178186
return nil, err
179187
}
180188

0 commit comments

Comments
 (0)