diff --git a/AGHTechDoc.md b/AGHTechDoc.md index c6f615f3..f4e4d4c7 100644 --- a/AGHTechDoc.md +++ b/AGHTechDoc.md @@ -24,6 +24,9 @@ Contents: * "Enable DHCP" command * Static IP check/set * Add a static lease +* DNS access settings + * List access settings + * Set access settings ## First startup @@ -626,3 +629,47 @@ Response: Error response (Client not found): 400 + + +## DNS access settings + +There are low-level settings that can block undesired DNS requests. "Blocking" means not responding to request. + +There are 3 types of access settings: +* allowed_clients: Only these clients are allowed to make DNS requests. +* disallowed_clients: These clients are not allowed to make DNS requests. +* blocked_hosts: These hosts are not allowed to be resolved by a DNS request. + + +### List access settings + +Request: + + GET /control/access/list + +Response: + + 200 OK + + { + allowed_clients: ["127.0.0.1", ...] + disallowed_clients: ["127.0.0.1", ...] + blocked_hosts: ["host.com", ...] + } + + +### Set access settings + +Request: + + POST /control/access/set + + { + allowed_clients: ["127.0.0.1", ...] + disallowed_clients: ["127.0.0.1", ...] + blocked_hosts: ["host.com", ...] + } + +Response: + + 200 OK diff --git a/control.go b/control.go index 77970de2..e1113968 100644 --- a/control.go +++ b/control.go @@ -996,6 +996,9 @@ func registerControlHandlers() { http.HandleFunc("/control/dhcp/add_static_lease", postInstall(optionalAuth(ensurePOST(handleDHCPAddStaticLease)))) http.HandleFunc("/control/dhcp/remove_static_lease", postInstall(optionalAuth(ensurePOST(handleDHCPRemoveStaticLease)))) + http.HandleFunc("/control/access/list", postInstall(optionalAuth(ensureGET(handleAccessList)))) + http.HandleFunc("/control/access/set", postInstall(optionalAuth(ensurePOST(handleAccessSet)))) + RegisterTLSHandlers() RegisterClientsHandlers() diff --git a/control_access.go b/control_access.go new file mode 100644 index 00000000..0c6fd800 --- /dev/null +++ b/control_access.go @@ -0,0 +1,87 @@ +package main + +import ( + "encoding/json" + "net" + "net/http" + + "github.com/AdguardTeam/golibs/log" +) + +type accessListJSON struct { + AllowedClients []string `json:"allowed_clients"` + DisallowedClients []string `json:"disallowed_clients"` + BlockedHosts []string `json:"blocked_hosts"` +} + +func handleAccessList(w http.ResponseWriter, r *http.Request) { + log.Tracef("%s %v", r.Method, r.URL) + + controlLock.Lock() + j := accessListJSON{ + AllowedClients: config.DNS.AllowedClients, + DisallowedClients: config.DNS.DisallowedClients, + BlockedHosts: config.DNS.BlockedHosts, + } + controlLock.Unlock() + + w.Header().Set("Content-Type", "application/json") + err := json.NewEncoder(w).Encode(j) + if err != nil { + httpError(w, http.StatusInternalServerError, "json.Encode: %s", err) + return + } +} + +func checkIPCIDRArray(src []string) error { + for _, s := range src { + ip := net.ParseIP(s) + if ip != nil { + continue + } + + _, _, err := net.ParseCIDR(s) + if err != nil { + return err + } + } + + return nil +} + +func handleAccessSet(w http.ResponseWriter, r *http.Request) { + log.Tracef("%s %v", r.Method, r.URL) + + j := accessListJSON{} + err := json.NewDecoder(r.Body).Decode(&j) + if err != nil { + httpError(w, http.StatusBadRequest, "json.Decode: %s", err) + return + } + + err = checkIPCIDRArray(j.AllowedClients) + if err == nil { + err = checkIPCIDRArray(j.DisallowedClients) + } + if err != nil { + httpError(w, http.StatusBadRequest, "%s", err) + return + } + + config.Lock() + config.DNS.AllowedClients = j.AllowedClients + config.DNS.DisallowedClients = j.DisallowedClients + config.DNS.BlockedHosts = j.BlockedHosts + config.Unlock() + + log.Tracef("Update access lists: %d, %d, %d", + len(j.AllowedClients), len(j.DisallowedClients), len(j.BlockedHosts)) + + err = writeAllConfigsAndReloadDNS() + if err != nil { + httpError(w, http.StatusBadRequest, "%s", err) + return + } + + returnOK(w) +}