Filters are now saved to a file Also, they're loaded from the file on startup Filter ID is not passed to the CoreDNS plugin config (server-side AG DNS must be changed accordingly) Some minor refactoring, unused functions removed
This commit is contained in:
148
config.go
148
config.go
@@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"gopkg.in/yaml.v2"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
@@ -10,46 +11,61 @@ import (
|
||||
"sync"
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
// Current schema version. We compare it with the value from
|
||||
// the configuration file and perform necessary upgrade operations if needed
|
||||
const SchemaVersion = 1
|
||||
|
||||
// Directory where we'll store all downloaded filters contents
|
||||
const FiltersDir = "filters"
|
||||
|
||||
// configuration is loaded from YAML
|
||||
type configuration struct {
|
||||
ourConfigFilename string
|
||||
ourBinaryDir string
|
||||
// Directory to store data (i.e. filters contents)
|
||||
ourDataDir string
|
||||
|
||||
BindHost string `yaml:"bind_host"`
|
||||
BindPort int `yaml:"bind_port"`
|
||||
AuthName string `yaml:"auth_name"`
|
||||
AuthPass string `yaml:"auth_pass"`
|
||||
CoreDNS coreDNSConfig `yaml:"coredns"`
|
||||
Filters []filter `yaml:"filters"`
|
||||
UserRules []string `yaml:"user_rules"`
|
||||
// Schema version of the config file. This value is used when performing the app updates.
|
||||
SchemaVersion int `yaml:"schema_version"`
|
||||
BindHost string `yaml:"bind_host"`
|
||||
BindPort int `yaml:"bind_port"`
|
||||
AuthName string `yaml:"auth_name"`
|
||||
AuthPass string `yaml:"auth_pass"`
|
||||
CoreDNS coreDNSConfig `yaml:"coredns"`
|
||||
Filters []filter `yaml:"filters"`
|
||||
UserRules []string `yaml:"user_rules"`
|
||||
|
||||
sync.RWMutex `yaml:"-"`
|
||||
}
|
||||
|
||||
type coreDnsFilter struct {
|
||||
ID int `yaml:"-"`
|
||||
Path string `yaml:"-"`
|
||||
}
|
||||
|
||||
type coreDNSConfig struct {
|
||||
binaryFile string
|
||||
coreFile string
|
||||
FilterFile string `yaml:"-"`
|
||||
Port int `yaml:"port"`
|
||||
ProtectionEnabled bool `yaml:"protection_enabled"`
|
||||
FilteringEnabled bool `yaml:"filtering_enabled"`
|
||||
SafeBrowsingEnabled bool `yaml:"safebrowsing_enabled"`
|
||||
SafeSearchEnabled bool `yaml:"safesearch_enabled"`
|
||||
ParentalEnabled bool `yaml:"parental_enabled"`
|
||||
ParentalSensitivity int `yaml:"parental_sensitivity"`
|
||||
BlockedResponseTTL int `yaml:"blocked_response_ttl"`
|
||||
QueryLogEnabled bool `yaml:"querylog_enabled"`
|
||||
Pprof string `yaml:"-"`
|
||||
Cache string `yaml:"-"`
|
||||
Prometheus string `yaml:"-"`
|
||||
UpstreamDNS []string `yaml:"upstream_dns"`
|
||||
Filters []coreDnsFilter `yaml:"-"`
|
||||
Port int `yaml:"port"`
|
||||
ProtectionEnabled bool `yaml:"protection_enabled"`
|
||||
FilteringEnabled bool `yaml:"filtering_enabled"`
|
||||
SafeBrowsingEnabled bool `yaml:"safebrowsing_enabled"`
|
||||
SafeSearchEnabled bool `yaml:"safesearch_enabled"`
|
||||
ParentalEnabled bool `yaml:"parental_enabled"`
|
||||
ParentalSensitivity int `yaml:"parental_sensitivity"`
|
||||
BlockedResponseTTL int `yaml:"blocked_response_ttl"`
|
||||
QueryLogEnabled bool `yaml:"querylog_enabled"`
|
||||
Pprof string `yaml:"-"`
|
||||
Cache string `yaml:"-"`
|
||||
Prometheus string `yaml:"-"`
|
||||
UpstreamDNS []string `yaml:"upstream_dns"`
|
||||
}
|
||||
|
||||
type filter struct {
|
||||
ID int `json:"ID"` // auto-assigned when filter is added
|
||||
URL string `json:"url"`
|
||||
Name string `json:"name" yaml:"name"`
|
||||
Enabled bool `json:"enabled"`
|
||||
@@ -63,13 +79,13 @@ var defaultDNS = []string{"tls://1.1.1.1", "tls://1.0.0.1"}
|
||||
// initialize to default values, will be changed later when reading config or parsing command line
|
||||
var config = configuration{
|
||||
ourConfigFilename: "AdGuardHome.yaml",
|
||||
ourDataDir: "data",
|
||||
BindPort: 3000,
|
||||
BindHost: "127.0.0.1",
|
||||
CoreDNS: coreDNSConfig{
|
||||
Port: 53,
|
||||
binaryFile: "coredns", // only filename, no path
|
||||
coreFile: "Corefile", // only filename, no path
|
||||
FilterFile: "dnsfilter.txt", // only filename, no path
|
||||
binaryFile: "coredns", // only filename, no path
|
||||
coreFile: "Corefile", // only filename, no path
|
||||
ProtectionEnabled: true,
|
||||
FilteringEnabled: true,
|
||||
SafeBrowsingEnabled: false,
|
||||
@@ -80,13 +96,33 @@ var config = configuration{
|
||||
Prometheus: "prometheus :9153",
|
||||
},
|
||||
Filters: []filter{
|
||||
{Enabled: true, URL: "https://adguardteam.github.io/AdGuardSDNSFilter/Filters/filter.txt"},
|
||||
{Enabled: false, URL: "https://adaway.org/hosts.txt", Name: "AdAway"},
|
||||
{Enabled: false, URL: "https://hosts-file.net/ad_servers.txt", Name: "hpHosts - Ad and Tracking servers only"},
|
||||
{Enabled: false, URL: "http://www.malwaredomainlist.com/hostslist/hosts.txt", Name: "MalwareDomainList.com Hosts List"},
|
||||
{ID: 1, Enabled: true, URL: "https://adguardteam.github.io/AdGuardSDNSFilter/Filters/filter.txt", Name: "AdGuard Simplified Domain Names filter"},
|
||||
{ID: 2, Enabled: false, URL: "https://adaway.org/hosts.txt", Name: "AdAway"},
|
||||
{ID: 3, Enabled: false, URL: "https://hosts-file.net/ad_servers.txt", Name: "hpHosts - Ad and Tracking servers only"},
|
||||
{ID: 4, Enabled: false, URL: "http://www.malwaredomainlist.com/hostslist/hosts.txt", Name: "MalwareDomainList.com Hosts List"},
|
||||
},
|
||||
}
|
||||
|
||||
// Creates a helper object for working with the user rules
|
||||
func getUserFilter() filter {
|
||||
|
||||
// TODO: This should be calculated when UserRules are set
|
||||
contents := []byte{}
|
||||
for _, rule := range config.UserRules {
|
||||
contents = append(contents, []byte(rule)...)
|
||||
contents = append(contents, '\n')
|
||||
}
|
||||
|
||||
userFilter := filter{
|
||||
// User filter always has ID=0
|
||||
ID: 0,
|
||||
contents: contents,
|
||||
Enabled: true,
|
||||
}
|
||||
|
||||
return userFilter
|
||||
}
|
||||
|
||||
func parseConfig() error {
|
||||
configfile := filepath.Join(config.ourBinaryDir, config.ourConfigFilename)
|
||||
log.Printf("Reading YAML file: %s", configfile)
|
||||
@@ -117,16 +153,19 @@ func writeConfig() error {
|
||||
log.Printf("Couldn't generate YAML file: %s", err)
|
||||
return err
|
||||
}
|
||||
err = ioutil.WriteFile(configfile+".tmp", yamlText, 0644)
|
||||
err = writeFileSafe(configfile, yamlText)
|
||||
if err != nil {
|
||||
log.Printf("Couldn't write YAML config: %s", err)
|
||||
log.Printf("Couldn't save YAML config: %s", err)
|
||||
return err
|
||||
}
|
||||
err = os.Rename(configfile+".tmp", configfile)
|
||||
|
||||
userFilter := getUserFilter()
|
||||
err = userFilter.save()
|
||||
if err != nil {
|
||||
log.Printf("Couldn't rename YAML config: %s", err)
|
||||
log.Printf("Couldn't save the user filter: %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -141,15 +180,12 @@ func writeCoreDNSConfig() error {
|
||||
log.Printf("Couldn't generate DNS config: %s", err)
|
||||
return err
|
||||
}
|
||||
err = ioutil.WriteFile(corefile+".tmp", []byte(configtext), 0644)
|
||||
err = writeFileSafe(corefile, []byte(configtext))
|
||||
if err != nil {
|
||||
log.Printf("Couldn't write DNS config: %s", err)
|
||||
log.Printf("Couldn't save DNS config: %s", err)
|
||||
return err
|
||||
}
|
||||
err = os.Rename(corefile+".tmp", corefile)
|
||||
if err != nil {
|
||||
log.Printf("Couldn't rename DNS config: %s", err)
|
||||
}
|
||||
return err
|
||||
return nil
|
||||
}
|
||||
|
||||
func writeAllConfigs() error {
|
||||
@@ -167,12 +203,17 @@ func writeAllConfigs() error {
|
||||
}
|
||||
|
||||
const coreDNSConfigTemplate = `.:{{.Port}} {
|
||||
{{if .ProtectionEnabled}}dnsfilter {{if .FilteringEnabled}}{{.FilterFile}}{{end}} {
|
||||
{{if .ProtectionEnabled}}dnsfilter {
|
||||
{{if .SafeBrowsingEnabled}}safebrowsing{{end}}
|
||||
{{if .ParentalEnabled}}parental {{.ParentalSensitivity}}{{end}}
|
||||
{{if .SafeSearchEnabled}}safesearch{{end}}
|
||||
{{if .QueryLogEnabled}}querylog{{end}}
|
||||
blocked_ttl {{.BlockedResponseTTL}}
|
||||
{{if .FilteringEnabled}}
|
||||
{{range .Filters}}
|
||||
filter {{.ID}} "{{.Path}}"
|
||||
{{end}}
|
||||
{{end}}
|
||||
}{{end}}
|
||||
{{.Pprof}}
|
||||
hosts {
|
||||
@@ -196,7 +237,28 @@ func generateCoreDNSConfigText() (string, error) {
|
||||
|
||||
var configBytes bytes.Buffer
|
||||
temporaryConfig := config.CoreDNS
|
||||
temporaryConfig.FilterFile = filepath.Join(config.ourBinaryDir, config.CoreDNS.FilterFile)
|
||||
|
||||
// fill the list of filters
|
||||
filters := make([]coreDnsFilter, 0)
|
||||
|
||||
// first of all, append the user filter
|
||||
userFilter := getUserFilter()
|
||||
|
||||
// TODO: Don't add if empty
|
||||
//if len(userFilter.contents) > 0 {
|
||||
filters = append(filters, coreDnsFilter{ID: userFilter.ID, Path: userFilter.getFilterFilePath()})
|
||||
//}
|
||||
|
||||
// then go through other filters
|
||||
for i := range config.Filters {
|
||||
filter := &config.Filters[i]
|
||||
|
||||
if filter.Enabled && len(filter.contents) > 0 {
|
||||
filters = append(filters, coreDnsFilter{ID: filter.ID, Path: filter.getFilterFilePath()})
|
||||
}
|
||||
}
|
||||
temporaryConfig.Filters = filters
|
||||
|
||||
// run the template
|
||||
err = t.Execute(&configBytes, &temporaryConfig)
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user