Pull request: 4535-list-services
Updates #4535. * commit '986124948a21b5dfebb0bd6a9f948911b0a4b938': all: imp client, add api chlog filtering: imp code Add '/blocked_services/services' API
This commit is contained in:
@@ -1355,6 +1355,19 @@ Internally, all supported services are stored as a map:
|
|||||||
service name -> list of rules
|
service name -> list of rules
|
||||||
|
|
||||||
|
|
||||||
|
### API: Get blocked services list of available services
|
||||||
|
|
||||||
|
Request:
|
||||||
|
|
||||||
|
GET /control/blocked_services/services
|
||||||
|
|
||||||
|
Response:
|
||||||
|
|
||||||
|
200 OK
|
||||||
|
|
||||||
|
[ "name1", ... ]
|
||||||
|
|
||||||
|
|
||||||
### API: Get blocked services list
|
### API: Get blocked services list
|
||||||
|
|
||||||
Request:
|
Request:
|
||||||
|
|||||||
@@ -20,6 +20,11 @@ and this project adheres to
|
|||||||
- Weaker cipher suites that use the CBC (cipher block chaining) mode of
|
- Weaker cipher suites that use the CBC (cipher block chaining) mode of
|
||||||
operation have been disabled ([#2993]).
|
operation have been disabled ([#2993]).
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- A new HTTP API, `GET /control/blocked_services/services`, that lists all
|
||||||
|
available blocked services ([#4535]).
|
||||||
|
|
||||||
### Deprecated
|
### Deprecated
|
||||||
|
|
||||||
- Ports 784 and 8853 for DNS-over-QUIC in Docker images. Users who still serve
|
- Ports 784 and 8853 for DNS-over-QUIC in Docker images. Users who still serve
|
||||||
@@ -34,6 +39,7 @@ and this project adheres to
|
|||||||
- Unnecessary logging of non-critical statistics errors ([#4850]).
|
- Unnecessary logging of non-critical statistics errors ([#4850]).
|
||||||
|
|
||||||
[#2993]: https://github.com/AdguardTeam/AdGuardHome/issues/2993
|
[#2993]: https://github.com/AdguardTeam/AdGuardHome/issues/2993
|
||||||
|
[#4535]: https://github.com/AdguardTeam/AdGuardHome/issues/4535
|
||||||
[#4745]: https://github.com/AdguardTeam/AdGuardHome/issues/4745
|
[#4745]: https://github.com/AdguardTeam/AdGuardHome/issues/4745
|
||||||
[#4850]: https://github.com/AdguardTeam/AdGuardHome/issues/4850
|
[#4850]: https://github.com/AdguardTeam/AdGuardHome/issues/4850
|
||||||
|
|
||||||
@@ -59,7 +65,7 @@ See also the [v0.107.11 GitHub milestone][ms-v0.107.11].
|
|||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- DNS-over-QUIC connections now use keptalive.
|
- DNS-over-QUIC connections now use keepalive.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,21 @@ import { createAction } from 'redux-actions';
|
|||||||
import apiClient from '../api/Api';
|
import apiClient from '../api/Api';
|
||||||
import { addErrorToast, addSuccessToast } from './toasts';
|
import { addErrorToast, addSuccessToast } from './toasts';
|
||||||
|
|
||||||
|
export const getBlockedServicesAvailableServicesRequest = createAction('GET_BLOCKED_SERVICES_AVAILABLE_SERVICES_REQUEST');
|
||||||
|
export const getBlockedServicesAvailableServicesFailure = createAction('GET_BLOCKED_SERVICES_AVAILABLE_SERVICES_FAILURE');
|
||||||
|
export const getBlockedServicesAvailableServicesSuccess = createAction('GET_BLOCKED_SERVICES_AVAILABLE_SERVICES_SUCCESS');
|
||||||
|
|
||||||
|
export const getBlockedServicesAvailableServices = () => async (dispatch) => {
|
||||||
|
dispatch(getBlockedServicesAvailableServicesRequest());
|
||||||
|
try {
|
||||||
|
const data = await apiClient.getBlockedServicesAvailableServices();
|
||||||
|
dispatch(getBlockedServicesAvailableServicesSuccess(data));
|
||||||
|
} catch (error) {
|
||||||
|
dispatch(addErrorToast({ error }));
|
||||||
|
dispatch(getBlockedServicesAvailableServicesFailure());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export const getBlockedServicesRequest = createAction('GET_BLOCKED_SERVICES_REQUEST');
|
export const getBlockedServicesRequest = createAction('GET_BLOCKED_SERVICES_REQUEST');
|
||||||
export const getBlockedServicesFailure = createAction('GET_BLOCKED_SERVICES_FAILURE');
|
export const getBlockedServicesFailure = createAction('GET_BLOCKED_SERVICES_FAILURE');
|
||||||
export const getBlockedServicesSuccess = createAction('GET_BLOCKED_SERVICES_SUCCESS');
|
export const getBlockedServicesSuccess = createAction('GET_BLOCKED_SERVICES_SUCCESS');
|
||||||
|
|||||||
@@ -481,10 +481,17 @@ class Api {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Blocked services
|
// Blocked services
|
||||||
|
BLOCKED_SERVICES_SERVICES = { path: 'blocked_services/services', method: 'GET' };
|
||||||
|
|
||||||
BLOCKED_SERVICES_LIST = { path: 'blocked_services/list', method: 'GET' };
|
BLOCKED_SERVICES_LIST = { path: 'blocked_services/list', method: 'GET' };
|
||||||
|
|
||||||
BLOCKED_SERVICES_SET = { path: 'blocked_services/set', method: 'POST' };
|
BLOCKED_SERVICES_SET = { path: 'blocked_services/set', method: 'POST' };
|
||||||
|
|
||||||
|
getBlockedServicesAvailableServices() {
|
||||||
|
const { path, method } = this.BLOCKED_SERVICES_SERVICES;
|
||||||
|
return this.makeRequest(path, method);
|
||||||
|
}
|
||||||
|
|
||||||
getBlockedServices() {
|
getBlockedServices() {
|
||||||
const { path, method } = this.BLOCKED_SERVICES_LIST;
|
const { path, method } = this.BLOCKED_SERVICES_LIST;
|
||||||
return this.makeRequest(path, method);
|
return this.makeRequest(path, method);
|
||||||
|
|||||||
@@ -1,6 +1,18 @@
|
|||||||
// This file was autogenerated. Please do not change.
|
// This file was autogenerated. Please do not change.
|
||||||
// All changes will be overwrited on commit.
|
// All changes will be overwrited on commit.
|
||||||
export default class BlockedServicesApi {
|
export default class BlockedServicesApi {
|
||||||
|
static async blockedServicesAvailableServices(): Promise<string[] | Error> {
|
||||||
|
return await fetch(`/control/blocked_services/services`, {
|
||||||
|
method: 'GET',
|
||||||
|
}).then(async (res) => {
|
||||||
|
if (res.status === 200) {
|
||||||
|
return res.json();
|
||||||
|
} else {
|
||||||
|
return new Error(String(res.status));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
static async blockedServicesList(): Promise<string[] | Error> {
|
static async blockedServicesList(): Promise<string[] | Error> {
|
||||||
return await fetch(`/control/blocked_services/list`, {
|
return await fetch(`/control/blocked_services/list`, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
|
|||||||
@@ -7,19 +7,21 @@ import (
|
|||||||
"github.com/AdguardTeam/AdGuardHome/internal/aghhttp"
|
"github.com/AdguardTeam/AdGuardHome/internal/aghhttp"
|
||||||
"github.com/AdguardTeam/golibs/log"
|
"github.com/AdguardTeam/golibs/log"
|
||||||
"github.com/AdguardTeam/urlfilter/rules"
|
"github.com/AdguardTeam/urlfilter/rules"
|
||||||
|
"golang.org/x/exp/slices"
|
||||||
)
|
)
|
||||||
|
|
||||||
var serviceRules map[string][]*rules.NetworkRule // service name -> filtering rules
|
// svc represents a single blocked service.
|
||||||
|
|
||||||
type svc struct {
|
type svc struct {
|
||||||
name string
|
name string
|
||||||
rules []string
|
rules []string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// servicesData contains raw blocked service data.
|
||||||
|
//
|
||||||
// Keep in sync with:
|
// Keep in sync with:
|
||||||
// client/src/helpers/constants.js
|
// - client/src/helpers/constants.js
|
||||||
// client/src/components/ui/Icons.js
|
// - client/src/components/ui/Icons.js
|
||||||
var serviceRulesArray = []svc{{
|
var servicesData = []svc{{
|
||||||
name: "whatsapp",
|
name: "whatsapp",
|
||||||
rules: []string{
|
rules: []string{
|
||||||
"||wa.me^",
|
"||wa.me^",
|
||||||
@@ -365,21 +367,38 @@ var serviceRulesArray = []svc{{
|
|||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
|
|
||||||
// convert array to map
|
// serviceRules maps a service ID to its filtering rules.
|
||||||
|
var serviceRules map[string][]*rules.NetworkRule
|
||||||
|
|
||||||
|
// serviceIDs contains service IDs sorted alphabetically.
|
||||||
|
var serviceIDs []string
|
||||||
|
|
||||||
|
// initBlockedServices initializes package-level blocked service data.
|
||||||
func initBlockedServices() {
|
func initBlockedServices() {
|
||||||
serviceRules = make(map[string][]*rules.NetworkRule)
|
l := len(servicesData)
|
||||||
for _, s := range serviceRulesArray {
|
serviceIDs = make([]string, l)
|
||||||
netRules := []*rules.NetworkRule{}
|
serviceRules = make(map[string][]*rules.NetworkRule, l)
|
||||||
|
|
||||||
|
for i, s := range servicesData {
|
||||||
|
netRules := make([]*rules.NetworkRule, 0, len(s.rules))
|
||||||
for _, text := range s.rules {
|
for _, text := range s.rules {
|
||||||
rule, err := rules.NewNetworkRule(text, BlockedSvcsListID)
|
rule, err := rules.NewNetworkRule(text, BlockedSvcsListID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("rules.NewNetworkRule: %s rule: %s", err, text)
|
log.Error("parsing blocked service %q rule %q: %s", s.name, text, err)
|
||||||
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
netRules = append(netRules, rule)
|
netRules = append(netRules, rule)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
serviceIDs[i] = s.name
|
||||||
serviceRules[s.name] = netRules
|
serviceRules[s.name] = netRules
|
||||||
}
|
}
|
||||||
|
|
||||||
|
slices.Sort(serviceIDs)
|
||||||
|
|
||||||
|
log.Debug("filtering: initialized %d services", l)
|
||||||
}
|
}
|
||||||
|
|
||||||
// BlockedSvcKnown - return TRUE if a blocked service name is known
|
// BlockedSvcKnown - return TRUE if a blocked service name is known
|
||||||
@@ -411,6 +430,16 @@ func (d *DNSFilter) ApplyBlockedServices(setts *Settings, list []string, global
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *DNSFilter) handleBlockedServicesAvailableServices(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
err := json.NewEncoder(w).Encode(serviceIDs)
|
||||||
|
if err != nil {
|
||||||
|
aghhttp.Error(r, w, http.StatusInternalServerError, "encoding available services: %s", err)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (d *DNSFilter) handleBlockedServicesList(w http.ResponseWriter, r *http.Request) {
|
func (d *DNSFilter) handleBlockedServicesList(w http.ResponseWriter, r *http.Request) {
|
||||||
d.confLock.RLock()
|
d.confLock.RLock()
|
||||||
list := d.Config.BlockedServices
|
list := d.Config.BlockedServices
|
||||||
@@ -419,7 +448,7 @@ func (d *DNSFilter) handleBlockedServicesList(w http.ResponseWriter, r *http.Req
|
|||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
err := json.NewEncoder(w).Encode(list)
|
err := json.NewEncoder(w).Encode(list)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
aghhttp.Error(r, w, http.StatusInternalServerError, "json.Encode: %s", err)
|
aghhttp.Error(r, w, http.StatusInternalServerError, "encoding services: %s", err)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -445,6 +474,7 @@ func (d *DNSFilter) handleBlockedServicesSet(w http.ResponseWriter, r *http.Requ
|
|||||||
|
|
||||||
// registerBlockedServicesHandlers - register HTTP handlers
|
// registerBlockedServicesHandlers - register HTTP handlers
|
||||||
func (d *DNSFilter) registerBlockedServicesHandlers() {
|
func (d *DNSFilter) registerBlockedServicesHandlers() {
|
||||||
|
d.Config.HTTPRegister(http.MethodGet, "/control/blocked_services/services", d.handleBlockedServicesAvailableServices)
|
||||||
d.Config.HTTPRegister(http.MethodGet, "/control/blocked_services/list", d.handleBlockedServicesList)
|
d.Config.HTTPRegister(http.MethodGet, "/control/blocked_services/list", d.handleBlockedServicesList)
|
||||||
d.Config.HTTPRegister(http.MethodPost, "/control/blocked_services/set", d.handleBlockedServicesSet)
|
d.Config.HTTPRegister(http.MethodPost, "/control/blocked_services/set", d.handleBlockedServicesSet)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -296,9 +296,11 @@ func cloneRewrites(entries []*LegacyRewrite) (clone []*LegacyRewrite) {
|
|||||||
return clone
|
return clone
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetFilters - set new filters (synchronously or asynchronously)
|
// SetFilters sets new filters, synchronously or asynchronously. When filters
|
||||||
// When filters are set asynchronously, the old filters continue working until the new filters are ready.
|
// are set asynchronously, the old filters continue working until the new
|
||||||
// In this case the caller must ensure that the old filter files are intact.
|
// filters are ready.
|
||||||
|
//
|
||||||
|
// In this case the caller must ensure that the old filter files are intact.
|
||||||
func (d *DNSFilter) SetFilters(blockFilters, allowFilters []Filter, async bool) error {
|
func (d *DNSFilter) SetFilters(blockFilters, allowFilters []Filter, async bool) error {
|
||||||
if async {
|
if async {
|
||||||
params := filtersInitializerParams{
|
params := filtersInitializerParams{
|
||||||
|
|||||||
@@ -130,10 +130,9 @@ func matchDomainWildcard(host, wildcard string) (ok bool) {
|
|||||||
//
|
//
|
||||||
// The sorting priority:
|
// The sorting priority:
|
||||||
//
|
//
|
||||||
// A and AAAA > CNAME
|
// 1. A and AAAA > CNAME
|
||||||
// wildcard > exact
|
// 2. wildcard > exact
|
||||||
// lower level wildcard > higher level wildcard
|
// 3. lower level wildcard > higher level wildcard
|
||||||
//
|
|
||||||
type rewritesSorted []*LegacyRewrite
|
type rewritesSorted []*LegacyRewrite
|
||||||
|
|
||||||
// Len implements the sort.Interface interface for legacyRewritesSorted.
|
// Len implements the sort.Interface interface for legacyRewritesSorted.
|
||||||
|
|||||||
@@ -4,6 +4,15 @@
|
|||||||
|
|
||||||
## v0.108.0: API changes
|
## v0.108.0: API changes
|
||||||
|
|
||||||
|
## v0.107.12: API changes
|
||||||
|
|
||||||
|
### `GET /control/blocked_services/services`
|
||||||
|
|
||||||
|
* The new `GET /control/blocked_services/services` HTTP API allows inspecting
|
||||||
|
all available services.
|
||||||
|
|
||||||
|
## v0.107.7: API changes
|
||||||
|
|
||||||
### The new optional field `"ecs"` in `QueryLogItem`
|
### The new optional field `"ecs"` in `QueryLogItem`
|
||||||
|
|
||||||
* The new optional field `"ecs"` in `GET /control/querylog` contains the IP
|
* The new optional field `"ecs"` in `GET /control/querylog` contains the IP
|
||||||
|
|||||||
@@ -874,6 +874,19 @@
|
|||||||
'summary': 'Set (dis)allowed clients, blocked hosts, etc.'
|
'summary': 'Set (dis)allowed clients, blocked hosts, etc.'
|
||||||
'tags':
|
'tags':
|
||||||
- 'clients'
|
- 'clients'
|
||||||
|
'/blocked_services/services':
|
||||||
|
'get':
|
||||||
|
'tags':
|
||||||
|
- 'blocked_services'
|
||||||
|
'operationId': 'blockedServicesAvailableServices'
|
||||||
|
'summary': 'Get available services to use for blocking'
|
||||||
|
'responses':
|
||||||
|
'200':
|
||||||
|
'description': 'OK.'
|
||||||
|
'content':
|
||||||
|
'application/json':
|
||||||
|
'schema':
|
||||||
|
'$ref': '#/components/schemas/BlockedServicesArray'
|
||||||
'/blocked_services/list':
|
'/blocked_services/list':
|
||||||
'get':
|
'get':
|
||||||
'tags':
|
'tags':
|
||||||
|
|||||||
Reference in New Issue
Block a user