Pull request: all: support multiple dns hosts
Updates #1401. Squashed commit of the following: commit a18c3f062a88ad7d7fbfacaedb893f1ca660b6dc Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Mon Mar 22 21:55:26 2021 +0300 home: imp code commit 2b4a28cbf379fbc5fb168af6d8d078cab2b8bd64 Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Mon Mar 22 20:55:08 2021 +0300 all: rm unused field commit 5766a97dafff4acff6b909eb6303459f7991c81e Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Mon Mar 22 16:40:14 2021 +0300 all: support multiple dns hosts
This commit is contained in:
parent
3b2f5d7842
commit
5d0d32b926
|
@ -15,6 +15,7 @@ and this project adheres to
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
- The ability to serve DNS queries on multiple hosts and interfaces ([#1401]).
|
||||||
- `ips` and `text` DHCP server options ([#2385]).
|
- `ips` and `text` DHCP server options ([#2385]).
|
||||||
- `SRV` records support in `$dnsrewrite` filters ([#2533]).
|
- `SRV` records support in `$dnsrewrite` filters ([#2533]).
|
||||||
|
|
||||||
|
@ -38,6 +39,7 @@ and this project adheres to
|
||||||
|
|
||||||
- Go 1.14 support.
|
- Go 1.14 support.
|
||||||
|
|
||||||
|
[#1401]: https://github.com/AdguardTeam/AdGuardHome/issues/1401
|
||||||
[#2385]: https://github.com/AdguardTeam/AdGuardHome/issues/2385
|
[#2385]: https://github.com/AdguardTeam/AdGuardHome/issues/2385
|
||||||
[#2412]: https://github.com/AdguardTeam/AdGuardHome/issues/2412
|
[#2412]: https://github.com/AdguardTeam/AdGuardHome/issues/2412
|
||||||
[#2498]: https://github.com/AdguardTeam/AdGuardHome/issues/2498
|
[#2498]: https://github.com/AdguardTeam/AdGuardHome/issues/2498
|
||||||
|
|
|
@ -50,10 +50,9 @@ type Resolver interface {
|
||||||
|
|
||||||
// Config allows you to configure DNS filtering with New() or just change variables directly.
|
// Config allows you to configure DNS filtering with New() or just change variables directly.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
ParentalEnabled bool `yaml:"parental_enabled"`
|
ParentalEnabled bool `yaml:"parental_enabled"`
|
||||||
SafeSearchEnabled bool `yaml:"safesearch_enabled"`
|
SafeSearchEnabled bool `yaml:"safesearch_enabled"`
|
||||||
SafeBrowsingEnabled bool `yaml:"safebrowsing_enabled"`
|
SafeBrowsingEnabled bool `yaml:"safebrowsing_enabled"`
|
||||||
ResolverAddress string `yaml:"-"` // DNS server address
|
|
||||||
|
|
||||||
SafeBrowsingCacheSize uint `yaml:"safebrowsing_cache_size"` // (in bytes)
|
SafeBrowsingCacheSize uint `yaml:"safebrowsing_cache_size"` // (in bytes)
|
||||||
SafeSearchCacheSize uint `yaml:"safesearch_cache_size"` // (in bytes)
|
SafeSearchCacheSize uint `yaml:"safesearch_cache_size"` // (in bytes)
|
||||||
|
|
|
@ -93,8 +93,8 @@ type FilteringConfig struct {
|
||||||
|
|
||||||
// TLSConfig is the TLS configuration for HTTPS, DNS-over-HTTPS, and DNS-over-TLS
|
// TLSConfig is the TLS configuration for HTTPS, DNS-over-HTTPS, and DNS-over-TLS
|
||||||
type TLSConfig struct {
|
type TLSConfig struct {
|
||||||
TLSListenAddr *net.TCPAddr `yaml:"-" json:"-"`
|
TLSListenAddrs []*net.TCPAddr `yaml:"-" json:"-"`
|
||||||
QUICListenAddr *net.UDPAddr `yaml:"-" json:"-"`
|
QUICListenAddrs []*net.UDPAddr `yaml:"-" json:"-"`
|
||||||
|
|
||||||
// Reject connection if the client uses server name (in SNI) that doesn't match the certificate
|
// Reject connection if the client uses server name (in SNI) that doesn't match the certificate
|
||||||
StrictSNICheck bool `yaml:"strict_sni_check" json:"-"`
|
StrictSNICheck bool `yaml:"strict_sni_check" json:"-"`
|
||||||
|
@ -121,18 +121,18 @@ type TLSConfig struct {
|
||||||
|
|
||||||
// DNSCryptConfig is the DNSCrypt server configuration struct.
|
// DNSCryptConfig is the DNSCrypt server configuration struct.
|
||||||
type DNSCryptConfig struct {
|
type DNSCryptConfig struct {
|
||||||
UDPListenAddr *net.UDPAddr
|
UDPListenAddrs []*net.UDPAddr
|
||||||
TCPListenAddr *net.TCPAddr
|
TCPListenAddrs []*net.TCPAddr
|
||||||
ProviderName string
|
ProviderName string
|
||||||
ResolverCert *dnscrypt.Cert
|
ResolverCert *dnscrypt.Cert
|
||||||
Enabled bool
|
Enabled bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServerConfig represents server configuration.
|
// ServerConfig represents server configuration.
|
||||||
// The zero ServerConfig is empty and ready for use.
|
// The zero ServerConfig is empty and ready for use.
|
||||||
type ServerConfig struct {
|
type ServerConfig struct {
|
||||||
UDPListenAddr *net.UDPAddr // UDP listen address
|
UDPListenAddrs []*net.UDPAddr // UDP listen address
|
||||||
TCPListenAddr *net.TCPAddr // TCP listen address
|
TCPListenAddrs []*net.TCPAddr // TCP listen address
|
||||||
UpstreamConfig *proxy.UpstreamConfig // Upstream DNS servers config
|
UpstreamConfig *proxy.UpstreamConfig // Upstream DNS servers config
|
||||||
OnDNSRequest func(d *proxy.DNSContext)
|
OnDNSRequest func(d *proxy.DNSContext)
|
||||||
|
|
||||||
|
@ -153,16 +153,16 @@ type ServerConfig struct {
|
||||||
|
|
||||||
// if any of ServerConfig values are zero, then default values from below are used
|
// if any of ServerConfig values are zero, then default values from below are used
|
||||||
var defaultValues = ServerConfig{
|
var defaultValues = ServerConfig{
|
||||||
UDPListenAddr: &net.UDPAddr{Port: 53},
|
UDPListenAddrs: []*net.UDPAddr{{Port: 53}},
|
||||||
TCPListenAddr: &net.TCPAddr{Port: 53},
|
TCPListenAddrs: []*net.TCPAddr{{Port: 53}},
|
||||||
FilteringConfig: FilteringConfig{BlockedResponseTTL: 3600},
|
FilteringConfig: FilteringConfig{BlockedResponseTTL: 3600},
|
||||||
}
|
}
|
||||||
|
|
||||||
// createProxyConfig creates and validates configuration for the main proxy
|
// createProxyConfig creates and validates configuration for the main proxy
|
||||||
func (s *Server) createProxyConfig() (proxy.Config, error) {
|
func (s *Server) createProxyConfig() (proxy.Config, error) {
|
||||||
proxyConfig := proxy.Config{
|
proxyConfig := proxy.Config{
|
||||||
UDPListenAddr: []*net.UDPAddr{s.conf.UDPListenAddr},
|
UDPListenAddr: s.conf.UDPListenAddrs,
|
||||||
TCPListenAddr: []*net.TCPAddr{s.conf.TCPListenAddr},
|
TCPListenAddr: s.conf.TCPListenAddrs,
|
||||||
Ratelimit: int(s.conf.Ratelimit),
|
Ratelimit: int(s.conf.Ratelimit),
|
||||||
RatelimitWhitelist: s.conf.RatelimitWhitelist,
|
RatelimitWhitelist: s.conf.RatelimitWhitelist,
|
||||||
RefuseAny: s.conf.RefuseAny,
|
RefuseAny: s.conf.RefuseAny,
|
||||||
|
@ -205,8 +205,8 @@ func (s *Server) createProxyConfig() (proxy.Config, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.conf.DNSCryptConfig.Enabled {
|
if s.conf.DNSCryptConfig.Enabled {
|
||||||
proxyConfig.DNSCryptUDPListenAddr = []*net.UDPAddr{s.conf.DNSCryptConfig.UDPListenAddr}
|
proxyConfig.DNSCryptUDPListenAddr = s.conf.DNSCryptConfig.UDPListenAddrs
|
||||||
proxyConfig.DNSCryptTCPListenAddr = []*net.TCPAddr{s.conf.DNSCryptConfig.TCPListenAddr}
|
proxyConfig.DNSCryptTCPListenAddr = s.conf.DNSCryptConfig.TCPListenAddrs
|
||||||
proxyConfig.DNSCryptProviderName = s.conf.DNSCryptConfig.ProviderName
|
proxyConfig.DNSCryptProviderName = s.conf.DNSCryptConfig.ProviderName
|
||||||
proxyConfig.DNSCryptResolverCert = s.conf.DNSCryptConfig.ResolverCert
|
proxyConfig.DNSCryptResolverCert = s.conf.DNSCryptConfig.ResolverCert
|
||||||
}
|
}
|
||||||
|
@ -225,21 +225,27 @@ func (s *Server) initDefaultSettings() {
|
||||||
if len(s.conf.UpstreamDNS) == 0 {
|
if len(s.conf.UpstreamDNS) == 0 {
|
||||||
s.conf.UpstreamDNS = defaultDNS
|
s.conf.UpstreamDNS = defaultDNS
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(s.conf.BootstrapDNS) == 0 {
|
if len(s.conf.BootstrapDNS) == 0 {
|
||||||
s.conf.BootstrapDNS = defaultBootstrap
|
s.conf.BootstrapDNS = defaultBootstrap
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(s.conf.ParentalBlockHost) == 0 {
|
if len(s.conf.ParentalBlockHost) == 0 {
|
||||||
s.conf.ParentalBlockHost = parentalBlockHost
|
s.conf.ParentalBlockHost = parentalBlockHost
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(s.conf.SafeBrowsingBlockHost) == 0 {
|
if len(s.conf.SafeBrowsingBlockHost) == 0 {
|
||||||
s.conf.SafeBrowsingBlockHost = safeBrowsingBlockHost
|
s.conf.SafeBrowsingBlockHost = safeBrowsingBlockHost
|
||||||
}
|
}
|
||||||
if s.conf.UDPListenAddr == nil {
|
|
||||||
s.conf.UDPListenAddr = defaultValues.UDPListenAddr
|
if s.conf.UDPListenAddrs == nil {
|
||||||
|
s.conf.UDPListenAddrs = defaultValues.UDPListenAddrs
|
||||||
}
|
}
|
||||||
if s.conf.TCPListenAddr == nil {
|
|
||||||
s.conf.TCPListenAddr = defaultValues.TCPListenAddr
|
if s.conf.TCPListenAddrs == nil {
|
||||||
|
s.conf.TCPListenAddrs = defaultValues.TCPListenAddrs
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(s.conf.BlockedHosts) == 0 {
|
if len(s.conf.BlockedHosts) == 0 {
|
||||||
s.conf.BlockedHosts = defaultBlockedHosts
|
s.conf.BlockedHosts = defaultBlockedHosts
|
||||||
}
|
}
|
||||||
|
@ -325,17 +331,16 @@ func (s *Server) prepareTLS(proxyConfig *proxy.Config) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.conf.TLSListenAddr == nil &&
|
if s.conf.TLSListenAddrs == nil && s.conf.QUICListenAddrs == nil {
|
||||||
s.conf.QUICListenAddr == nil {
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.conf.TLSListenAddr != nil {
|
if s.conf.TLSListenAddrs != nil {
|
||||||
proxyConfig.TLSListenAddr = []*net.TCPAddr{s.conf.TLSListenAddr}
|
proxyConfig.TLSListenAddr = s.conf.TLSListenAddrs
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.conf.QUICListenAddr != nil {
|
if s.conf.QUICListenAddrs != nil {
|
||||||
proxyConfig.QUICListenAddr = []*net.UDPAddr{s.conf.QUICListenAddr}
|
proxyConfig.QUICListenAddr = s.conf.QUICListenAddrs
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
|
|
|
@ -123,8 +123,8 @@ func createTestTLS(t *testing.T, tlsConf TLSConfig) (s *Server, certPem []byte)
|
||||||
_, certPem, keyPem = createServerTLSConfig(t)
|
_, certPem, keyPem = createServerTLSConfig(t)
|
||||||
|
|
||||||
s = createTestServer(t, &dnsfilter.Config{}, ServerConfig{
|
s = createTestServer(t, &dnsfilter.Config{}, ServerConfig{
|
||||||
UDPListenAddr: &net.UDPAddr{},
|
UDPListenAddrs: []*net.UDPAddr{{}},
|
||||||
TCPListenAddr: &net.TCPAddr{},
|
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||||
})
|
})
|
||||||
|
|
||||||
tlsConf.CertificateChainData, tlsConf.PrivateKeyData = certPem, keyPem
|
tlsConf.CertificateChainData, tlsConf.PrivateKeyData = certPem, keyPem
|
||||||
|
@ -219,8 +219,8 @@ func sendTestMessages(t *testing.T, conn *dns.Conn) {
|
||||||
|
|
||||||
func TestServer(t *testing.T) {
|
func TestServer(t *testing.T) {
|
||||||
s := createTestServer(t, &dnsfilter.Config{}, ServerConfig{
|
s := createTestServer(t, &dnsfilter.Config{}, ServerConfig{
|
||||||
UDPListenAddr: &net.UDPAddr{},
|
UDPListenAddrs: []*net.UDPAddr{{}},
|
||||||
TCPListenAddr: &net.TCPAddr{},
|
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||||
})
|
})
|
||||||
s.conf.UpstreamConfig.Upstreams = []upstream.Upstream{
|
s.conf.UpstreamConfig.Upstreams = []upstream.Upstream{
|
||||||
&aghtest.TestUpstream{
|
&aghtest.TestUpstream{
|
||||||
|
@ -257,8 +257,8 @@ func TestServer(t *testing.T) {
|
||||||
|
|
||||||
func TestServerWithProtectionDisabled(t *testing.T) {
|
func TestServerWithProtectionDisabled(t *testing.T) {
|
||||||
s := createTestServer(t, &dnsfilter.Config{}, ServerConfig{
|
s := createTestServer(t, &dnsfilter.Config{}, ServerConfig{
|
||||||
UDPListenAddr: &net.UDPAddr{},
|
UDPListenAddrs: []*net.UDPAddr{{}},
|
||||||
TCPListenAddr: &net.TCPAddr{},
|
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||||
})
|
})
|
||||||
s.conf.UpstreamConfig.Upstreams = []upstream.Upstream{
|
s.conf.UpstreamConfig.Upstreams = []upstream.Upstream{
|
||||||
&aghtest.TestUpstream{
|
&aghtest.TestUpstream{
|
||||||
|
@ -281,7 +281,7 @@ func TestServerWithProtectionDisabled(t *testing.T) {
|
||||||
|
|
||||||
func TestDoTServer(t *testing.T) {
|
func TestDoTServer(t *testing.T) {
|
||||||
s, certPem := createTestTLS(t, TLSConfig{
|
s, certPem := createTestTLS(t, TLSConfig{
|
||||||
TLSListenAddr: &net.TCPAddr{},
|
TLSListenAddrs: []*net.TCPAddr{{}},
|
||||||
})
|
})
|
||||||
s.conf.UpstreamConfig.Upstreams = []upstream.Upstream{
|
s.conf.UpstreamConfig.Upstreams = []upstream.Upstream{
|
||||||
&aghtest.TestUpstream{
|
&aghtest.TestUpstream{
|
||||||
|
@ -311,7 +311,7 @@ func TestDoTServer(t *testing.T) {
|
||||||
|
|
||||||
func TestDoQServer(t *testing.T) {
|
func TestDoQServer(t *testing.T) {
|
||||||
s, _ := createTestTLS(t, TLSConfig{
|
s, _ := createTestTLS(t, TLSConfig{
|
||||||
QUICListenAddr: &net.UDPAddr{},
|
QUICListenAddrs: []*net.UDPAddr{{}},
|
||||||
})
|
})
|
||||||
s.conf.UpstreamConfig.Upstreams = []upstream.Upstream{
|
s.conf.UpstreamConfig.Upstreams = []upstream.Upstream{
|
||||||
&aghtest.TestUpstream{
|
&aghtest.TestUpstream{
|
||||||
|
@ -348,8 +348,8 @@ func TestServerRace(t *testing.T) {
|
||||||
CacheTime: 30,
|
CacheTime: 30,
|
||||||
}
|
}
|
||||||
forwardConf := ServerConfig{
|
forwardConf := ServerConfig{
|
||||||
UDPListenAddr: &net.UDPAddr{},
|
UDPListenAddrs: []*net.UDPAddr{{}},
|
||||||
TCPListenAddr: &net.TCPAddr{},
|
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||||
FilteringConfig: FilteringConfig{
|
FilteringConfig: FilteringConfig{
|
||||||
ProtectionEnabled: true,
|
ProtectionEnabled: true,
|
||||||
UpstreamDNS: []string{"8.8.8.8:53", "8.8.4.4:53"},
|
UpstreamDNS: []string{"8.8.8.8:53", "8.8.4.4:53"},
|
||||||
|
@ -383,8 +383,8 @@ func TestSafeSearch(t *testing.T) {
|
||||||
CustomResolver: resolver,
|
CustomResolver: resolver,
|
||||||
}
|
}
|
||||||
forwardConf := ServerConfig{
|
forwardConf := ServerConfig{
|
||||||
UDPListenAddr: &net.UDPAddr{},
|
UDPListenAddrs: []*net.UDPAddr{{}},
|
||||||
TCPListenAddr: &net.TCPAddr{},
|
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||||
FilteringConfig: FilteringConfig{
|
FilteringConfig: FilteringConfig{
|
||||||
ProtectionEnabled: true,
|
ProtectionEnabled: true,
|
||||||
},
|
},
|
||||||
|
@ -440,8 +440,8 @@ func TestSafeSearch(t *testing.T) {
|
||||||
|
|
||||||
func TestInvalidRequest(t *testing.T) {
|
func TestInvalidRequest(t *testing.T) {
|
||||||
s := createTestServer(t, &dnsfilter.Config{}, ServerConfig{
|
s := createTestServer(t, &dnsfilter.Config{}, ServerConfig{
|
||||||
UDPListenAddr: &net.UDPAddr{},
|
UDPListenAddrs: []*net.UDPAddr{{}},
|
||||||
TCPListenAddr: &net.TCPAddr{},
|
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||||
})
|
})
|
||||||
startDeferStop(t, s)
|
startDeferStop(t, s)
|
||||||
|
|
||||||
|
@ -464,8 +464,8 @@ func TestInvalidRequest(t *testing.T) {
|
||||||
|
|
||||||
func TestBlockedRequest(t *testing.T) {
|
func TestBlockedRequest(t *testing.T) {
|
||||||
forwardConf := ServerConfig{
|
forwardConf := ServerConfig{
|
||||||
UDPListenAddr: &net.UDPAddr{},
|
UDPListenAddrs: []*net.UDPAddr{{}},
|
||||||
TCPListenAddr: &net.TCPAddr{},
|
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||||
FilteringConfig: FilteringConfig{
|
FilteringConfig: FilteringConfig{
|
||||||
ProtectionEnabled: true,
|
ProtectionEnabled: true,
|
||||||
},
|
},
|
||||||
|
@ -488,8 +488,8 @@ func TestBlockedRequest(t *testing.T) {
|
||||||
|
|
||||||
func TestServerCustomClientUpstream(t *testing.T) {
|
func TestServerCustomClientUpstream(t *testing.T) {
|
||||||
forwardConf := ServerConfig{
|
forwardConf := ServerConfig{
|
||||||
UDPListenAddr: &net.UDPAddr{},
|
UDPListenAddrs: []*net.UDPAddr{{}},
|
||||||
TCPListenAddr: &net.TCPAddr{},
|
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||||
FilteringConfig: FilteringConfig{
|
FilteringConfig: FilteringConfig{
|
||||||
ProtectionEnabled: true,
|
ProtectionEnabled: true,
|
||||||
},
|
},
|
||||||
|
@ -537,8 +537,8 @@ var testIPv4 = map[string][]net.IP{
|
||||||
|
|
||||||
func TestBlockCNAMEProtectionEnabled(t *testing.T) {
|
func TestBlockCNAMEProtectionEnabled(t *testing.T) {
|
||||||
s := createTestServer(t, &dnsfilter.Config{}, ServerConfig{
|
s := createTestServer(t, &dnsfilter.Config{}, ServerConfig{
|
||||||
UDPListenAddr: &net.UDPAddr{},
|
UDPListenAddrs: []*net.UDPAddr{{}},
|
||||||
TCPListenAddr: &net.TCPAddr{},
|
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||||
})
|
})
|
||||||
testUpstm := &aghtest.TestUpstream{
|
testUpstm := &aghtest.TestUpstream{
|
||||||
CName: testCNAMEs,
|
CName: testCNAMEs,
|
||||||
|
@ -564,8 +564,8 @@ func TestBlockCNAMEProtectionEnabled(t *testing.T) {
|
||||||
|
|
||||||
func TestBlockCNAME(t *testing.T) {
|
func TestBlockCNAME(t *testing.T) {
|
||||||
forwardConf := ServerConfig{
|
forwardConf := ServerConfig{
|
||||||
UDPListenAddr: &net.UDPAddr{},
|
UDPListenAddrs: []*net.UDPAddr{{}},
|
||||||
TCPListenAddr: &net.TCPAddr{},
|
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||||
FilteringConfig: FilteringConfig{
|
FilteringConfig: FilteringConfig{
|
||||||
ProtectionEnabled: true,
|
ProtectionEnabled: true,
|
||||||
},
|
},
|
||||||
|
@ -622,8 +622,8 @@ func TestBlockCNAME(t *testing.T) {
|
||||||
|
|
||||||
func TestClientRulesForCNAMEMatching(t *testing.T) {
|
func TestClientRulesForCNAMEMatching(t *testing.T) {
|
||||||
forwardConf := ServerConfig{
|
forwardConf := ServerConfig{
|
||||||
UDPListenAddr: &net.UDPAddr{},
|
UDPListenAddrs: []*net.UDPAddr{{}},
|
||||||
TCPListenAddr: &net.TCPAddr{},
|
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||||
FilteringConfig: FilteringConfig{
|
FilteringConfig: FilteringConfig{
|
||||||
ProtectionEnabled: true,
|
ProtectionEnabled: true,
|
||||||
FilterHandler: func(_ net.IP, _ string, settings *dnsfilter.RequestFilteringSettings) {
|
FilterHandler: func(_ net.IP, _ string, settings *dnsfilter.RequestFilteringSettings) {
|
||||||
|
@ -664,8 +664,8 @@ func TestClientRulesForCNAMEMatching(t *testing.T) {
|
||||||
|
|
||||||
func TestNullBlockedRequest(t *testing.T) {
|
func TestNullBlockedRequest(t *testing.T) {
|
||||||
forwardConf := ServerConfig{
|
forwardConf := ServerConfig{
|
||||||
UDPListenAddr: &net.UDPAddr{},
|
UDPListenAddrs: []*net.UDPAddr{{}},
|
||||||
TCPListenAddr: &net.TCPAddr{},
|
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||||
FilteringConfig: FilteringConfig{
|
FilteringConfig: FilteringConfig{
|
||||||
ProtectionEnabled: true,
|
ProtectionEnabled: true,
|
||||||
BlockingMode: "null_ip",
|
BlockingMode: "null_ip",
|
||||||
|
@ -707,8 +707,8 @@ func TestBlockedCustomIP(t *testing.T) {
|
||||||
DNSFilter: dnsfilter.New(&dnsfilter.Config{}, filters),
|
DNSFilter: dnsfilter.New(&dnsfilter.Config{}, filters),
|
||||||
})
|
})
|
||||||
conf := &ServerConfig{
|
conf := &ServerConfig{
|
||||||
UDPListenAddr: &net.UDPAddr{},
|
UDPListenAddrs: []*net.UDPAddr{{}},
|
||||||
TCPListenAddr: &net.TCPAddr{},
|
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||||
FilteringConfig: FilteringConfig{
|
FilteringConfig: FilteringConfig{
|
||||||
ProtectionEnabled: true,
|
ProtectionEnabled: true,
|
||||||
BlockingMode: "custom_ip",
|
BlockingMode: "custom_ip",
|
||||||
|
@ -746,8 +746,8 @@ func TestBlockedCustomIP(t *testing.T) {
|
||||||
|
|
||||||
func TestBlockedByHosts(t *testing.T) {
|
func TestBlockedByHosts(t *testing.T) {
|
||||||
forwardConf := ServerConfig{
|
forwardConf := ServerConfig{
|
||||||
UDPListenAddr: &net.UDPAddr{},
|
UDPListenAddrs: []*net.UDPAddr{{}},
|
||||||
TCPListenAddr: &net.TCPAddr{},
|
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||||
FilteringConfig: FilteringConfig{
|
FilteringConfig: FilteringConfig{
|
||||||
ProtectionEnabled: true,
|
ProtectionEnabled: true,
|
||||||
},
|
},
|
||||||
|
@ -780,8 +780,8 @@ func TestBlockedBySafeBrowsing(t *testing.T) {
|
||||||
SafeBrowsingEnabled: true,
|
SafeBrowsingEnabled: true,
|
||||||
}
|
}
|
||||||
forwardConf := ServerConfig{
|
forwardConf := ServerConfig{
|
||||||
UDPListenAddr: &net.UDPAddr{},
|
UDPListenAddrs: []*net.UDPAddr{{}},
|
||||||
TCPListenAddr: &net.TCPAddr{},
|
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||||
FilteringConfig: FilteringConfig{
|
FilteringConfig: FilteringConfig{
|
||||||
SafeBrowsingBlockHost: ans4.String(),
|
SafeBrowsingBlockHost: ans4.String(),
|
||||||
ProtectionEnabled: true,
|
ProtectionEnabled: true,
|
||||||
|
@ -824,8 +824,8 @@ func TestRewrite(t *testing.T) {
|
||||||
|
|
||||||
s := NewServer(DNSCreateParams{DNSFilter: f})
|
s := NewServer(DNSCreateParams{DNSFilter: f})
|
||||||
assert.Nil(t, s.Prepare(&ServerConfig{
|
assert.Nil(t, s.Prepare(&ServerConfig{
|
||||||
UDPListenAddr: &net.UDPAddr{},
|
UDPListenAddrs: []*net.UDPAddr{{}},
|
||||||
TCPListenAddr: &net.TCPAddr{},
|
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||||
FilteringConfig: FilteringConfig{
|
FilteringConfig: FilteringConfig{
|
||||||
ProtectionEnabled: true,
|
ProtectionEnabled: true,
|
||||||
UpstreamDNS: []string{"8.8.8.8:53"},
|
UpstreamDNS: []string{"8.8.8.8:53"},
|
||||||
|
@ -1109,8 +1109,8 @@ func TestPTRResponseFromDHCPLeases(t *testing.T) {
|
||||||
DHCPServer: &testDHCP{},
|
DHCPServer: &testDHCP{},
|
||||||
})
|
})
|
||||||
|
|
||||||
s.conf.UDPListenAddr = &net.UDPAddr{}
|
s.conf.UDPListenAddrs = []*net.UDPAddr{{}}
|
||||||
s.conf.TCPListenAddr = &net.TCPAddr{}
|
s.conf.TCPListenAddrs = []*net.TCPAddr{{}}
|
||||||
s.conf.UpstreamDNS = []string{"127.0.0.1:53"}
|
s.conf.UpstreamDNS = []string{"127.0.0.1:53"}
|
||||||
s.conf.FilteringConfig.ProtectionEnabled = true
|
s.conf.FilteringConfig.ProtectionEnabled = true
|
||||||
require.Nil(t, s.Prepare(nil))
|
require.Nil(t, s.Prepare(nil))
|
||||||
|
@ -1154,8 +1154,8 @@ func TestPTRResponseFromHosts(t *testing.T) {
|
||||||
t.Cleanup(c.AutoHosts.Close)
|
t.Cleanup(c.AutoHosts.Close)
|
||||||
|
|
||||||
s := NewServer(DNSCreateParams{DNSFilter: dnsfilter.New(&c, nil)})
|
s := NewServer(DNSCreateParams{DNSFilter: dnsfilter.New(&c, nil)})
|
||||||
s.conf.UDPListenAddr = &net.UDPAddr{}
|
s.conf.UDPListenAddrs = []*net.UDPAddr{{}}
|
||||||
s.conf.TCPListenAddr = &net.TCPAddr{}
|
s.conf.TCPListenAddrs = []*net.TCPAddr{{}}
|
||||||
s.conf.UpstreamDNS = []string{"127.0.0.1:53"}
|
s.conf.UpstreamDNS = []string{"127.0.0.1:53"}
|
||||||
s.conf.FilteringConfig.ProtectionEnabled = true
|
s.conf.FilteringConfig.ProtectionEnabled = true
|
||||||
require.Nil(t, s.Prepare(nil))
|
require.Nil(t, s.Prepare(nil))
|
||||||
|
|
|
@ -23,8 +23,8 @@ func TestDNSForwardHTTTP_handleGetConfig(t *testing.T) {
|
||||||
CacheTime: 30,
|
CacheTime: 30,
|
||||||
}
|
}
|
||||||
forwardConf := ServerConfig{
|
forwardConf := ServerConfig{
|
||||||
UDPListenAddr: &net.UDPAddr{},
|
UDPListenAddrs: []*net.UDPAddr{},
|
||||||
TCPListenAddr: &net.TCPAddr{},
|
TCPListenAddrs: []*net.TCPAddr{},
|
||||||
FilteringConfig: FilteringConfig{
|
FilteringConfig: FilteringConfig{
|
||||||
ProtectionEnabled: true,
|
ProtectionEnabled: true,
|
||||||
UpstreamDNS: []string{"8.8.8.8:53", "8.8.4.4:53"},
|
UpstreamDNS: []string{"8.8.8.8:53", "8.8.4.4:53"},
|
||||||
|
@ -94,8 +94,8 @@ func TestDNSForwardHTTTP_handleSetConfig(t *testing.T) {
|
||||||
CacheTime: 30,
|
CacheTime: 30,
|
||||||
}
|
}
|
||||||
forwardConf := ServerConfig{
|
forwardConf := ServerConfig{
|
||||||
UDPListenAddr: &net.UDPAddr{},
|
UDPListenAddrs: []*net.UDPAddr{},
|
||||||
TCPListenAddr: &net.TCPAddr{},
|
TCPListenAddrs: []*net.TCPAddr{},
|
||||||
FilteringConfig: FilteringConfig{
|
FilteringConfig: FilteringConfig{
|
||||||
ProtectionEnabled: true,
|
ProtectionEnabled: true,
|
||||||
UpstreamDNS: []string{"8.8.8.8:53", "8.8.4.4:53"},
|
UpstreamDNS: []string{"8.8.8.8:53", "8.8.4.4:53"},
|
||||||
|
|
|
@ -76,8 +76,8 @@ type configuration struct {
|
||||||
|
|
||||||
// field ordering is important -- yaml fields will mirror ordering from here
|
// field ordering is important -- yaml fields will mirror ordering from here
|
||||||
type dnsConfig struct {
|
type dnsConfig struct {
|
||||||
BindHost net.IP `yaml:"bind_host"`
|
BindHosts []net.IP `yaml:"bind_hosts"`
|
||||||
Port int `yaml:"port"`
|
Port int `yaml:"port"`
|
||||||
|
|
||||||
// time interval for statistics (in days)
|
// time interval for statistics (in days)
|
||||||
StatsInterval uint32 `yaml:"statistics_interval"`
|
StatsInterval uint32 `yaml:"statistics_interval"`
|
||||||
|
@ -101,7 +101,7 @@ type tlsConfigSettings struct {
|
||||||
ForceHTTPS bool `yaml:"force_https" json:"force_https,omitempty"` // ForceHTTPS: if true, forces HTTP->HTTPS redirect
|
ForceHTTPS bool `yaml:"force_https" json:"force_https,omitempty"` // ForceHTTPS: if true, forces HTTP->HTTPS redirect
|
||||||
PortHTTPS int `yaml:"port_https" json:"port_https,omitempty"` // HTTPS port. If 0, HTTPS will be disabled
|
PortHTTPS int `yaml:"port_https" json:"port_https,omitempty"` // HTTPS port. If 0, HTTPS will be disabled
|
||||||
PortDNSOverTLS int `yaml:"port_dns_over_tls" json:"port_dns_over_tls,omitempty"` // DNS-over-TLS port. If 0, DOT will be disabled
|
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
|
PortDNSOverQUIC int `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,
|
// PortDNSCrypt is the port for DNSCrypt requests. If it's zero,
|
||||||
// DNSCrypt is disabled.
|
// DNSCrypt is disabled.
|
||||||
|
@ -125,7 +125,7 @@ var config = configuration{
|
||||||
BetaBindPort: 0,
|
BetaBindPort: 0,
|
||||||
BindHost: net.IP{0, 0, 0, 0},
|
BindHost: net.IP{0, 0, 0, 0},
|
||||||
DNS: dnsConfig{
|
DNS: dnsConfig{
|
||||||
BindHost: net.IP{0, 0, 0, 0},
|
BindHosts: []net.IP{{0, 0, 0, 0}},
|
||||||
Port: 53,
|
Port: 53,
|
||||||
StatsInterval: 1,
|
StatsInterval: 1,
|
||||||
FilteringConfig: dnsforward.FilteringConfig{
|
FilteringConfig: dnsforward.FilteringConfig{
|
||||||
|
|
|
@ -17,7 +17,6 @@ import (
|
||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardHome/internal/agherr"
|
"github.com/AdguardTeam/AdGuardHome/internal/agherr"
|
||||||
"github.com/AdguardTeam/AdGuardHome/internal/aghnet"
|
"github.com/AdguardTeam/AdGuardHome/internal/aghnet"
|
||||||
|
|
||||||
"github.com/AdguardTeam/golibs/log"
|
"github.com/AdguardTeam/golibs/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -264,7 +263,7 @@ func copyInstallSettings(dst, src *configuration) {
|
||||||
dst.BindHost = src.BindHost
|
dst.BindHost = src.BindHost
|
||||||
dst.BindPort = src.BindPort
|
dst.BindPort = src.BindPort
|
||||||
dst.BetaBindPort = src.BetaBindPort
|
dst.BetaBindPort = src.BetaBindPort
|
||||||
dst.DNS.BindHost = src.DNS.BindHost
|
dst.DNS.BindHosts = src.DNS.BindHosts
|
||||||
dst.DNS.Port = src.DNS.Port
|
dst.DNS.Port = src.DNS.Port
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,7 +334,7 @@ func (web *Web) handleInstallConfigure(w http.ResponseWriter, r *http.Request) {
|
||||||
Context.firstRun = false
|
Context.firstRun = false
|
||||||
config.BindHost = newSettings.Web.IP
|
config.BindHost = newSettings.Web.IP
|
||||||
config.BindPort = newSettings.Web.Port
|
config.BindPort = newSettings.Web.Port
|
||||||
config.DNS.BindHost = newSettings.DNS.IP
|
config.DNS.BindHosts = []net.IP{newSettings.DNS.IP}
|
||||||
config.DNS.Port = newSettings.DNS.Port
|
config.DNS.Port = newSettings.DNS.Port
|
||||||
|
|
||||||
// TODO(e.burkov): StartMods() should be put in a separate goroutine at
|
// TODO(e.burkov): StartMods() should be put in a separate goroutine at
|
||||||
|
|
|
@ -56,11 +56,6 @@ func initDNSServer() error {
|
||||||
Context.queryLog = querylog.New(conf)
|
Context.queryLog = querylog.New(conf)
|
||||||
|
|
||||||
filterConf := config.DNS.DnsfilterConf
|
filterConf := config.DNS.DnsfilterConf
|
||||||
bindhost := config.DNS.BindHost
|
|
||||||
if config.DNS.BindHost.IsUnspecified() {
|
|
||||||
bindhost = net.IPv4(127, 0, 0, 1)
|
|
||||||
}
|
|
||||||
filterConf.ResolverAddress = net.JoinHostPort(bindhost.String(), strconv.Itoa(config.DNS.Port))
|
|
||||||
filterConf.AutoHosts = &Context.autoHosts
|
filterConf.AutoHosts = &Context.autoHosts
|
||||||
filterConf.ConfigModified = onConfigModified
|
filterConf.ConfigModified = onConfigModified
|
||||||
filterConf.HTTPRegister = httpRegister
|
filterConf.HTTPRegister = httpRegister
|
||||||
|
@ -114,11 +109,51 @@ func onDNSRequest(d *proxy.DNSContext) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateServerConfig() (newconfig dnsforward.ServerConfig, err error) {
|
func ipsToTCPAddrs(ips []net.IP, port int) (tcpAddrs []*net.TCPAddr) {
|
||||||
newconfig = dnsforward.ServerConfig{
|
if ips == nil {
|
||||||
UDPListenAddr: &net.UDPAddr{IP: config.DNS.BindHost, Port: config.DNS.Port},
|
return nil
|
||||||
TCPListenAddr: &net.TCPAddr{IP: config.DNS.BindHost, Port: config.DNS.Port},
|
}
|
||||||
FilteringConfig: config.DNS.FilteringConfig,
|
|
||||||
|
tcpAddrs = make([]*net.TCPAddr, len(ips))
|
||||||
|
for i, ip := range ips {
|
||||||
|
tcpAddrs[i] = &net.TCPAddr{
|
||||||
|
IP: ip,
|
||||||
|
Port: port,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tcpAddrs
|
||||||
|
}
|
||||||
|
|
||||||
|
func ipsToUDPAddrs(ips []net.IP, port int) (udpAddrs []*net.UDPAddr) {
|
||||||
|
if ips == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
udpAddrs = make([]*net.UDPAddr, len(ips))
|
||||||
|
for i, ip := range ips {
|
||||||
|
udpAddrs[i] = &net.UDPAddr{
|
||||||
|
IP: ip,
|
||||||
|
Port: port,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return udpAddrs
|
||||||
|
}
|
||||||
|
|
||||||
|
func generateServerConfig() (newConf dnsforward.ServerConfig, err error) {
|
||||||
|
dnsConf := config.DNS
|
||||||
|
hosts := dnsConf.BindHosts
|
||||||
|
for i, h := range hosts {
|
||||||
|
if h.IsUnspecified() {
|
||||||
|
hosts[i] = net.IP{127, 0, 0, 1}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
newConf = dnsforward.ServerConfig{
|
||||||
|
UDPListenAddrs: ipsToUDPAddrs(hosts, dnsConf.Port),
|
||||||
|
TCPListenAddrs: ipsToTCPAddrs(hosts, dnsConf.Port),
|
||||||
|
FilteringConfig: dnsConf.FilteringConfig,
|
||||||
ConfigModified: onConfigModified,
|
ConfigModified: onConfigModified,
|
||||||
HTTPRegister: httpRegister,
|
HTTPRegister: httpRegister,
|
||||||
OnDNSRequest: onDNSRequest,
|
OnDNSRequest: onDNSRequest,
|
||||||
|
@ -127,25 +162,19 @@ func generateServerConfig() (newconfig dnsforward.ServerConfig, err error) {
|
||||||
tlsConf := tlsConfigSettings{}
|
tlsConf := tlsConfigSettings{}
|
||||||
Context.tls.WriteDiskConfig(&tlsConf)
|
Context.tls.WriteDiskConfig(&tlsConf)
|
||||||
if tlsConf.Enabled {
|
if tlsConf.Enabled {
|
||||||
newconfig.TLSConfig = tlsConf.TLSConfig
|
newConf.TLSConfig = tlsConf.TLSConfig
|
||||||
newconfig.TLSConfig.ServerName = tlsConf.ServerName
|
newConf.TLSConfig.ServerName = tlsConf.ServerName
|
||||||
|
|
||||||
if tlsConf.PortDNSOverTLS != 0 {
|
if tlsConf.PortDNSOverTLS != 0 {
|
||||||
newconfig.TLSListenAddr = &net.TCPAddr{
|
newConf.TLSListenAddrs = ipsToTCPAddrs(hosts, tlsConf.PortDNSOverTLS)
|
||||||
IP: config.DNS.BindHost,
|
|
||||||
Port: tlsConf.PortDNSOverTLS,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if tlsConf.PortDNSOverQUIC != 0 {
|
if tlsConf.PortDNSOverQUIC != 0 {
|
||||||
newconfig.QUICListenAddr = &net.UDPAddr{
|
newConf.QUICListenAddrs = ipsToUDPAddrs(hosts, tlsConf.PortDNSOverQUIC)
|
||||||
IP: config.DNS.BindHost,
|
|
||||||
Port: int(tlsConf.PortDNSOverQUIC),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if tlsConf.PortDNSCrypt != 0 {
|
if tlsConf.PortDNSCrypt != 0 {
|
||||||
newconfig.DNSCryptConfig, err = newDNSCrypt(config.DNS.BindHost, tlsConf)
|
newConf.DNSCryptConfig, err = newDNSCrypt(hosts, tlsConf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Don't wrap the error, because it's already
|
// Don't wrap the error, because it's already
|
||||||
// wrapped by newDNSCrypt.
|
// wrapped by newDNSCrypt.
|
||||||
|
@ -154,17 +183,17 @@ func generateServerConfig() (newconfig dnsforward.ServerConfig, err error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
newconfig.TLSv12Roots = Context.tlsRoots
|
newConf.TLSv12Roots = Context.tlsRoots
|
||||||
newconfig.TLSCiphers = Context.tlsCiphers
|
newConf.TLSCiphers = Context.tlsCiphers
|
||||||
newconfig.TLSAllowUnencryptedDOH = tlsConf.AllowUnencryptedDOH
|
newConf.TLSAllowUnencryptedDOH = tlsConf.AllowUnencryptedDOH
|
||||||
|
|
||||||
newconfig.FilterHandler = applyAdditionalFiltering
|
newConf.FilterHandler = applyAdditionalFiltering
|
||||||
newconfig.GetCustomUpstreamByClient = Context.clients.FindUpstreams
|
newConf.GetCustomUpstreamByClient = Context.clients.FindUpstreams
|
||||||
|
|
||||||
return newconfig, nil
|
return newConf, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newDNSCrypt(bindHost net.IP, tlsConf tlsConfigSettings) (dnscc dnsforward.DNSCryptConfig, err error) {
|
func newDNSCrypt(hosts []net.IP, tlsConf tlsConfigSettings) (dnscc dnsforward.DNSCryptConfig, err error) {
|
||||||
if tlsConf.DNSCryptConfigFile == "" {
|
if tlsConf.DNSCryptConfigFile == "" {
|
||||||
return dnscc, agherr.Error("no dnscrypt_config_file")
|
return dnscc, agherr.Error("no dnscrypt_config_file")
|
||||||
}
|
}
|
||||||
|
@ -186,21 +215,12 @@ func newDNSCrypt(bindHost net.IP, tlsConf tlsConfigSettings) (dnscc dnsforward.D
|
||||||
return dnscc, fmt.Errorf("creating dnscrypt cert: %w", err)
|
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{
|
return dnsforward.DNSCryptConfig{
|
||||||
UDPListenAddr: udpAddr,
|
UDPListenAddrs: ipsToUDPAddrs(hosts, tlsConf.PortDNSCrypt),
|
||||||
TCPListenAddr: tcpAddr,
|
TCPListenAddrs: ipsToTCPAddrs(hosts, tlsConf.PortDNSCrypt),
|
||||||
ResolverCert: cert,
|
ResolverCert: cert,
|
||||||
ProviderName: rc.ProviderName,
|
ProviderName: rc.ProviderName,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,10 +269,8 @@ func getDNSEncryption() (de dnsEncryption) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the list of DNS addresses the server is listening on
|
// Get the list of DNS addresses the server is listening on
|
||||||
func getDNSAddresses() []string {
|
func getDNSAddresses() (dnsAddrs []string) {
|
||||||
dnsAddresses := []string{}
|
if hosts := config.DNS.BindHosts; len(hosts) == 0 || hosts[0].IsUnspecified() {
|
||||||
|
|
||||||
if config.DNS.BindHost.IsUnspecified() {
|
|
||||||
ifaces, e := aghnet.GetValidNetInterfacesForWeb()
|
ifaces, e := aghnet.GetValidNetInterfacesForWeb()
|
||||||
if e != nil {
|
if e != nil {
|
||||||
log.Error("Couldn't get network interfaces: %v", e)
|
log.Error("Couldn't get network interfaces: %v", e)
|
||||||
|
@ -261,25 +279,29 @@ func getDNSAddresses() []string {
|
||||||
|
|
||||||
for _, iface := range ifaces {
|
for _, iface := range ifaces {
|
||||||
for _, addr := range iface.Addresses {
|
for _, addr := range iface.Addresses {
|
||||||
addDNSAddress(&dnsAddresses, addr)
|
addDNSAddress(&dnsAddrs, addr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
addDNSAddress(&dnsAddresses, config.DNS.BindHost)
|
for _, h := range hosts {
|
||||||
|
addDNSAddress(&dnsAddrs, h)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
de := getDNSEncryption()
|
de := getDNSEncryption()
|
||||||
if de.https != "" {
|
if de.https != "" {
|
||||||
dnsAddresses = append(dnsAddresses, de.https)
|
dnsAddrs = append(dnsAddrs, de.https)
|
||||||
}
|
|
||||||
if de.tls != "" {
|
|
||||||
dnsAddresses = append(dnsAddresses, de.tls)
|
|
||||||
}
|
|
||||||
if de.quic != "" {
|
|
||||||
dnsAddresses = append(dnsAddresses, de.quic)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return dnsAddresses
|
if de.tls != "" {
|
||||||
|
dnsAddrs = append(dnsAddrs, de.tls)
|
||||||
|
}
|
||||||
|
|
||||||
|
if de.quic != "" {
|
||||||
|
dnsAddrs = append(dnsAddrs, de.quic)
|
||||||
|
}
|
||||||
|
|
||||||
|
return dnsAddrs
|
||||||
}
|
}
|
||||||
|
|
||||||
// applyAdditionalFiltering adds additional client information and settings if
|
// applyAdditionalFiltering adds additional client information and settings if
|
||||||
|
@ -353,13 +375,13 @@ func startDNSServer() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func reconfigureDNSServer() (err error) {
|
func reconfigureDNSServer() (err error) {
|
||||||
var newconfig dnsforward.ServerConfig
|
var newConf dnsforward.ServerConfig
|
||||||
newconfig, err = generateServerConfig()
|
newConf, err = generateServerConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("generating forwarding dns server config: %w", err)
|
return fmt.Errorf("generating forwarding dns server config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = Context.dnsServer.Reconfigure(&newconfig)
|
err = Context.dnsServer.Reconfigure(&newConf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("starting forwarding dns server: %w", err)
|
return fmt.Errorf("starting forwarding dns server: %w", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,12 +13,20 @@ import (
|
||||||
yaml "gopkg.in/yaml.v2"
|
yaml "gopkg.in/yaml.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
const currentSchemaVersion = 7 // used for upgrading from old configs to new config
|
// currentSchemaVersion is the current schema version.
|
||||||
|
const currentSchemaVersion = 8
|
||||||
|
|
||||||
|
// These aliases are provided for convenience.
|
||||||
|
type (
|
||||||
|
any = interface{}
|
||||||
|
yarr = []any
|
||||||
|
yobj = map[any]any
|
||||||
|
)
|
||||||
|
|
||||||
// Performs necessary upgrade operations if needed
|
// Performs necessary upgrade operations if needed
|
||||||
func upgradeConfig() error {
|
func upgradeConfig() error {
|
||||||
// read a config file into an interface map, so we can manipulate values without losing any
|
// read a config file into an interface map, so we can manipulate values without losing any
|
||||||
diskConfig := map[string]interface{}{}
|
diskConfig := yobj{}
|
||||||
body, err := readConfigFile()
|
body, err := readConfigFile()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -53,7 +61,7 @@ func upgradeConfig() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Upgrade from oldVersion to newVersion
|
// Upgrade from oldVersion to newVersion
|
||||||
func upgradeConfigSchema(oldVersion int, diskConfig *map[string]interface{}) error {
|
func upgradeConfigSchema(oldVersion int, diskConfig *yobj) error {
|
||||||
switch oldVersion {
|
switch oldVersion {
|
||||||
case 0:
|
case 0:
|
||||||
err := upgradeSchema0to1(diskConfig)
|
err := upgradeSchema0to1(diskConfig)
|
||||||
|
@ -96,6 +104,11 @@ func upgradeConfigSchema(oldVersion int, diskConfig *map[string]interface{}) err
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
case 7:
|
||||||
|
err := upgradeSchema7to8(diskConfig)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
err := fmt.Errorf("configuration file contains unknown schema_version, abort")
|
err := fmt.Errorf("configuration file contains unknown schema_version, abort")
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
|
@ -121,7 +134,7 @@ func upgradeConfigSchema(oldVersion int, diskConfig *map[string]interface{}) err
|
||||||
|
|
||||||
// The first schema upgrade:
|
// The first schema upgrade:
|
||||||
// No more "dnsfilter.txt", filters are now kept in data/filters/
|
// No more "dnsfilter.txt", filters are now kept in data/filters/
|
||||||
func upgradeSchema0to1(diskConfig *map[string]interface{}) error {
|
func upgradeSchema0to1(diskConfig *yobj) error {
|
||||||
log.Printf("%s(): called", funcName())
|
log.Printf("%s(): called", funcName())
|
||||||
|
|
||||||
dnsFilterPath := filepath.Join(Context.workDir, "dnsfilter.txt")
|
dnsFilterPath := filepath.Join(Context.workDir, "dnsfilter.txt")
|
||||||
|
@ -142,7 +155,7 @@ func upgradeSchema0to1(diskConfig *map[string]interface{}) error {
|
||||||
// Second schema upgrade:
|
// Second schema upgrade:
|
||||||
// coredns is now dns in config
|
// coredns is now dns in config
|
||||||
// delete 'Corefile', since we don't use that anymore
|
// delete 'Corefile', since we don't use that anymore
|
||||||
func upgradeSchema1to2(diskConfig *map[string]interface{}) error {
|
func upgradeSchema1to2(diskConfig *yobj) error {
|
||||||
log.Printf("%s(): called", funcName())
|
log.Printf("%s(): called", funcName())
|
||||||
|
|
||||||
coreFilePath := filepath.Join(Context.workDir, "Corefile")
|
coreFilePath := filepath.Join(Context.workDir, "Corefile")
|
||||||
|
@ -166,7 +179,7 @@ func upgradeSchema1to2(diskConfig *map[string]interface{}) error {
|
||||||
|
|
||||||
// Third schema upgrade:
|
// Third schema upgrade:
|
||||||
// Bootstrap DNS becomes an array
|
// Bootstrap DNS becomes an array
|
||||||
func upgradeSchema2to3(diskConfig *map[string]interface{}) error {
|
func upgradeSchema2to3(diskConfig *yobj) error {
|
||||||
log.Printf("%s(): called", funcName())
|
log.Printf("%s(): called", funcName())
|
||||||
|
|
||||||
// Let's read dns configuration from diskConfig
|
// Let's read dns configuration from diskConfig
|
||||||
|
@ -175,8 +188,8 @@ func upgradeSchema2to3(diskConfig *map[string]interface{}) error {
|
||||||
return fmt.Errorf("no DNS configuration in config file")
|
return fmt.Errorf("no DNS configuration in config file")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert interface{} to map[string]interface{}
|
// Convert interface{} to yobj
|
||||||
newDNSConfig := make(map[string]interface{})
|
newDNSConfig := make(yobj)
|
||||||
|
|
||||||
switch v := dnsConfig.(type) {
|
switch v := dnsConfig.(type) {
|
||||||
case map[interface{}]interface{}:
|
case map[interface{}]interface{}:
|
||||||
|
@ -204,7 +217,7 @@ func upgradeSchema2to3(diskConfig *map[string]interface{}) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add use_global_blocked_services=true setting for existing "clients" array
|
// Add use_global_blocked_services=true setting for existing "clients" array
|
||||||
func upgradeSchema3to4(diskConfig *map[string]interface{}) error {
|
func upgradeSchema3to4(diskConfig *yobj) error {
|
||||||
log.Printf("%s(): called", funcName())
|
log.Printf("%s(): called", funcName())
|
||||||
|
|
||||||
(*diskConfig)["schema_version"] = 4
|
(*diskConfig)["schema_version"] = 4
|
||||||
|
@ -240,7 +253,7 @@ func upgradeSchema3to4(diskConfig *map[string]interface{}) error {
|
||||||
// - name: "..."
|
// - name: "..."
|
||||||
// password: "..."
|
// password: "..."
|
||||||
// ...
|
// ...
|
||||||
func upgradeSchema4to5(diskConfig *map[string]interface{}) error {
|
func upgradeSchema4to5(diskConfig *yobj) error {
|
||||||
log.Printf("%s(): called", funcName())
|
log.Printf("%s(): called", funcName())
|
||||||
|
|
||||||
(*diskConfig)["schema_version"] = 5
|
(*diskConfig)["schema_version"] = 5
|
||||||
|
@ -295,7 +308,7 @@ func upgradeSchema4to5(diskConfig *map[string]interface{}) error {
|
||||||
// ids:
|
// ids:
|
||||||
// - 127.0.0.1
|
// - 127.0.0.1
|
||||||
// - ...
|
// - ...
|
||||||
func upgradeSchema5to6(diskConfig *map[string]interface{}) error {
|
func upgradeSchema5to6(diskConfig *yobj) error {
|
||||||
log.Printf("%s(): called", funcName())
|
log.Printf("%s(): called", funcName())
|
||||||
|
|
||||||
(*diskConfig)["schema_version"] = 6
|
(*diskConfig)["schema_version"] = 6
|
||||||
|
@ -365,7 +378,7 @@ func upgradeSchema5to6(diskConfig *map[string]interface{}) error {
|
||||||
// dhcpv4:
|
// dhcpv4:
|
||||||
// gateway_ip: 192.168.56.1
|
// gateway_ip: 192.168.56.1
|
||||||
// ...
|
// ...
|
||||||
func upgradeSchema6to7(diskConfig *map[string]interface{}) error {
|
func upgradeSchema6to7(diskConfig *yobj) error {
|
||||||
log.Printf("Upgrade yaml: 6 to 7")
|
log.Printf("Upgrade yaml: 6 to 7")
|
||||||
|
|
||||||
(*diskConfig)["schema_version"] = 7
|
(*diskConfig)["schema_version"] = 7
|
||||||
|
@ -384,7 +397,7 @@ func upgradeSchema6to7(diskConfig *map[string]interface{}) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
dhcpv4 := map[string]interface{}{
|
dhcpv4 := yobj{
|
||||||
"gateway_ip": str,
|
"gateway_ip": str,
|
||||||
}
|
}
|
||||||
delete(dhcp, "gateway_ip")
|
delete(dhcp, "gateway_ip")
|
||||||
|
@ -438,6 +451,44 @@ func upgradeSchema6to7(diskConfig *map[string]interface{}) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// upgradeSchema7to8 performs the following changes:
|
||||||
|
//
|
||||||
|
// # BEFORE:
|
||||||
|
// 'dns':
|
||||||
|
// 'bind_host': '127.0.0.1'
|
||||||
|
//
|
||||||
|
// # AFTER:
|
||||||
|
// 'dns':
|
||||||
|
// 'bind_hosts':
|
||||||
|
// - '127.0.0.1'
|
||||||
|
//
|
||||||
|
func upgradeSchema7to8(diskConfig *yobj) (err error) {
|
||||||
|
log.Printf("Upgrade yaml: 7 to 8")
|
||||||
|
|
||||||
|
(*diskConfig)["schema_version"] = 8
|
||||||
|
|
||||||
|
dnsVal, ok := (*diskConfig)["dns"]
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
dns, ok := dnsVal.(yobj)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("unexpected type of dns: %T", dnsVal)
|
||||||
|
}
|
||||||
|
|
||||||
|
bindHostVal := dns["bind_host"]
|
||||||
|
bindHost, ok := bindHostVal.(string)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("undexpected type of dns.bind_host: %T", bindHostVal)
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(dns, "bind_host")
|
||||||
|
dns["bind_hosts"] = yarr{bindHost}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(a.garipov): Replace with log.Output when we port it to our logging
|
// TODO(a.garipov): Replace with log.Output when we port it to our logging
|
||||||
// package.
|
// package.
|
||||||
func funcName() string {
|
func funcName() string {
|
||||||
|
|
|
@ -1,18 +1,13 @@
|
||||||
package home
|
package home
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
// any is a convenient alias for interface{}.
|
// TODO(a.garipov): Cover all migrations, use a testdata/ dir.
|
||||||
type any = interface{}
|
|
||||||
|
|
||||||
// object is a convenient alias for map[string]interface{}.
|
|
||||||
type object = map[string]any
|
|
||||||
|
|
||||||
func TestUpgradeSchema1to2(t *testing.T) {
|
func TestUpgradeSchema1to2(t *testing.T) {
|
||||||
diskConf := testDiskConf(1)
|
diskConf := testDiskConf(1)
|
||||||
|
@ -25,11 +20,10 @@ func TestUpgradeSchema1to2(t *testing.T) {
|
||||||
_, ok := diskConf["coredns"]
|
_, ok := diskConf["coredns"]
|
||||||
require.False(t, ok)
|
require.False(t, ok)
|
||||||
|
|
||||||
dnsMap, ok := diskConf["dns"]
|
newDNSConf, ok := diskConf["dns"]
|
||||||
require.True(t, ok)
|
require.True(t, ok)
|
||||||
|
|
||||||
oldDNSConf := convertToObject(t, testDNSConf(1))
|
oldDNSConf := testDNSConf(1)
|
||||||
newDNSConf := convertToObject(t, dnsMap)
|
|
||||||
assert.Equal(t, oldDNSConf, newDNSConf)
|
assert.Equal(t, oldDNSConf, newDNSConf)
|
||||||
|
|
||||||
oldExcludedEntries := []string{"coredns", "schema_version"}
|
oldExcludedEntries := []string{"coredns", "schema_version"}
|
||||||
|
@ -49,7 +43,9 @@ func TestUpgradeSchema2to3(t *testing.T) {
|
||||||
dnsMap, ok := diskConf["dns"]
|
dnsMap, ok := diskConf["dns"]
|
||||||
require.True(t, ok)
|
require.True(t, ok)
|
||||||
|
|
||||||
newDNSConf := convertToObject(t, dnsMap)
|
newDNSConf, ok := dnsMap.(yobj)
|
||||||
|
require.True(t, ok)
|
||||||
|
|
||||||
bootstrapDNS := newDNSConf["bootstrap_dns"]
|
bootstrapDNS := newDNSConf["bootstrap_dns"]
|
||||||
switch v := bootstrapDNS.(type) {
|
switch v := bootstrapDNS.(type) {
|
||||||
case []string:
|
case []string:
|
||||||
|
@ -60,7 +56,7 @@ func TestUpgradeSchema2to3(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
excludedEntries := []string{"bootstrap_dns"}
|
excludedEntries := []string{"bootstrap_dns"}
|
||||||
oldDNSConf := convertToObject(t, testDNSConf(2))
|
oldDNSConf := testDNSConf(2)
|
||||||
assertEqualExcept(t, oldDNSConf, newDNSConf, excludedEntries, excludedEntries)
|
assertEqualExcept(t, oldDNSConf, newDNSConf, excludedEntries, excludedEntries)
|
||||||
|
|
||||||
excludedEntries = []string{"dns", "schema_version"}
|
excludedEntries = []string{"dns", "schema_version"}
|
||||||
|
@ -68,29 +64,34 @@ func TestUpgradeSchema2to3(t *testing.T) {
|
||||||
assertEqualExcept(t, oldDiskConf, diskConf, excludedEntries, excludedEntries)
|
assertEqualExcept(t, oldDiskConf, diskConf, excludedEntries, excludedEntries)
|
||||||
}
|
}
|
||||||
|
|
||||||
func convertToObject(t *testing.T, oldConf any) (newConf object) {
|
func TestUpgradeSchema7to8(t *testing.T) {
|
||||||
t.Helper()
|
const host = "1.2.3.4"
|
||||||
|
oldConf := yobj{
|
||||||
switch v := oldConf.(type) {
|
"dns": yobj{
|
||||||
case map[any]any:
|
"bind_host": host,
|
||||||
newConf = make(object, len(v))
|
},
|
||||||
for key, value := range v {
|
"schema_version": 7,
|
||||||
newConf[fmt.Sprint(key)] = value
|
|
||||||
}
|
|
||||||
case object:
|
|
||||||
newConf = make(object, len(v))
|
|
||||||
for key, value := range v {
|
|
||||||
newConf[key] = value
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
t.Fatalf("dns configuration is not a map, got %T", oldConf)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return newConf
|
err := upgradeSchema7to8(&oldConf)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
require.Equal(t, oldConf["schema_version"], 8)
|
||||||
|
|
||||||
|
dnsVal, ok := oldConf["dns"]
|
||||||
|
require.True(t, ok)
|
||||||
|
|
||||||
|
newDNSConf, ok := dnsVal.(yobj)
|
||||||
|
require.True(t, ok)
|
||||||
|
|
||||||
|
newBindHosts, ok := newDNSConf["bind_hosts"].(yarr)
|
||||||
|
require.True(t, ok)
|
||||||
|
require.Len(t, newBindHosts, 1)
|
||||||
|
assert.Equal(t, host, newBindHosts[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
// assertEqualExcept removes entries from configs and compares them.
|
// assertEqualExcept removes entries from configs and compares them.
|
||||||
func assertEqualExcept(t *testing.T, oldConf, newConf object, oldKeys, newKeys []string) {
|
func assertEqualExcept(t *testing.T, oldConf, newConf yobj, oldKeys, newKeys []string) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
for _, k := range oldKeys {
|
for _, k := range oldKeys {
|
||||||
|
@ -103,20 +104,17 @@ func assertEqualExcept(t *testing.T, oldConf, newConf object, oldKeys, newKeys [
|
||||||
assert.Equal(t, oldConf, newConf)
|
assert.Equal(t, oldConf, newConf)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testDiskConf(schemaVersion int) (diskConf object) {
|
func testDiskConf(schemaVersion int) (diskConf yobj) {
|
||||||
filters := []filter{
|
filters := []filter{{
|
||||||
{
|
URL: "https://filters.adtidy.org/android/filters/111_optimized.txt",
|
||||||
URL: "https://filters.adtidy.org/android/filters/111_optimized.txt",
|
Name: "Latvian filter",
|
||||||
Name: "Latvian filter",
|
RulesCount: 100,
|
||||||
RulesCount: 100,
|
}, {
|
||||||
},
|
URL: "https://easylist.to/easylistgermany/easylistgermany.txt",
|
||||||
{
|
Name: "Germany filter",
|
||||||
URL: "https://easylist.to/easylistgermany/easylistgermany.txt",
|
RulesCount: 200,
|
||||||
Name: "Germany filter",
|
}}
|
||||||
RulesCount: 200,
|
diskConf = yobj{
|
||||||
},
|
|
||||||
}
|
|
||||||
diskConf = object{
|
|
||||||
"language": "en",
|
"language": "en",
|
||||||
"filters": filters,
|
"filters": filters,
|
||||||
"user_rules": []string{},
|
"user_rules": []string{},
|
||||||
|
@ -139,8 +137,8 @@ func testDiskConf(schemaVersion int) (diskConf object) {
|
||||||
|
|
||||||
// testDNSConf creates a DNS config for test the way gopkg.in/yaml.v2 would
|
// testDNSConf creates a DNS config for test the way gopkg.in/yaml.v2 would
|
||||||
// unmarshal it. In YAML, keys aren't guaranteed to always only be strings.
|
// unmarshal it. In YAML, keys aren't guaranteed to always only be strings.
|
||||||
func testDNSConf(schemaVersion int) (dnsConf map[any]any) {
|
func testDNSConf(schemaVersion int) (dnsConf yobj) {
|
||||||
dnsConf = map[any]any{
|
dnsConf = yobj{
|
||||||
"port": 53,
|
"port": 53,
|
||||||
"blocked_response_ttl": 10,
|
"blocked_response_ttl": 10,
|
||||||
"querylog_enabled": true,
|
"querylog_enabled": true,
|
||||||
|
|
|
@ -93,7 +93,7 @@ readonly build_flags="${BUILD_FLAGS:-$out_flags $par_flags\
|
||||||
$v_flags $x_flags}"
|
$v_flags $x_flags}"
|
||||||
|
|
||||||
# Don't use quotes with flag variables to get word splitting.
|
# Don't use quotes with flag variables to get word splitting.
|
||||||
"$go" generate $v_flags $x_flags ./...
|
"$go" generate $v_flags $x_flags ./main.go
|
||||||
|
|
||||||
# Don't use quotes with flag variables to get word splitting.
|
# Don't use quotes with flag variables to get word splitting.
|
||||||
"$go" build --ldflags "$ldflags" $build_flags
|
"$go" build --ldflags "$ldflags" $build_flags
|
||||||
|
|
Loading…
Reference in New Issue