Skip to content

Commit

Permalink
Merge: + Reload configuration command; refactoring
Browse files Browse the repository at this point in the history
Close #1302

* commit 'dd7d9dc334181b3923b1532aaae51cae77d5ed55':
  * move getDNSAddresses() and "/dns-query" handler to DNS module
  * TLS is now a separate module (logically)
  * move HTTP server code
  * refactor: move blocked-services functions to dnsfilter
  * refactor
  + service: support "-s reload" command
  + clients: re-read auto-clients from /etc/hosts when SIGHUP is received
  • Loading branch information
szolin committed Mar 17, 2020
2 parents e5db337 + dd7d9dc commit 32baa90
Show file tree
Hide file tree
Showing 20 changed files with 724 additions and 422 deletions.
1 change: 0 additions & 1 deletion AGHTechDoc.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ Contents:
![](doc/agh-arch.png)



## First startup

The first application startup is detected when there's no .yaml configuration file.
Expand Down
10 changes: 7 additions & 3 deletions dhcpd/dhcpd.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import (
const defaultDiscoverTime = time.Second * 3
const leaseExpireStatic = 1

var webHandlersRegistered = false

// Lease contains the necessary information about a DHCP lease
// field ordering is important -- yaml fields will mirror ordering from here
type Lease struct {
Expand Down Expand Up @@ -121,9 +123,6 @@ func Create(config ServerConfig) *Server {
return nil
}
}
if s.conf.HTTPRegister != nil {
s.registerHandlers()
}

// we can't delay database loading until DHCP server is started,
// because we need static leases functionality available beforehand
Expand Down Expand Up @@ -221,6 +220,11 @@ func (s *Server) setConfig(config ServerConfig) error {
// Start will listen on port 67 and serve DHCP requests.
func (s *Server) Start() error {

if !webHandlersRegistered && s.conf.HTTPRegister != nil {
webHandlersRegistered = true
s.registerHandlers()
}

// TODO: don't close if interface and addresses are the same
if s.conn != nil {
s.closeConn()
Expand Down
56 changes: 27 additions & 29 deletions home/blocked_services.go → dnsfilter/blocked_services.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
package home
package dnsfilter

import (
"encoding/json"
"net/http"

"github.com/AdguardTeam/AdGuardHome/dnsfilter"
"github.com/AdguardTeam/golibs/log"
"github.com/AdguardTeam/urlfilter/rules"
)
Expand Down Expand Up @@ -119,7 +118,7 @@ var serviceRulesArray = []svc{
}

// convert array to map
func initServices() {
func initBlockedServices() {
serviceRules = make(map[string][]*rules.NetworkRule)
for _, s := range serviceRulesArray {
netRules := []*rules.NetworkRule{}
Expand All @@ -135,15 +134,20 @@ func initServices() {
}
}

// Return TRUE if a blocked service name is known
func blockedSvcKnown(s string) bool {
// BlockedSvcKnown - return TRUE if a blocked service name is known
func BlockedSvcKnown(s string) bool {
_, ok := serviceRules[s]
return ok
}

// ApplyBlockedServices - set blocked services settings for this DNS request
func ApplyBlockedServices(setts *dnsfilter.RequestFilteringSettings, list []string) {
setts.ServicesRules = []dnsfilter.ServiceEntry{}
func (d *Dnsfilter) ApplyBlockedServices(setts *RequestFilteringSettings, list []string, global bool) {
setts.ServicesRules = []ServiceEntry{}
if global {
d.confLock.RLock()
defer d.confLock.RUnlock()
list = d.Config.BlockedServices
}
for _, name := range list {
rules, ok := serviceRules[name]

Expand All @@ -152,51 +156,45 @@ func ApplyBlockedServices(setts *dnsfilter.RequestFilteringSettings, list []stri
continue
}

s := dnsfilter.ServiceEntry{}
s := ServiceEntry{}
s.Name = name
s.Rules = rules
setts.ServicesRules = append(setts.ServicesRules, s)
}
}

func handleBlockedServicesList(w http.ResponseWriter, r *http.Request) {
config.RLock()
list := config.DNS.BlockedServices
config.RUnlock()
func (d *Dnsfilter) handleBlockedServicesList(w http.ResponseWriter, r *http.Request) {
d.confLock.RLock()
list := d.Config.BlockedServices
d.confLock.RUnlock()

w.Header().Set("Content-Type", "application/json")
err := json.NewEncoder(w).Encode(list)
if err != nil {
httpError(w, http.StatusInternalServerError, "json.Encode: %s", err)
httpError(r, w, http.StatusInternalServerError, "json.Encode: %s", err)
return
}
}

func handleBlockedServicesSet(w http.ResponseWriter, r *http.Request) {
func (d *Dnsfilter) handleBlockedServicesSet(w http.ResponseWriter, r *http.Request) {
list := []string{}
err := json.NewDecoder(r.Body).Decode(&list)
if err != nil {
httpError(w, http.StatusBadRequest, "json.Decode: %s", err)
httpError(r, w, http.StatusBadRequest, "json.Decode: %s", err)
return
}

config.Lock()
config.DNS.BlockedServices = list
config.Unlock()
d.confLock.Lock()
d.Config.BlockedServices = list
d.confLock.Unlock()

log.Debug("Updated blocked services list: %d", len(list))

err = writeAllConfigsAndReloadDNS()
if err != nil {
httpError(w, http.StatusBadRequest, "%s", err)
return
}

httpOK(r, w)
d.ConfigModified()
}

// RegisterBlockedServicesHandlers - register HTTP handlers
func RegisterBlockedServicesHandlers() {
httpRegister(http.MethodGet, "/control/blocked_services/list", handleBlockedServicesList)
httpRegister(http.MethodPost, "/control/blocked_services/set", handleBlockedServicesSet)
// registerBlockedServicesHandlers - register HTTP handlers
func (d *Dnsfilter) registerBlockedServicesHandlers() {
d.Config.HTTPRegister("GET", "/control/blocked_services/list", d.handleBlockedServicesList)
d.Config.HTTPRegister("POST", "/control/blocked_services/set", d.handleBlockedServicesSet)
}
18 changes: 18 additions & 0 deletions dnsfilter/dnsfilter.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ type Config struct {

Rewrites []RewriteEntry `yaml:"rewrites"`

// Names of services to block (globally).
// Per-client settings can override this configuration.
BlockedServices []string `yaml:"blocked_services"`

// Called when the configuration is changed by HTTP request
ConfigModified func() `yaml:"-"`

Expand Down Expand Up @@ -175,6 +179,7 @@ func (d *Dnsfilter) WriteDiskConfig(c *Config) {
d.confLock.Lock()
*c = d.Config
c.Rewrites = rewriteArrayDup(d.Config.Rewrites)
// BlockedServices
d.confLock.Unlock()
}

Expand Down Expand Up @@ -633,6 +638,18 @@ func New(c *Config, blockFilters []Filter) *Dnsfilter {
d.prepareRewrites()
}

bsvcs := []string{}
for _, s := range d.BlockedServices {
if !BlockedSvcKnown(s) {
log.Debug("skipping unknown blocked-service '%s'", s)
continue
}
bsvcs = append(bsvcs, s)
}
d.BlockedServices = bsvcs

initBlockedServices()

if blockFilters != nil {
err := d.initFiltering(nil, blockFilters)
if err != nil {
Expand All @@ -655,6 +672,7 @@ func (d *Dnsfilter) Start() {
if d.Config.HTTPRegister != nil { // for tests
d.registerSecurityHandlers()
d.registerRewritesHandlers()
d.registerBlockedServicesHandlers()
}
}

Expand Down
1 change: 1 addition & 0 deletions dnsforward/dnsforward.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ type ServerConfig struct {

FilteringConfig
TLSConfig
TLSAllowUnencryptedDOH bool

TLSv12Roots *x509.CertPool // list of root CAs for TLSv1.2

Expand Down
16 changes: 16 additions & 0 deletions dnsforward/dnsforward_http.go
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,20 @@ func checkDNS(input string, bootstrap []string) error {
return nil
}

func (s *Server) handleDOH(w http.ResponseWriter, r *http.Request) {
if !s.conf.TLSAllowUnencryptedDOH && r.TLS == nil {
httpError(r, w, http.StatusNotFound, "Not Found")
return
}

if !s.IsRunning() {
httpError(r, w, http.StatusInternalServerError, "DNS server is not running")
return
}

s.ServeHTTP(w, r)
}

func (s *Server) registerHandlers() {
s.conf.HTTPRegister("GET", "/control/dns_info", s.handleGetConfig)
s.conf.HTTPRegister("POST", "/control/dns_config", s.handleSetConfig)
Expand All @@ -384,4 +398,6 @@ func (s *Server) registerHandlers() {

s.conf.HTTPRegister("GET", "/control/access/list", s.handleAccessList)
s.conf.HTTPRegister("POST", "/control/access/set", s.handleAccessSet)

s.conf.HTTPRegister("", "/dns-query", s.handleDOH)
}
28 changes: 22 additions & 6 deletions home/clients.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"time"

"github.com/AdguardTeam/AdGuardHome/dhcpd"
"github.com/AdguardTeam/AdGuardHome/dnsfilter"
"github.com/AdguardTeam/AdGuardHome/dnsforward"
"github.com/AdguardTeam/dnsproxy/upstream"
"github.com/AdguardTeam/golibs/log"
Expand All @@ -24,6 +25,8 @@ const (
clientsUpdatePeriod = 1 * time.Hour
)

var webHandlersRegistered = false

// Client information
type Client struct {
IDs []string
Expand Down Expand Up @@ -98,13 +101,27 @@ func (clients *clientsContainer) Init(objects []clientObject, dhcpServer *dhcpd.
clients.addFromConfig(objects)

if !clients.testing {
go clients.periodicUpdate()

clients.addFromDHCP()
clients.dhcpServer.SetOnLeaseChanged(clients.onDHCPLeaseChanged)
}
}

clients.registerWebHandlers()
// Start - start the module
func (clients *clientsContainer) Start() {
if !clients.testing {
if !webHandlersRegistered {
webHandlersRegistered = true
clients.registerWebHandlers()
}
go clients.periodicUpdate()
}

}

// Reload - reload auto-clients
func (clients *clientsContainer) Reload() {
clients.addFromHostsFile()
clients.addFromSystemARP()
}

type clientObject struct {
Expand Down Expand Up @@ -145,7 +162,7 @@ func (clients *clientsContainer) addFromConfig(objects []clientObject) {
}

for _, s := range cy.BlockedServices {
if !blockedSvcKnown(s) {
if !dnsfilter.BlockedSvcKnown(s) {
log.Debug("Clients: skipping unknown blocked-service '%s'", s)
continue
}
Expand Down Expand Up @@ -194,8 +211,7 @@ func (clients *clientsContainer) WriteDiskConfig(objects *[]clientObject) {

func (clients *clientsContainer) periodicUpdate() {
for {
clients.addFromHostsFile()
clients.addFromSystemARP()
clients.Reload()
time.Sleep(clientsUpdatePeriod)
}
}
Expand Down
Loading

0 comments on commit 32baa90

Please sign in to comment.