Pull request: 1947 disable autohosts option

Merge in DNS/adguard-home from 1947-hosts-opt to master

Updates #1947.
Updates #2829.

Squashed commit of the following:

commit d09285c3dbfa7816469eec223b88c320c255c8fe
Merge: cff8c4cd 7c6557b0
Author: Eugene Burkov <e.burkov@adguard.com>
Date:   Mon Apr 12 18:23:20 2021 +0300

    Merge branch 'master' into 1947-hosts-opt

commit cff8c4cdbf4bcd1f5f413c541d7f4a9e42b8b05b
Author: Eugene Burkov <e.burkov@adguard.com>
Date:   Mon Apr 12 17:46:19 2021 +0300

    home: fix help

commit 1fa01d5b30f5adeda564dcc85a7064e2921d5981
Author: Eugene Burkov <e.burkov@adguard.com>
Date:   Mon Apr 12 17:40:48 2021 +0300

    home: fix option order

commit 9d83cb604aaddcc8cbe99bafa544636f8f0b7e54
Author: Eugene Burkov <e.burkov@adguard.com>
Date:   Mon Apr 12 17:28:30 2021 +0300

    aghnet: add important todo

commit 7f1386ff5c3081e07e975b640164a7a05e1319c9
Author: Eugene Burkov <e.burkov@adguard.com>
Date:   Mon Apr 12 17:17:17 2021 +0300

    all: correct naming

commit cbe2b2e4b21d5bceb3ee88e09cad154ba62b5cef
Author: Eugene Burkov <e.burkov@adguard.com>
Date:   Mon Apr 12 15:55:46 2021 +0300

    all: mv functionality from util

commit e82ad53862682d903dd0dd10844db65997a758bc
Author: Eugene Burkov <e.burkov@adguard.com>
Date:   Mon Apr 12 15:41:35 2021 +0300

    home: imp code, docs

commit 9058977f3ff99648fabaebbd7c1c354c71671327
Author: Eugene Burkov <e.burkov@adguard.com>
Date:   Mon Apr 12 15:02:34 2021 +0300

    home: add an option to disable autohosts
This commit is contained in:
Eugene Burkov 2021-04-12 18:31:45 +03:00
parent 7c6557b05e
commit e671f43a2f
10 changed files with 178 additions and 137 deletions

View File

