diff --git a/AGHTechDoc.md b/AGHTechDoc.md index 7d223c5b..5d812e6b 100644 --- a/AGHTechDoc.md +++ b/AGHTechDoc.md @@ -56,6 +56,7 @@ Contents: * API: Get filtering parameters * API: Set filtering parameters * API: Set URL parameters + * API: Domain Check * Log-in page * API: Log in * API: Log out @@ -1355,6 +1356,30 @@ Response: 200 OK +### API: Domain Check + +Check if host name is filtered. + +Request: + + GET /control/filtering/check_host?name=hostname + +Response: + + 200 OK + + { + "reason":"FilteredBlackList", + "filter_id":1, + "rule":"||doubleclick.net^", + "service_name": "...", // set if reason=FilteredBlockedService + + // if reason=ReasonRewrite: + "cname": "...", + "ip_addrs": ["1.2.3.4", ...], + } + + ## Log-in page After user completes the steps of installation wizard, he must log in into dashboard using his name and password. After user successfully logs in, he gets the Cookie which allows the server to authenticate him next time without password. After the Cookie is expired, user needs to perform log-in operation again. diff --git a/home/control_filtering.go b/home/control_filtering.go index 6188c875..77c6cafa 100644 --- a/home/control_filtering.go +++ b/home/control_filtering.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" "io/ioutil" + "net" "net/http" "net/url" "os" @@ -11,6 +12,7 @@ import ( "time" "github.com/AdguardTeam/golibs/log" + "github.com/miekg/dns" ) // IsValidURL - return TRUE if URL is valid @@ -290,15 +292,58 @@ func handleFilteringConfig(w http.ResponseWriter, r *http.Request) { enableFilters(true) } +type checkHostResp struct { + Reason string `json:"reason"` + FilterID int64 `json:"filter_id"` + Rule string `json:"rule"` + + // for FilteredBlockedService: + SvcName string `json:"service_name"` + + // for ReasonRewrite: + CanonName string `json:"cname"` // CNAME value + IPList []net.IP `json:"ip_addrs"` // list of IP addresses +} + +func handleCheckHost(w http.ResponseWriter, r *http.Request) { + q := r.URL.Query() + host := q.Get("name") + + setts := Context.dnsFilter.GetConfig() + setts.FilteringEnabled = true + ApplyBlockedServices(&setts, config.DNS.BlockedServices) + result, err := Context.dnsFilter.CheckHost(host, dns.TypeA, &setts) + if err != nil { + httpError(w, http.StatusInternalServerError, "couldn't apply filtering: %s: %s", host, err) + return + } + + resp := checkHostResp{} + resp.Reason = result.Reason.String() + resp.FilterID = result.FilterID + resp.Rule = result.Rule + resp.SvcName = result.ServiceName + resp.CanonName = result.CanonName + resp.IPList = result.IPList + js, err := json.Marshal(resp) + if err != nil { + httpError(w, http.StatusInternalServerError, "json encode: %s", err) + return + } + w.Header().Set("Content-Type", "application/json") + _, _ = w.Write(js) +} + // RegisterFilteringHandlers - register handlers func RegisterFilteringHandlers() { - httpRegister(http.MethodGet, "/control/filtering/status", handleFilteringStatus) - httpRegister(http.MethodPost, "/control/filtering/config", handleFilteringConfig) - httpRegister(http.MethodPost, "/control/filtering/add_url", handleFilteringAddURL) - httpRegister(http.MethodPost, "/control/filtering/remove_url", handleFilteringRemoveURL) - httpRegister(http.MethodPost, "/control/filtering/set_url", handleFilteringSetURL) - httpRegister(http.MethodPost, "/control/filtering/refresh", handleFilteringRefresh) - httpRegister(http.MethodPost, "/control/filtering/set_rules", handleFilteringSetRules) + httpRegister("GET", "/control/filtering/status", handleFilteringStatus) + httpRegister("POST", "/control/filtering/config", handleFilteringConfig) + httpRegister("POST", "/control/filtering/add_url", handleFilteringAddURL) + httpRegister("POST", "/control/filtering/remove_url", handleFilteringRemoveURL) + httpRegister("POST", "/control/filtering/set_url", handleFilteringSetURL) + httpRegister("POST", "/control/filtering/refresh", handleFilteringRefresh) + httpRegister("POST", "/control/filtering/set_rules", handleFilteringSetRules) + httpRegister("GET", "/control/filtering/check_host", handleCheckHost) } func checkFiltersUpdateIntervalHours(i uint32) bool { diff --git a/openapi/openapi.yaml b/openapi/openapi.yaml index 2d042c62..9ad2c5d1 100644 --- a/openapi/openapi.yaml +++ b/openapi/openapi.yaml @@ -2,7 +2,7 @@ swagger: '2.0' info: title: 'AdGuard Home' description: 'AdGuard Home REST API. Admin web interface is built on top of this REST API.' - version: '0.99.3' + version: '0.101' schemes: - http basePath: /control @@ -594,6 +594,22 @@ paths: 200: description: OK + /filtering/check_host: + get: + tags: + - filtering + operationId: filteringCheckHost + summary: 'Check if host name is filtered' + parameters: + - name: name + in: query + type: string + responses: + 200: + description: OK + schema: + $ref: "#/definitions/FilterCheckHostResponse" + # -------------------------------------------------- # Safebrowsing methods # -------------------------------------------------- @@ -1178,6 +1194,42 @@ definitions: enabled: type: "boolean" + FilterCheckHostResponse: + type: "object" + description: "Check Host Result" + properties: + reason: + type: "string" + description: "DNS filter status" + enum: + - "NotFilteredNotFound" + - "NotFilteredWhiteList" + - "NotFilteredError" + - "FilteredBlackList" + - "FilteredSafeBrowsing" + - "FilteredParental" + - "FilteredInvalid" + - "FilteredSafeSearch" + - "FilteredBlockedService" + - "ReasonRewrite" + filter_id: + type: "integer" + rule: + type: "string" + example: "||example.org^" + description: "Filtering rule applied to the request (if any)" + service_name: + type: "string" + description: "Set if reason=FilteredBlockedService" + cname: + type: "string" + description: "Set if reason=ReasonRewrite" + ip_addrs: + type: "array" + items: + type: "string" + description: "Set if reason=ReasonRewrite" + GetVersionRequest: type: "object" description: "/version.json request data" @@ -1471,6 +1523,7 @@ definitions: - "FilteredInvalid" - "FilteredSafeSearch" - "FilteredBlockedService" + - "ReasonRewrite" service_name: type: "string" description: "Set if reason=FilteredBlockedService"