forked from AdguardTeam/dnsproxy
/
server_dnscrypt.go
88 lines (70 loc) · 2.28 KB
/
server_dnscrypt.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package proxy
import (
"fmt"
"net"
"github.com/AdguardTeam/golibs/errors"
"github.com/AdguardTeam/golibs/log"
"github.com/ameshkov/dnscrypt/v2"
"github.com/miekg/dns"
)
func (p *Proxy) createDNSCryptListeners() (err error) {
if len(p.DNSCryptUDPListenAddr) == 0 && len(p.DNSCryptTCPListenAddr) == 0 {
// Do nothing if DNSCrypt listen addresses are not specified.
return nil
}
if p.DNSCryptResolverCert == nil || p.DNSCryptProviderName == "" {
return errors.Error("invalid DNSCrypt configuration: no certificate or provider name")
}
log.Info("Initializing DNSCrypt: %s", p.DNSCryptProviderName)
p.dnsCryptServer = &dnscrypt.Server{
ProviderName: p.DNSCryptProviderName,
ResolverCert: p.DNSCryptResolverCert,
Handler: &dnsCryptHandler{
proxy: p,
requestGoroutinesSema: p.requestGoroutinesSema,
},
}
for _, a := range p.DNSCryptUDPListenAddr {
log.Info("Creating a DNSCrypt UDP listener")
udpListen, err := net.ListenUDP("udp", a)
if err != nil {
return err
}
p.dnsCryptUDPListen = append(p.dnsCryptUDPListen, udpListen)
log.Info("Listening for DNSCrypt messages on udp://%s", udpListen.LocalAddr())
}
for _, a := range p.DNSCryptTCPListenAddr {
log.Info("Creating a DNSCrypt TCP listener")
tcpListen, err := net.ListenTCP("tcp", a)
if err != nil {
return fmt.Errorf("listening to dnscrypt tcp socket: %w", err)
}
p.dnsCryptTCPListen = append(p.dnsCryptTCPListen, tcpListen)
log.Info("Listening for DNSCrypt messages on tcp://%s", tcpListen.Addr())
}
return nil
}
// dnsCryptHandler - dnscrypt.Handler implementation
type dnsCryptHandler struct {
proxy *Proxy
requestGoroutinesSema semaphore
}
// compile-time type check
var _ dnscrypt.Handler = &dnsCryptHandler{}
// ServeDNS - processes the DNS query
func (h *dnsCryptHandler) ServeDNS(rw dnscrypt.ResponseWriter, req *dns.Msg) error {
d := h.proxy.newDNSContext(ProtoDNSCrypt, req)
d.Addr = rw.RemoteAddr()
d.DNSCryptResponseWriter = rw
h.requestGoroutinesSema.acquire()
defer h.requestGoroutinesSema.release()
return h.proxy.handleDNSRequest(d)
}
// Writes a response to the UDP client
func (p *Proxy) respondDNSCrypt(d *DNSContext) error {
if d.Res == nil {
// If no response has been written, do nothing and let it drop
return nil
}
return d.DNSCryptResponseWriter.WriteMsg(d.Res)
}