Pull request: all: add dnscrypt support
Merge in DNS/adguard-home from 1361-dnscrypt to master Closes #1361. Squashed commit of the following: commit 31b780c16cc6b68336b95275f62381cee2e822a2 Merge: c2ce98aaf9b963fc77Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Mon Dec 7 17:48:41 2020 +0300 Merge branch 'master' into 1361-dnscrypt commit c2ce98aaf24bd5ed5b5cd7da86aae093866ab34e Merge: 3bf3d7b9663e513e33Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Fri Dec 4 19:32:40 2020 +0300 Merge branch 'master' into 1361-dnscrypt commit 3bf3d7b96530c86b54545462390562ebedc616b2 Merge: 5de4519964134220c5Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Thu Dec 3 17:31:59 2020 +0300 Merge branch 'master' into 1361-dnscrypt commit 5de451996d48ab3792ce78291068f72785303494 Merge: 60d7976f7ab8defdb0Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Wed Dec 2 19:07:56 2020 +0300 Merge branch 'master' into 1361-dnscrypt commit 60d7976f7c7ad0316751b92477a31f882c1e3134 Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Mon Nov 30 19:11:14 2020 +0300 all: add dnscrypt support
This commit is contained in:
@@ -15,6 +15,7 @@ import (
|
||||
"github.com/AdguardTeam/dnsproxy/proxy"
|
||||
"github.com/AdguardTeam/dnsproxy/upstream"
|
||||
"github.com/AdguardTeam/golibs/log"
|
||||
"github.com/ameshkov/dnscrypt/v2"
|
||||
)
|
||||
|
||||
// FilteringConfig represents the DNS filtering configuration of AdGuard Home
|
||||
@@ -114,6 +115,15 @@ type TLSConfig struct {
|
||||
dnsNames []string
|
||||
}
|
||||
|
||||
// DNSCryptConfig is the DNSCrypt server configuration struct.
|
||||
type DNSCryptConfig struct {
|
||||
UDPListenAddr *net.UDPAddr
|
||||
TCPListenAddr *net.TCPAddr
|
||||
ProviderName string
|
||||
ResolverCert *dnscrypt.Cert
|
||||
Enabled bool
|
||||
}
|
||||
|
||||
// ServerConfig represents server configuration.
|
||||
// The zero ServerConfig is empty and ready for use.
|
||||
type ServerConfig struct {
|
||||
@@ -124,6 +134,7 @@ type ServerConfig struct {
|
||||
|
||||
FilteringConfig
|
||||
TLSConfig
|
||||
DNSCryptConfig
|
||||
TLSAllowUnencryptedDOH bool
|
||||
|
||||
TLSv12Roots *x509.CertPool // list of root CAs for TLSv1.2
|
||||
@@ -189,6 +200,13 @@ func (s *Server) createProxyConfig() (proxy.Config, error) {
|
||||
return proxyConfig, err
|
||||
}
|
||||
|
||||
if s.conf.DNSCryptConfig.Enabled {
|
||||
proxyConfig.DNSCryptUDPListenAddr = []*net.UDPAddr{s.conf.DNSCryptConfig.UDPListenAddr}
|
||||
proxyConfig.DNSCryptTCPListenAddr = []*net.TCPAddr{s.conf.DNSCryptConfig.TCPListenAddr}
|
||||
proxyConfig.DNSCryptProviderName = s.conf.DNSCryptConfig.ProviderName
|
||||
proxyConfig.DNSCryptResolverCert = s.conf.DNSCryptConfig.ResolverCert
|
||||
}
|
||||
|
||||
// Validate proxy config
|
||||
if proxyConfig.UpstreamConfig == nil || len(proxyConfig.UpstreamConfig.Upstreams) == 0 {
|
||||
return proxyConfig, errors.New("no default upstream servers configured")
|
||||
|
||||
@@ -99,6 +99,16 @@ type tlsConfigSettings struct {
|
||||
PortDNSOverTLS int `yaml:"port_dns_over_tls" json:"port_dns_over_tls,omitempty"` // DNS-over-TLS port. If 0, DOT will be disabled
|
||||
PortDNSOverQUIC uint16 `yaml:"port_dns_over_quic" json:"port_dns_over_quic,omitempty"` // DNS-over-QUIC port. If 0, DoQ will be disabled
|
||||
|
||||
// PortDNSCrypt is the port for DNSCrypt requests. If it's zero,
|
||||
// DNSCrypt is disabled.
|
||||
PortDNSCrypt int `yaml:"port_dnscrypt" json:"port_dnscrypt"`
|
||||
// DNSCryptConfigFile is the path to the DNSCrypt config file. Must be
|
||||
// set if PortDNSCrypt is not zero.
|
||||
//
|
||||
// See https://github.com/AdguardTeam/dnsproxy and
|
||||
// https://github.com/ameshkov/dnscrypt.
|
||||
DNSCryptConfigFile string `yaml:"dnscrypt_config_file" json:"dnscrypt_config_file"`
|
||||
|
||||
// Allow DOH queries via unencrypted HTTP (e.g. for reverse proxying)
|
||||
AllowUnencryptedDOH bool `yaml:"allow_unencrypted_doh" json:"allow_unencrypted_doh"`
|
||||
|
||||
|
||||
@@ -3,8 +3,10 @@ package home
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/agherr"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/dnsfilter"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/dnsforward"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/querylog"
|
||||
@@ -12,6 +14,8 @@ import (
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/util"
|
||||
"github.com/AdguardTeam/dnsproxy/proxy"
|
||||
"github.com/AdguardTeam/golibs/log"
|
||||
"github.com/ameshkov/dnscrypt/v2"
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
// Called by other modules when configuration is changed
|
||||
@@ -70,7 +74,12 @@ func initDNSServer() error {
|
||||
}
|
||||
Context.dnsServer = dnsforward.NewServer(p)
|
||||
Context.clients.dnsServer = Context.dnsServer
|
||||
dnsConfig := generateServerConfig()
|
||||
dnsConfig, err := generateServerConfig()
|
||||
if err != nil {
|
||||
closeDNSServer()
|
||||
return fmt.Errorf("generateServerConfig: %w", err)
|
||||
}
|
||||
|
||||
err = Context.dnsServer.Prepare(&dnsConfig)
|
||||
if err != nil {
|
||||
closeDNSServer()
|
||||
@@ -104,10 +113,11 @@ func onDNSRequest(d *proxy.DNSContext) {
|
||||
}
|
||||
}
|
||||
|
||||
func generateServerConfig() dnsforward.ServerConfig {
|
||||
newconfig := dnsforward.ServerConfig{
|
||||
UDPListenAddr: &net.UDPAddr{IP: net.ParseIP(config.DNS.BindHost), Port: config.DNS.Port},
|
||||
TCPListenAddr: &net.TCPAddr{IP: net.ParseIP(config.DNS.BindHost), Port: config.DNS.Port},
|
||||
func generateServerConfig() (newconfig dnsforward.ServerConfig, err error) {
|
||||
bindHost := net.ParseIP(config.DNS.BindHost)
|
||||
newconfig = dnsforward.ServerConfig{
|
||||
UDPListenAddr: &net.UDPAddr{IP: bindHost, Port: config.DNS.Port},
|
||||
TCPListenAddr: &net.TCPAddr{IP: bindHost, Port: config.DNS.Port},
|
||||
FilteringConfig: config.DNS.FilteringConfig,
|
||||
ConfigModified: onConfigModified,
|
||||
HTTPRegister: httpRegister,
|
||||
@@ -121,25 +131,76 @@ func generateServerConfig() dnsforward.ServerConfig {
|
||||
|
||||
if tlsConf.PortDNSOverTLS != 0 {
|
||||
newconfig.TLSListenAddr = &net.TCPAddr{
|
||||
IP: net.ParseIP(config.DNS.BindHost),
|
||||
IP: bindHost,
|
||||
Port: tlsConf.PortDNSOverTLS,
|
||||
}
|
||||
}
|
||||
|
||||
if tlsConf.PortDNSOverQUIC != 0 {
|
||||
newconfig.QUICListenAddr = &net.UDPAddr{
|
||||
IP: net.ParseIP(config.DNS.BindHost),
|
||||
IP: bindHost,
|
||||
Port: int(tlsConf.PortDNSOverQUIC),
|
||||
}
|
||||
}
|
||||
|
||||
if tlsConf.PortDNSCrypt != 0 {
|
||||
newconfig.DNSCryptConfig, err = newDNSCrypt(bindHost, tlsConf)
|
||||
if err != nil {
|
||||
// Don't wrap the error, because it's already
|
||||
// wrapped by newDNSCrypt.
|
||||
return dnsforward.ServerConfig{}, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
newconfig.TLSv12Roots = Context.tlsRoots
|
||||
newconfig.TLSCiphers = Context.tlsCiphers
|
||||
newconfig.TLSAllowUnencryptedDOH = tlsConf.AllowUnencryptedDOH
|
||||
|
||||
newconfig.FilterHandler = applyAdditionalFiltering
|
||||
newconfig.GetCustomUpstreamByClient = Context.clients.FindUpstreams
|
||||
return newconfig
|
||||
|
||||
return newconfig, nil
|
||||
}
|
||||
|
||||
func newDNSCrypt(bindHost net.IP, tlsConf tlsConfigSettings) (dnscc dnsforward.DNSCryptConfig, err error) {
|
||||
if tlsConf.DNSCryptConfigFile == "" {
|
||||
return dnscc, agherr.Error("no dnscrypt_config_file")
|
||||
}
|
||||
|
||||
f, err := os.Open(tlsConf.DNSCryptConfigFile)
|
||||
if err != nil {
|
||||
return dnscc, fmt.Errorf("opening dnscrypt config: %w", err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
rc := &dnscrypt.ResolverConfig{}
|
||||
err = yaml.NewDecoder(f).Decode(rc)
|
||||
if err != nil {
|
||||
return dnscc, fmt.Errorf("decoding dnscrypt config: %w", err)
|
||||
}
|
||||
|
||||
cert, err := rc.CreateCert()
|
||||
if err != nil {
|
||||
return dnscc, fmt.Errorf("creating dnscrypt cert: %w", err)
|
||||
}
|
||||
|
||||
udpAddr := &net.UDPAddr{
|
||||
IP: bindHost,
|
||||
Port: tlsConf.PortDNSCrypt,
|
||||
}
|
||||
tcpAddr := &net.TCPAddr{
|
||||
IP: bindHost,
|
||||
Port: tlsConf.PortDNSCrypt,
|
||||
}
|
||||
|
||||
return dnsforward.DNSCryptConfig{
|
||||
UDPListenAddr: udpAddr,
|
||||
TCPListenAddr: tcpAddr,
|
||||
ResolverCert: cert,
|
||||
ProviderName: rc.ProviderName,
|
||||
Enabled: true,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type dnsEncryption struct {
|
||||
@@ -281,11 +342,16 @@ func startDNSServer() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func reconfigureDNSServer() error {
|
||||
newconfig := generateServerConfig()
|
||||
err := Context.dnsServer.Reconfigure(&newconfig)
|
||||
func reconfigureDNSServer() (err error) {
|
||||
var newconfig dnsforward.ServerConfig
|
||||
newconfig, err = generateServerConfig()
|
||||
if err != nil {
|
||||
return fmt.Errorf("couldn't start forwarding DNS server: %w", err)
|
||||
return fmt.Errorf("generating forwarding dns server config: %w", err)
|
||||
}
|
||||
|
||||
err = Context.dnsServer.Reconfigure(&newconfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("starting forwarding dns server: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
Reference in New Issue
Block a user