From d4afd60b08a3cc6da63d3ece706906f4dc76fdb9 Mon Sep 17 00:00:00 2001
From: hellodword <46193371+hellodword@users.noreply.github.com>
Date: Fri, 9 Sep 2022 19:51:10 +0800
Subject: [PATCH] feat: add dns.ipset_file setting

---
 CHANGELOG.md                      |  6 ++++++
 internal/dnsforward/config.go     | 23 +++++++++++++++++++++++
 internal/dnsforward/dnsforward.go |  2 +-
 3 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 67835936..7371ea24 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -31,6 +31,12 @@ and this project adheres to
 See also the [v0.107.13 GitHub milestone][ms-v0.107.13].
 
 [ms-v0.107.13]:   https://github.com/AdguardTeam/AdGuardHome/milestone/49?closed=1
+
+### Added
+
+- The `dns.ipset_file` property in the configuration file now allows you to
+  load the ipset list from a separate file instead of setting all upstreams
+  in AdGuard Home settings.  ([#4686]).
 -->
 
 
diff --git a/internal/dnsforward/config.go b/internal/dnsforward/config.go
index 2b2ba2e8..5febc457 100644
--- a/internal/dnsforward/config.go
+++ b/internal/dnsforward/config.go
@@ -131,6 +131,10 @@ type FilteringConfig struct {
 	//   DOMAIN[,DOMAIN].../IPSET_NAME
 	//
 	IpsetList []string `yaml:"ipset"`
+
+	// IpsetListFileName, if set, points to the file with ipset configuration.
+	// The format is the same as in IpsetList.
+	IpsetListFileName string `yaml:"ipset_file"`
 }
 
 // TLSConfig is the TLS configuration for HTTPS, DNS-over-HTTPS, and DNS-over-TLS
@@ -501,3 +505,22 @@ func (s *Server) onGetCertificate(ch *tls.ClientHelloInfo) (*tls.Certificate, er
 	}
 	return &s.conf.cert, nil
 }
+
+// prepareIpsetListSettings - prepares ipset list settings
+func (s *Server) prepareIpsetListSettings() error {
+	var ipsets []string
+	if s.conf.IpsetListFileName != "" {
+		data, err := os.ReadFile(s.conf.IpsetListFileName)
+		if err != nil {
+			return err
+		}
+
+		ipsets = stringutil.SplitTrimmed(string(data), "\n")
+
+		log.Debug("dns: using %d ipset list from file %s", len(ipsets), s.conf.IpsetListFileName)
+	} else {
+		ipsets = s.conf.IpsetList
+	}
+
+	return s.ipset.init(ipsets)
+}
diff --git a/internal/dnsforward/dnsforward.go b/internal/dnsforward/dnsforward.go
index 33be1e83..0ed97b8a 100644
--- a/internal/dnsforward/dnsforward.go
+++ b/internal/dnsforward/dnsforward.go
@@ -446,7 +446,7 @@ func (s *Server) Prepare(conf *ServerConfig) (err error) {
 
 	s.initDefaultSettings()
 
-	err = s.ipset.init(s.conf.IpsetList)
+	err = s.prepareIpsetListSettings()
 	if err != nil {
 		// Don't wrap the error, because it's informative enough as is.
 		return err