Skip to content

Commit 2a1d678

Browse files
committed
Merge branch 'master' of github.com:DNSCrypt/dnscrypt-proxy
* 'master' of github.com:DNSCrypt/dnscrypt-proxy: Impove generate-domains-blocklist.py for bad network situations Update deps Forward plugin: if we got nothing but errors, return the last response we got Empty signal handler for Windows Allow manual reload via SIGHUP regardless of hot-reload enablement prometheus: removing duplicate metric prometheus: expose "build_info" gauge Monitoring UI: fix UI scrolling issues Always redo SetWriteDeadline for each broadcast update global WebSocket directly to avoid side effects Monitoring UI: preserve recent queries table during WebSocket reconnects
2 parents 5293961 + 5669e1d commit 2a1d678

25 files changed

Lines changed: 17830 additions & 17677 deletions

File tree

dnscrypt-proxy/hot_reload.go

Lines changed: 16 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,17 @@
11
package main
22

33
import (
4-
"os"
5-
"os/signal"
6-
"syscall"
7-
84
"github.com/jedisct1/dlog"
95
)
106

117
// InitHotReload sets up hot-reloading for configuration files
128
func (proxy *Proxy) InitHotReload() error {
13-
// Check if hot reload is enabled
14-
if !proxy.enableHotReload {
9+
// Check if hot reload is enabled and platform has SIGHUP
10+
if !proxy.enableHotReload && !HasSIGHUP {
1511
dlog.Notice("Hot reload is disabled")
1612
return nil
1713
}
1814

19-
dlog.Notice("Hot reload is enabled")
20-
21-
// Create a new configuration watcher
22-
configWatcher := NewConfigWatcher(1000) // Check every second
23-
2415
// Find plugins that support hot-reloading
2516
plugins := []Plugin{}
2617

@@ -40,6 +31,20 @@ func (proxy *Proxy) InitHotReload() error {
4031
}
4132
proxy.pluginsGlobals.RUnlock()
4233

34+
// Setup SIGHUP handler for manual reload
35+
setupSignalHandler(proxy, plugins)
36+
37+
// Check if hot reload is enabled
38+
if !proxy.enableHotReload {
39+
dlog.Notice("Hot reload is disabled")
40+
return nil
41+
}
42+
43+
dlog.Notice("Hot reload is enabled")
44+
45+
// Create a new configuration watcher
46+
configWatcher := NewConfigWatcher(1000) // Check every second
47+
4348
// Register plugins for config watching
4449
for _, plugin := range plugins {
4550
switch p := plugin.(type) {
@@ -100,32 +105,5 @@ func (proxy *Proxy) InitHotReload() error {
100105
}
101106
}
102107

103-
// Setup SIGHUP handler for manual reload
104-
setupSignalHandler(proxy, plugins)
105-
106108
return nil
107109
}
108-
109-
// setupSignalHandler sets up a SIGHUP handler to manually trigger reloads
110-
func setupSignalHandler(proxy *Proxy, plugins []Plugin) {
111-
sigChan := make(chan os.Signal, 1)
112-
signal.Notify(sigChan, syscall.SIGHUP)
113-
114-
go func() {
115-
for {
116-
sig := <-sigChan
117-
if sig == syscall.SIGHUP {
118-
dlog.Notice("Received SIGHUP signal, reloading configurations")
119-
120-
// Reload each plugin that supports hot-reloading
121-
for _, plugin := range plugins {
122-
if err := plugin.Reload(); err != nil {
123-
dlog.Errorf("Failed to reload plugin [%s]: %v", plugin.Name(), err)
124-
} else {
125-
dlog.Noticef("Successfully reloaded plugin [%s]", plugin.Name())
126-
}
127-
}
128-
}
129-
}
130-
}()
131-
}

dnscrypt-proxy/monitoring_ui.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"html"
88
"net"
99
"net/http"
10+
"runtime"
1011
"sort"
1112
"strings"
1213
"sync"
@@ -485,6 +486,10 @@ func (mc *MetricsCollector) generatePrometheusMetrics() string {
485486
var result strings.Builder
486487

487488
// Write help and type information for each metric
489+
result.WriteString("# HELP dnscrypt_proxy_build_info A metric with a constant '1' value labeled by version, goversion from which dnscrypt_proxy was built, and the goos and goarch for the build.\n")
490+
result.WriteString("# TYPE dnscrypt_proxy_build_info gauge\n")
491+
result.WriteString(fmt.Sprintf("dnscrypt_proxy_build_info{goarch=\"%s\" goos=\"%s\" goversion=\"%s\" version=\"%s\"} 1\n", runtime.GOARCH, runtime.GOOS, runtime.Version(), AppVersion))
492+
488493
result.WriteString("# HELP dnscrypt_proxy_queries_total Total number of DNS queries processed\n")
489494
result.WriteString("# TYPE dnscrypt_proxy_queries_total counter\n")
490495
result.WriteString(fmt.Sprintf("dnscrypt_proxy_queries_total %d\n", totalQueries))
@@ -1119,6 +1124,7 @@ func (ui *MonitoringUI) broadcastMetrics() {
11191124
defer ui.clientsMutex.Unlock()
11201125

11211126
for client := range ui.clients {
1127+
client.SetWriteDeadline(time.Now().Add(5 * time.Second))
11221128
err := client.WriteJSON(metrics)
11231129
if err != nil {
11241130
dlog.Debugf("WebSocket write error: %v", err)

dnscrypt-proxy/plugin_forward.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -322,19 +322,19 @@ func (plugin *PluginForward) Eval(pluginsState *PluginsState, msg *dns.Msg) erro
322322
continue
323323
}
324324
}
325-
if len(sequence) > 0 {
326-
switch respMsg.Rcode {
327-
case dns.RcodeNameError, dns.RcodeRefused, dns.RcodeNotAuth:
328-
continue
329-
}
330-
}
331325
if edns0 := respMsg.IsEdns0(); edns0 == nil || !edns0.Do() {
332326
respMsg.AuthenticatedData = false
333327
}
334328
respMsg.Id = msg.Id
335329
pluginsState.synthResponse = respMsg
336330
pluginsState.action = PluginsActionSynth
337331
pluginsState.returnCode = PluginsReturnCodeForward
332+
if len(sequence) > 0 {
333+
switch respMsg.Rcode {
334+
case dns.RcodeNameError, dns.RcodeRefused, dns.RcodeNotAuth:
335+
continue
336+
}
337+
}
338338
return nil
339339
}
340340
return err

dnscrypt-proxy/signal_others.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
//go:build windows || (js && wasm) || wasip1
2+
3+
package main
4+
5+
const HasSIGHUP = false
6+
7+
// setupSignalHandler sets up a SIGHUP handler to manually trigger reloads
8+
func setupSignalHandler(proxy *Proxy, plugins []Plugin) {
9+
return
10+
}

dnscrypt-proxy/signal_posix.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//go:build unix && !(js && wasm) && !wasip1
2+
3+
package main
4+
5+
import (
6+
"os"
7+
"os/signal"
8+
"syscall"
9+
10+
"github.com/jedisct1/dlog"
11+
)
12+
13+
const HasSIGHUP = true
14+
15+
// setupSignalHandler sets up a SIGHUP handler to manually trigger reloads
16+
func setupSignalHandler(proxy *Proxy, plugins []Plugin) {
17+
sigChan := make(chan os.Signal, 1)
18+
signal.Notify(sigChan, syscall.SIGHUP)
19+
20+
go func() {
21+
for {
22+
sig := <-sigChan
23+
if sig == syscall.SIGHUP {
24+
dlog.Notice("Received SIGHUP signal, reloading configurations")
25+
26+
// Reload each plugin that supports hot-reloading
27+
for _, plugin := range plugins {
28+
if err := plugin.Reload(); err != nil {
29+
dlog.Errorf("Failed to reload plugin [%s]: %v", plugin.Name(), err)
30+
} else {
31+
dlog.Noticef("Successfully reloaded plugin [%s]", plugin.Name())
32+
}
33+
}
34+
}
35+
}
36+
}()
37+
}

dnscrypt-proxy/static/js/monitoring.js

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ function handleError(error) {
6464
}
6565
}
6666

67+
// Cache for the last non-empty recent queries
68+
let lastRecentQueries = [];
69+
6770
// Safe update function that handles missing data
6871
function safeUpdateDashboard(data) {
6972
try {
@@ -72,6 +75,11 @@ function safeUpdateDashboard(data) {
7275
return;
7376
}
7477

78+
if (data.type === 'pong') {
79+
console.log('Received pong message');
80+
return;
81+
}
82+
7583
console.log('Updating dashboard with data');
7684

7785
// Store the current scroll position before updates
@@ -142,9 +150,14 @@ function safeUpdateDashboard(data) {
142150

143151
// Update recent queries table
144152
const queriesTable = document.getElementById('queries-table').getElementsByTagName('tbody')[0];
153+
let queriesToShow = lastRecentQueries;
154+
if (data.recent_queries && Array.isArray(data.recent_queries) && data.recent_queries.length > 0) {
155+
lastRecentQueries = data.recent_queries;
156+
queriesToShow = lastRecentQueries;
157+
}
145158
queriesTable.innerHTML = '';
146-
if (data.recent_queries && Array.isArray(data.recent_queries)) {
147-
data.recent_queries.slice().reverse().forEach(query => {
159+
if (queriesToShow && Array.isArray(queriesToShow)) {
160+
queriesToShow.slice().reverse().forEach(query => {
148161
const row = queriesTable.insertRow();
149162
row.insertCell(0).textContent = query.timestamp ? new Date(query.timestamp).toLocaleTimeString() : '-';
150163
row.insertCell(1).textContent = query.domain || '-';
@@ -273,23 +286,23 @@ function connectWebSocket() {
273286
console.log('WebSocket URL:', wsUrl);
274287

275288
// Create WebSocket connection
276-
var ws = new WebSocket(wsUrl);
289+
var newWs = new WebSocket(wsUrl);
277290

278291
// Connection opened
279-
ws.onopen = function() {
292+
newWs.onopen = function() {
280293
console.log('WebSocket connected successfully');
281294
wsReconnectAttempts = 0; // Reset reconnect attempts on successful connection
282295

283296
// Send a ping to verify connection
284297
try {
285-
ws.send(JSON.stringify({type: 'ping'}));
298+
newWs.send(JSON.stringify({type: 'ping'}));
286299
} catch (e) {
287300
console.error('Error sending ping:', e);
288301
}
289302
};
290303

291304
// Listen for messages
292-
ws.onmessage = function(event) {
305+
newWs.onmessage = function(event) {
293306
try {
294307
if (!event) {
295308
console.warn('Received invalid WebSocket event');
@@ -310,12 +323,12 @@ function connectWebSocket() {
310323
};
311324

312325
// Handle errors
313-
ws.onerror = function(error) {
326+
newWs.onerror = function(error) {
314327
console.error('WebSocket error occurred:', error);
315328
};
316329

317330
// Connection closed
318-
ws.onclose = function(event) {
331+
newWs.onclose = function(event) {
319332
console.log('WebSocket disconnected, code:', event.code, 'reason:', event.reason || 'No reason provided');
320333

321334
// Try to reconnect with exponential backoff
@@ -325,10 +338,8 @@ function connectWebSocket() {
325338
console.log('Attempting to reconnect in ' + delay + 'ms (attempt ' + wsReconnectAttempts + '/' + maxReconnectAttempts + ')');
326339

327340
setTimeout(function() {
328-
var newWs = connectWebSocket();
329-
if (newWs) {
330-
// We can't update the global ws variable from here
331-
// Instead, we'll rely on the polling fallback
341+
ws = connectWebSocket();
342+
if (ws) {
332343
console.log('New WebSocket connection established');
333344
}
334345
}, delay);
@@ -337,7 +348,7 @@ function connectWebSocket() {
337348
}
338349
};
339350

340-
return ws;
351+
return newWs;
341352
} catch (error) {
342353
console.error('Failed to create WebSocket connection:', error);
343354
return null;
@@ -446,4 +457,4 @@ setTimeout(function() {
446457
loadingIndicator.style.display = 'none';
447458
}, 5000);
448459
}
449-
}, 20000);
460+
}, 20000);

go.mod

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ require (
2424
github.com/miekg/dns v1.1.66
2525
github.com/powerman/check v1.8.0
2626
github.com/quic-go/quic-go v0.52.0
27-
golang.org/x/crypto v0.38.0
28-
golang.org/x/net v0.40.0
27+
golang.org/x/crypto v0.39.0
28+
golang.org/x/net v0.41.0
2929
golang.org/x/sys v0.33.0
3030
gopkg.in/natefinch/lumberjack.v2 v2.2.1
3131
)
@@ -44,10 +44,10 @@ require (
4444
github.com/quic-go/qpack v0.5.1 // indirect
4545
github.com/smartystreets/goconvey v1.8.1 // indirect
4646
go.uber.org/mock v0.5.0 // indirect
47-
golang.org/x/mod v0.24.0 // indirect
48-
golang.org/x/sync v0.14.0 // indirect
49-
golang.org/x/text v0.25.0 // indirect
50-
golang.org/x/tools v0.32.0 // indirect
47+
golang.org/x/mod v0.25.0 // indirect
48+
golang.org/x/sync v0.15.0 // indirect
49+
golang.org/x/text v0.26.0 // indirect
50+
golang.org/x/tools v0.33.0 // indirect
5151
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect
5252
google.golang.org/grpc v1.56.3 // indirect
5353
google.golang.org/protobuf v1.34.2 // indirect

go.sum

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -91,23 +91,23 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT
9191
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
9292
go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
9393
go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
94-
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
95-
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
96-
golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
97-
golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
98-
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
99-
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
100-
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
101-
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
94+
golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM=
95+
golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=
96+
golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w=
97+
golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
98+
golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
99+
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
100+
golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8=
101+
golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
102102
golang.org/x/sys v0.0.0-20190529164535-6a60838ec259/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
103103
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
104104
golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
105105
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
106106
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
107-
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
108-
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
109-
golang.org/x/tools v0.32.0 h1:Q7N1vhpkQv7ybVzLFtTjvQya2ewbwNDZzUgfXGqtMWU=
110-
golang.org/x/tools v0.32.0/go.mod h1:ZxrU41P/wAbZD8EDa6dDCa6XfpkhJ7HFMjHJXfBDu8s=
107+
golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
108+
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
109+
golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc=
110+
golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI=
111111
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
112112
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A=
113113
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU=

0 commit comments

Comments
 (0)