@ -15,6 +15,8 @@ and this project adheres to
### Added
- New flag `--no-etc-hosts` to disable client domain name lookups in the
operating system's /etc/hosts files ([#1947]).
- The ability to set up custom upstreams to resolve PTR queries for local
addresses and to disable the automatic resolving of clients' addresses
([#2704]).
@ -54,6 +56,7 @@ and this project adheres to
[#1273]: https://github.com/AdguardTeam/AdGuardHome/issues/1273
[#1401]: https://github.com/AdguardTeam/AdGuardHome/issues/1401
[#1947]: https://github.com/AdguardTeam/AdGuardHome/issues/1947
[#2385]: https://github.com/AdguardTeam/AdGuardHome/issues/2385
[#2393]: https://github.com/AdguardTeam/AdGuardHome/issues/2393
[#2412]: https://github.com/AdguardTeam/AdGuardHome/issues/2412

View File

@ -1,8 +1,4 @@
// Package util contains various utilities.
//
// TODO(a.garipov): Such packages are widely considered an antipattern. Remove
// this when we refactor our project structure.
package util
package aghnet
import (
"bufio"
@ -16,7 +12,6 @@ import (
"strings"
"sync"
"github.com/AdguardTeam/AdGuardHome/internal/aghnet"
"github.com/AdguardTeam/AdGuardHome/internal/aghos"
"github.com/AdguardTeam/golibs/log"
"github.com/fsnotify/fsnotify"
@ -25,8 +20,11 @@ import (
type onChangedT func()
// AutoHosts - automatic DNS records
type AutoHosts struct {
// EtcHostsContainer - automatic DNS records
//
// TODO(e.burkov): Move the logic under interface. Refactor. Probably remove
// the resolving logic.
type EtcHostsContainer struct {
// lock protects table and tableReverse.
lock sync.RWMutex
// table is the host-to-IPs map.
@ -47,63 +45,67 @@ type AutoHosts struct {
}
// SetOnChanged - set callback function that will be called when the data is changed
func (a *AutoHosts) SetOnChanged(onChanged onChangedT) {
a.onChanged = onChanged
func (ehc *EtcHostsContainer) SetOnChanged(onChanged onChangedT) {
ehc.onChanged = onChanged
}
// Notify other modules
func (a *AutoHosts) notify() {
if a.onChanged == nil {
func (ehc *EtcHostsContainer) notify() {
if ehc.onChanged == nil {
return
}
a.onChanged()
ehc.onChanged()
}
// Init - initialize
// hostsFn: Override default name for the hosts-file (optional)
func (a *AutoHosts) Init(hostsFn string) {
a.table = make(map[string][]net.IP)
a.onlyWritesChan = make(chan fsnotify.Event, 2)
func (ehc *EtcHostsContainer) Init(hostsFn string) {
ehc.table = make(map[string][]net.IP)
ehc.onlyWritesChan = make(chan fsnotify.Event, 2)
a.hostsFn = "/etc/hosts"
ehc.hostsFn = "/etc/hosts"
if runtime.GOOS == "windows" {
a.hostsFn = os.ExpandEnv("$SystemRoot\\system32\\drivers\\etc\\hosts")
ehc.hostsFn = os.ExpandEnv("$SystemRoot\\system32\\drivers\\etc\\hosts")
}
if len(hostsFn) != 0 {
a.hostsFn = hostsFn
ehc.hostsFn = hostsFn
}
if aghos.IsOpenWrt() {
// OpenWrt: "/tmp/hosts/dhcp.cfg01411c".
a.hostsDirs = append(a.hostsDirs, "/tmp/hosts")
ehc.hostsDirs = append(ehc.hostsDirs, "/tmp/hosts")
}
// Load hosts initially
a.updateHosts()
ehc.updateHosts()
var err error
a.watcher, err = fsnotify.NewWatcher()
ehc.watcher, err = fsnotify.NewWatcher()
if err != nil {
log.Error("autohosts: %s", err)
log.Error("etchostscontainer: %s", err)
}
}
// Start - start module
func (a *AutoHosts) Start() {
log.Debug("Start AutoHosts module")
func (ehc *EtcHostsContainer) Start() {
if ehc == nil {
return
}
a.updateHosts()
log.Debug("Start etchostscontainer module")
if a.watcher != nil {
go a.watcherLoop()
ehc.updateHosts()
err := a.watcher.Add(a.hostsFn)
if ehc.watcher != nil {
go ehc.watcherLoop()
err := ehc.watcher.Add(ehc.hostsFn)
if err != nil {
log.Error("Error while initializing watcher for a file %s: %s", a.hostsFn, err)
log.Error("Error while initializing watcher for a file %s: %s", ehc.hostsFn, err)
}
for _, dir := range a.hostsDirs {
err = a.watcher.Add(dir)
for _, dir := range ehc.hostsDirs {
err = ehc.watcher.Add(dir)
if err != nil {
log.Error("Error while initializing watcher for a directory %s: %s", dir, err)
}
@ -112,67 +114,71 @@ func (a *AutoHosts) Start() {
}
// Close - close module
func (a *AutoHosts) Close() {
if a.watcher != nil {
_ = a.watcher.Close()
func (ehc *EtcHostsContainer) Close() {
if ehc == nil {
return
}
close(a.onlyWritesChan)
if ehc.watcher != nil {
_ = ehc.watcher.Close()
}
close(ehc.onlyWritesChan)
}
// Process returns the list of IP addresses for the hostname or nil if nothing
// found.
func (a *AutoHosts) Process(host string, qtype uint16) []net.IP {
func (ehc *EtcHostsContainer) Process(host string, qtype uint16) []net.IP {
if qtype == dns.TypePTR {
return nil
}
var ipsCopy []net.IP
a.lock.RLock()
defer a.lock.RUnlock()
ehc.lock.RLock()
defer ehc.lock.RUnlock()
if ips, ok := a.table[host]; ok {
if ips, ok := ehc.table[host]; ok {
ipsCopy = make([]net.IP, len(ips))
copy(ipsCopy, ips)
}
log.Debug("autohosts: answer: %s -> %v", host, ipsCopy)
log.Debug("etchostscontainer: answer: %s -> %v", host, ipsCopy)
return ipsCopy
}
// ProcessReverse processes a PTR request. It returns nil if nothing is found.
func (a *AutoHosts) ProcessReverse(addr string, qtype uint16) (hosts []string) {
func (ehc *EtcHostsContainer) ProcessReverse(addr string, qtype uint16) (hosts []string) {
if qtype != dns.TypePTR {
return nil
}
ipReal := aghnet.UnreverseAddr(addr)
ipReal := UnreverseAddr(addr)
if ipReal == nil {
return nil
}
ipStr := ipReal.String()
a.lock.RLock()
defer a.lock.RUnlock()
ehc.lock.RLock()
defer ehc.lock.RUnlock()
hosts = a.tableReverse[ipStr]
hosts = ehc.tableReverse[ipStr]
if len(hosts) == 0 {
return nil // not found
}
log.Debug("autohosts: reverse-lookup: %s -> %s", addr, hosts)
log.Debug("etchostscontainer: reverse-lookup: %s -> %s", addr, hosts)
return hosts
}
// List returns an IP-to-hostnames table. It is safe for concurrent use.
func (a *AutoHosts) List() (ipToHosts map[string][]string) {
a.lock.RLock()
defer a.lock.RUnlock()
func (ehc *EtcHostsContainer) List() (ipToHosts map[string][]string) {
ehc.lock.RLock()
defer ehc.lock.RUnlock()
ipToHosts = make(map[string][]string, len(a.tableReverse))
for k, v := range a.tableReverse {
ipToHosts = make(map[string][]string, len(ehc.tableReverse))
for k, v := range ehc.tableReverse {
ipToHosts[k] = v
}
@ -180,7 +186,7 @@ func (a *AutoHosts) List() (ipToHosts map[string][]string) {
}
// update table
func (a *AutoHosts) updateTable(table map[string][]net.IP, host string, ipAddr net.IP) {
func (ehc *EtcHostsContainer) updateTable(table map[string][]net.IP, host string, ipAddr net.IP) {
ips, ok := table[host]
if ok {
for _, ip := range ips {
@ -199,17 +205,17 @@ func (a *AutoHosts) updateTable(table map[string][]net.IP, host string, ipAddr n
ok = true
}
if ok {
log.Debug("autohosts: added %s -> %s", ipAddr, host)
log.Debug("etchostscontainer: added %s -> %s", ipAddr, host)
}
}
// updateTableRev updates the reverse address table.
func (a *AutoHosts) updateTableRev(tableRev map[string][]string, newHost string, ipAddr net.IP) {
func (ehc *EtcHostsContainer) updateTableRev(tableRev map[string][]string, newHost string, ipAddr net.IP) {
ipStr := ipAddr.String()
hosts, ok := tableRev[ipStr]
if !ok {
tableRev[ipStr] = []string{newHost}
log.Debug("autohosts: added reverse-address %s -> %s", ipStr, newHost)
log.Debug("etchostscontainer: added reverse-address %s -> %s", ipStr, newHost)
return
}
@ -221,20 +227,20 @@ func (a *AutoHosts) updateTableRev(tableRev map[string][]string, newHost string,
}
tableRev[ipStr] = append(tableRev[ipStr], newHost)
log.Debug("autohosts: added reverse-address %s -> %s", ipStr, newHost)
log.Debug("etchostscontainer: added reverse-address %s -> %s", ipStr, newHost)
}
// Read IP-hostname pairs from file
// Multiple hostnames per line (per one IP) is supported.
func (a *AutoHosts) load(table map[string][]net.IP, tableRev map[string][]string, fn string) {
func (ehc *EtcHostsContainer) load(table map[string][]net.IP, tableRev map[string][]string, fn string) {
f, err := os.Open(fn)
if err != nil {
log.Error("autohosts: %s", err)
log.Error("etchostscontainer: %s", err)
return
}
defer f.Close()
r := bufio.NewReader(f)
log.Debug("autohosts: loading hosts from file %s", fn)
log.Debug("etchostscontainer: loading hosts from file %s", fn)
for done := false; !done; {
var line string
@ -242,7 +248,7 @@ func (a *AutoHosts) load(table map[string][]net.IP, tableRev map[string][]string
if err == io.EOF {
done = true
} else if err != nil {
log.Error("autohosts: %s", err)
log.Error("etchostscontainer: %s", err)
return
}
@ -276,8 +282,8 @@ func (a *AutoHosts) load(table map[string][]net.IP, tableRev map[string][]string
host = host[:sharp]
}
a.updateTable(table, host, ip)
a.updateTableRev(tableRev, host, ip)
ehc.updateTable(table, host, ip)
ehc.updateTableRev(tableRev, host, ip)
if sharp >= 0 {
// Skip the comments again.
break
@ -287,20 +293,20 @@ func (a *AutoHosts) load(table map[string][]net.IP, tableRev map[string][]string
}
// onlyWrites is a filter for (*fsnotify.Watcher).Events.
func (a *AutoHosts) onlyWrites() {
for event := range a.watcher.Events {
func (ehc *EtcHostsContainer) onlyWrites() {
for event := range ehc.watcher.Events {
if event.Op&fsnotify.Write == fsnotify.Write {
a.onlyWritesChan <- event
ehc.onlyWritesChan <- event
}
}
}
// Receive notifications from fsnotify package
func (a *AutoHosts) watcherLoop() {
go a.onlyWrites()
func (ehc *EtcHostsContainer) watcherLoop() {
go ehc.onlyWrites()
for {
select {
case event, ok := <-a.onlyWritesChan:
case event, ok := <-ehc.onlyWritesChan:
if !ok {
return
}
@ -310,7 +316,7 @@ func (a *AutoHosts) watcherLoop() {
repeat := true
for repeat {
select {
case _, ok = <-a.onlyWritesChan:
case _, ok = <-ehc.onlyWritesChan:
repeat = ok
default:
repeat = false
@ -318,48 +324,48 @@ func (a *AutoHosts) watcherLoop() {
}
if event.Op&fsnotify.Write == fsnotify.Write {
log.Debug("autohosts: modified: %s", event.Name)
a.updateHosts()
log.Debug("etchostscontainer: modified: %s", event.Name)
ehc.updateHosts()
}
case err, ok := <-a.watcher.Errors:
case err, ok := <-ehc.watcher.Errors:
if !ok {
return
}
log.Error("autohosts: %s", err)
log.Error("etchostscontainer: %s", err)
}
}
}
// updateHosts - loads system hosts
func (a *AutoHosts) updateHosts() {
func (ehc *EtcHostsContainer) updateHosts() {
table := make(map[string][]net.IP)
tableRev := make(map[string][]string)
a.load(table, tableRev, a.hostsFn)
ehc.load(table, tableRev, ehc.hostsFn)
for _, dir := range a.hostsDirs {
for _, dir := range ehc.hostsDirs {
fis, err := ioutil.ReadDir(dir)
if err != nil {
if !errors.Is(err, os.ErrNotExist) {
log.Error("autohosts: Opening directory: %q: %s", dir, err)
log.Error("etchostscontainer: Opening directory: %q: %s", dir, err)
}
continue
}
for _, fi := range fis {
a.load(table, tableRev, filepath.Join(dir, fi.Name()))
ehc.load(table, tableRev, filepath.Join(dir, fi.Name()))
}
}
func() {
a.lock.Lock()
defer a.lock.Unlock()
ehc.lock.Lock()
defer ehc.lock.Unlock()
a.table = table
a.tableReverse = tableRev
ehc.table = table
ehc.tableReverse = tableRev
}()
a.notify()
ehc.notify()
}

View File

@ -1,4 +1,4 @@
package util
package aghnet
import (
"io/ioutil"
@ -43,8 +43,8 @@ func assertWriting(t *testing.T, f *os.File, strs ...string) {
}
}
func TestAutoHostsResolution(t *testing.T) {
ah := &AutoHosts{}
func TestEtcHostsContainerResolution(t *testing.T) {
ehc := &EtcHostsContainer{}
f := prepareTestFile(t)
@ -52,25 +52,25 @@ func TestAutoHostsResolution(t *testing.T) {
" 127.0.0.1 host localhost # comment \n",
" ::1 localhost#comment \n",
)
ah.Init(f.Name())
ehc.Init(f.Name())
t.Run("existing_host", func(t *testing.T) {
ips := ah.Process("localhost", dns.TypeA)
ips := ehc.Process("localhost", dns.TypeA)
require.Len(t, ips, 1)
assert.Equal(t, net.IPv4(127, 0, 0, 1), ips[0])
})
t.Run("unknown_host", func(t *testing.T) {
ips := ah.Process("newhost", dns.TypeA)
ips := ehc.Process("newhost", dns.TypeA)
assert.Nil(t, ips)
// Comment.
ips = ah.Process("comment", dns.TypeA)
ips = ehc.Process("comment", dns.TypeA)
assert.Nil(t, ips)
})
t.Run("hosts_file", func(t *testing.T) {
names, ok := ah.List()["127.0.0.1"]
names, ok := ehc.List()["127.0.0.1"]
require.True(t, ok)
assert.Equal(t, []string{"host", "localhost"}, names)
})
@ -90,29 +90,29 @@ func TestAutoHostsResolution(t *testing.T) {
require.Nil(t, err)
a = strings.TrimSuffix(a, ".")
hosts := ah.ProcessReverse(a, dns.TypePTR)
hosts := ehc.ProcessReverse(a, dns.TypePTR)
require.Len(t, hosts, tc.wantLen)
assert.Equal(t, tc.wantHost, hosts[0])
}
})
}
func TestAutoHostsFSNotify(t *testing.T) {
ah := &AutoHosts{}
func TestEtcHostsContainerFSNotify(t *testing.T) {
ehc := &EtcHostsContainer{}
f := prepareTestFile(t)
assertWriting(t, f, " 127.0.0.1 host localhost \n")
ah.Init(f.Name())
ehc.Init(f.Name())
t.Run("unknown_host", func(t *testing.T) {
ips := ah.Process("newhost", dns.TypeA)
ips := ehc.Process("newhost", dns.TypeA)
assert.Nil(t, ips)
})
// Start monitoring for changes.
ah.Start()
t.Cleanup(ah.Close)
ehc.Start()
t.Cleanup(ehc.Close)
assertWriting(t, f, "127.0.0.2 newhost\n")
require.Nil(t, f.Sync())
@ -122,7 +122,7 @@ func TestAutoHostsFSNotify(t *testing.T) {
time.Sleep(50 * time.Millisecond)
t.Run("notified", func(t *testing.T) {
ips := ah.Process("newhost", dns.TypeA)
ips := ehc.Process("newhost", dns.TypeA)
assert.NotNil(t, ips)
require.Len(t, ips, 1)
assert.True(t, net.IP{127, 0, 0, 2}.Equal(ips[0]))

View File

@ -13,7 +13,7 @@ import (
"strings"
"sync"
"github.com/AdguardTeam/AdGuardHome/internal/util"
"github.com/AdguardTeam/AdGuardHome/internal/aghnet"
"github.com/AdguardTeam/dnsproxy/upstream"
"github.com/AdguardTeam/golibs/cache"
"github.com/AdguardTeam/golibs/log"
@ -65,8 +65,9 @@ type Config struct {
// Per-client settings can override this configuration.
BlockedServices []string `yaml:"blocked_services"`
// IP-hostname pairs taken from system configuration (e.g. /etc/hosts) files
AutoHosts *util.AutoHosts `yaml:"-"`
// EtcHosts is a container of IP-hostname pairs taken from the operating
// system configuration files (e.g. /etc/hosts).
EtcHosts *aghnet.EtcHostsContainer `yaml:"-"`
// Called when the configuration is changed by HTTP request
ConfigModified func() `yaml:"-"`
@ -428,11 +429,11 @@ func (d *DNSFilter) checkAutoHosts(
qtype uint16,
_ *FilteringSettings,
) (res Result, err error) {
if d.Config.AutoHosts == nil {
if d.Config.EtcHosts == nil {
return Result{}, nil
}
ips := d.Config.AutoHosts.Process(host, qtype)
ips := d.Config.EtcHosts.Process(host, qtype)
if ips != nil {
res = Result{
Reason: RewrittenAutoHosts,
@ -442,7 +443,7 @@ func (d *DNSFilter) checkAutoHosts(
return res, nil
}
revHosts := d.Config.AutoHosts.ProcessReverse(host, qtype)
revHosts := d.Config.EtcHosts.ProcessReverse(host, qtype)
if len(revHosts) != 0 {
res = Result{
Reason: RewrittenAutoHosts,

View File

@ -23,7 +23,6 @@ import (
"github.com/AdguardTeam/AdGuardHome/internal/aghtest"
"github.com/AdguardTeam/AdGuardHome/internal/dhcpd"
"github.com/AdguardTeam/AdGuardHome/internal/dnsfilter"
"github.com/AdguardTeam/AdGuardHome/internal/util"
"github.com/AdguardTeam/dnsproxy/proxy"
"github.com/AdguardTeam/dnsproxy/upstream"
"github.com/miekg/dns"
@ -1074,7 +1073,7 @@ func TestPTRResponseFromDHCPLeases(t *testing.T) {
func TestPTRResponseFromHosts(t *testing.T) {
c := dnsfilter.Config{
AutoHosts: &util.AutoHosts{},
EtcHosts: &aghnet.EtcHostsContainer{},
}
// Prepare test hosts file.
@ -1090,8 +1089,8 @@ func TestPTRResponseFromHosts(t *testing.T) {
_, _ = hf.WriteString(" ::1 localhost#comment \n")
// Init auto hosts.
c.AutoHosts.Init(hf.Name())
t.Cleanup(c.AutoHosts.Close)
c.EtcHosts.Init(hf.Name())
t.Cleanup(c.EtcHosts.Close)
var snd *aghnet.SubnetDetector
snd, err = aghnet.NewSubnetDetector()

View File

@ -18,7 +18,6 @@ import (
"github.com/AdguardTeam/AdGuardHome/internal/dnsfilter"
"github.com/AdguardTeam/AdGuardHome/internal/dnsforward"
"github.com/AdguardTeam/AdGuardHome/internal/querylog"
"github.com/AdguardTeam/AdGuardHome/internal/util"
"github.com/AdguardTeam/dnsproxy/proxy"
"github.com/AdguardTeam/dnsproxy/upstream"
"github.com/AdguardTeam/golibs/log"
@ -92,7 +91,7 @@ type clientsContainer struct {
// dnsServer is used for checking clients IP status access list status
dnsServer *dnsforward.Server
autoHosts *util.AutoHosts // get entries from system hosts-files
etcHosts *aghnet.EtcHostsContainer // get entries from system hosts-files
testing bool // if TRUE, this object is used for internal tests
}
@ -100,7 +99,11 @@ type clientsContainer struct {
// Init initializes clients container
// dhcpServer: optional
// Note: this function must be called only once
func (clients *clientsContainer) Init(objects []clientObject, dhcpServer *dhcpd.Server, autoHosts *util.AutoHosts) {
func (clients *clientsContainer) Init(
objects []clientObject,
dhcpServer *dhcpd.Server,
etcHosts *aghnet.EtcHostsContainer,
) {
if clients.list != nil {
log.Fatal("clients.list != nil")
}
@ -114,7 +117,9 @@ func (clients *clientsContainer) Init(objects []clientObject, dhcpServer *dhcpd.
}
clients.dhcpServer = dhcpServer
clients.autoHosts = autoHosts
if etcHosts != nil {
clients.etcHosts = etcHosts
}
clients.addFromConfig(objects)
if !clients.testing {
@ -122,7 +127,9 @@ func (clients *clientsContainer) Init(objects []clientObject, dhcpServer *dhcpd.
if clients.dhcpServer != nil {
clients.dhcpServer.SetOnLeaseChanged(clients.onDHCPLeaseChanged)
}
clients.autoHosts.SetOnChanged(clients.onHostsChanged)
if clients.etcHosts != nil {
clients.etcHosts.SetOnChanged(clients.onHostsChanged)
}
}
}
@ -692,7 +699,11 @@ func (clients *clientsContainer) rmHostsBySrc(src clientSource) {
// addFromHostsFile fills the client-hostname pairing index from the system's
// hosts files.
func (clients *clientsContainer) addFromHostsFile() {
hosts := clients.autoHosts.List()
if clients.etcHosts == nil {
return
}
hosts := clients.etcHosts.List()
clients.lock.Lock()
defer clients.lock.Unlock()

View File

@ -57,7 +57,7 @@ func initDNSServer() error {
Context.queryLog = querylog.New(conf)
filterConf := config.DNS.DnsfilterConf
filterConf.AutoHosts = &Context.autoHosts
filterConf.EtcHosts = Context.etcHosts
filterConf.ConfigModified = onConfigModified
filterConf.HTTPRegister = httpRegister
Context.dnsFilter = dnsfilter.New(&filterConf, nil)

View File

@ -46,19 +46,19 @@ type homeContext struct {
// Modules
// --
clients clientsContainer // per-client-settings module
stats stats.Stats // statistics module
queryLog querylog.QueryLog // query log module
dnsServer *dnsforward.Server // DNS module
rdns *RDNS // rDNS module
whois *Whois // WHOIS module
dnsFilter *dnsfilter.DNSFilter // DNS filtering module
dhcpServer *dhcpd.Server // DHCP module
auth *Auth // HTTP authentication module
filters Filtering // DNS filtering module
web *Web // Web (HTTP, HTTPS) module
tls *TLSMod // TLS module
autoHosts util.AutoHosts // IP-hostname pairs taken from system configuration (e.g. /etc/hosts) files
clients clientsContainer // per-client-settings module
stats stats.Stats // statistics module
queryLog querylog.QueryLog // query log module
dnsServer *dnsforward.Server // DNS module
rdns *RDNS // rDNS module
whois *Whois // WHOIS module
dnsFilter *dnsfilter.DNSFilter // DNS filtering module
dhcpServer *dhcpd.Server // DHCP module
auth *Auth // HTTP authentication module
filters Filtering // DNS filtering module
web *Web // Web (HTTP, HTTPS) module
tls *TLSMod // TLS module
etcHosts *aghnet.EtcHostsContainer // IP-hostname pairs taken from system configuration (e.g. /etc/hosts) files
updater *updater.Updater
subnetDetector *aghnet.SubnetDetector
@ -186,8 +186,6 @@ func setupConfig(args options) {
log.Fatalf("can't initialize dhcp module")
}
Context.autoHosts.Init("")
Context.updater = updater.NewUpdater(&updater.Config{
Client: Context.client,
Version: version.Version(),
@ -200,7 +198,11 @@ func setupConfig(args options) {
ConfName: config.getConfigFilename(),
})
Context.clients.Init(config.Clients, Context.dhcpServer, &Context.autoHosts)
if !args.noEtcHosts {
Context.etcHosts = &aghnet.EtcHostsContainer{}
Context.etcHosts.Init("")
Context.clients.Init(config.Clients, Context.dhcpServer, Context.etcHosts)
}
config.Clients = nil
if (runtime.GOOS == "linux" || runtime.GOOS == "darwin") &&
@ -317,7 +319,7 @@ func run(args options) {
}
Context.tls.Start()
Context.autoHosts.Start()
Context.etcHosts.Start()
go func() {
serr := startDNSServer()
@ -530,7 +532,7 @@ func cleanup(ctx context.Context) {
Context.dhcpServer.Stop()
}
Context.autoHosts.Close()
Context.etcHosts.Close()
if Context.tls != nil {
Context.tls.Close()

View File

@ -32,6 +32,10 @@ type options struct {
disableMemoryOptimization bool
glinetMode bool // Activate GL-Inet compatibility mode
// noEtcHosts flag should be provided when /etc/hosts file shouldn't be
// used.
noEtcHosts bool
}
// functions used for their side-effects
@ -191,7 +195,7 @@ var glinetArg = arg{
}
var versionArg = arg{
description: "Show the version and exit",
description: "Show the version and exit. Show more detailed version description with -v",
longName: "version",
shortName: "",
updateWithValue: nil,
@ -212,7 +216,7 @@ var versionArg = arg{
}
var helpArg = arg{
"Print this help. Show more detailed version description with -v",
"Print this help",
"help", "",
nil, nil, func(o options, exec string) (effect, error) {
return func() error { _ = printHelp(exec); os.Exit(64); return nil }, nil
@ -220,6 +224,16 @@ var helpArg = arg{
func(o options) []string { return nil },
}
var noEtcHostsArg = arg{
description: "Do not use the OS-provided hosts.",
longName: "no-etc-hosts",
shortName: "",
updateWithValue: nil,
updateNoValue: func(o options) (options, error) { o.noEtcHosts = true; return o, nil },
effect: nil,
serialize: func(o options) []string { return boolSliceOrNil(o.noEtcHosts) },
}
func init() {
args = []arg{
configArg,
@ -232,6 +246,7 @@ func init() {
checkConfigArg,
noCheckUpdateArg,
disableMemoryOptimizationArg,
noEtcHostsArg,
verboseArg,
glinetArg,
versionArg,

View File

@ -1,3 +1,7 @@
// Package util contains various utilities.
//
// TODO(a.garipov): Such packages are widely considered an antipattern. Remove
// this when we refactor our project structure.
package util
import (