diff --git a/packages/adblock/Makefile b/packages/adblock/Makefile index e7afb7727..2a9f153fb 100644 --- a/packages/adblock/Makefile +++ b/packages/adblock/Makefile @@ -30,8 +30,6 @@ endef define Package/adblock/conffiles /etc/config/adblock -/etc/adblock/adblock.allowlist -/etc/adblock/adblock.blocklist /etc/adblock/adblock.custom.feeds endef @@ -56,14 +54,13 @@ define Package/adblock/install $(INSTALL_DIR) $(1)/etc/adblock $(INSTALL_BIN) ./files/adblock.mail $(1)/etc/adblock - $(INSTALL_CONF) ./files/adblock.allowlist $(1)/etc/adblock - $(INSTALL_CONF) ./files/adblock.blocklist $(1)/etc/adblock $(INSTALL_CONF) ./files/adblock.categories $(1)/etc/adblock $(INSTALL_CONF) ./files/adblock.feeds $(1)/etc/adblock $(INSTALL_CONF) ./files/adblock.custom.feeds $(1)/etc/adblock $(INSTALL_DIR) $(1)/etc/uci-defaults $(INSTALL_BIN) ./files/95-adblock-housekeeping $(1)/etc/uci-defaults + $(INSTALL_BIN) ./files/99_adblock_migrate_lists.sh $(1)/etc/uci-defaults/99_adblock_migrate_lists endef $(eval $(call BuildPackage,adblock)) diff --git a/packages/adblock/files/99_adblock_migrate_lists.sh b/packages/adblock/files/99_adblock_migrate_lists.sh new file mode 100644 index 000000000..ceea7796d --- /dev/null +++ b/packages/adblock/files/99_adblock_migrate_lists.sh @@ -0,0 +1,24 @@ +#!/bin/sh + +# +# Copyright (C) 2026 Nethesis S.r.l. +# SPDX-License-Identifier: GPL-2.0-only +# + +# Migrate local allow/block list files to staged UCI storage. +# Skip once the dedicated section is already present. +uci -q get adblock.ns_lists >/dev/null 2>&1 && exit 0 + +uci set adblock.ns_lists=ns_lists + +for type in allowlist blocklist; do + file="/etc/adblock/adblock.${type}" + [ -f "${file}" ] || continue + + while IFS= read -r line || [ -n "${line}" ]; do + [ -z "${line}" ] && continue + uci add_list "adblock.ns_lists.${type}=${line}" + done < "${file}" +done + +uci commit adblock diff --git a/packages/adblock/files/adblock.allowlist b/packages/adblock/files/adblock.allowlist deleted file mode 100644 index e69de29bb..000000000 diff --git a/packages/adblock/files/adblock.blocklist b/packages/adblock/files/adblock.blocklist deleted file mode 100644 index e69de29bb..000000000 diff --git a/packages/adblock/files/adblock.init b/packages/adblock/files/adblock.init index 9a6262f8e..14dbc1190 100755 --- a/packages/adblock/files/adblock.init +++ b/packages/adblock/files/adblock.init @@ -53,12 +53,37 @@ boot() { rc_procd start_service boot } +f_append_local_list_entry() { + local entry="${1}" + local file="${2}" + + printf '%s\n' "${entry}" >> "${file}" +} + +f_write_local_lists() { + local allowlist_file='/etc/adblock/adblock.allowlist' + local blocklist_file='/etc/adblock/adblock.blocklist' + + uci -q get adblock.ns_lists >/dev/null 2>&1 || return 0 + + config_load adblock + + : > "${allowlist_file}" + config_list_foreach ns_lists allowlist f_append_local_list_entry "${allowlist_file}" + + : > "${blocklist_file}" + config_list_foreach ns_lists blocklist f_append_local_list_entry "${blocklist_file}" +} + start_service() { if "${adb_init}" enabled; then /usr/sbin/ts-dns # configure threat shield dns, if needed if [ "${action}" = "boot" ]; then [ -n "$(uci_get adblock global adb_trigger)" ] && return 0 fi + # Start NethSecurity patch + f_write_local_lists + # End NethSecurity patch procd_open_instance "adblock" procd_set_param command "${adb_script}" "${@:-"${action}"}" procd_set_param pidfile "${adb_pidfile}" @@ -70,16 +95,19 @@ start_service() { } restart() { + # Start NethSecurity patch /usr/sbin/ts-dns # configure threat shield dns, if needed + # End NethSecurity patch stop_service "restart" rc_procd start_service restart } reload_service() { - # Start NethSecurity patch + # Start NethSecurity patch /usr/sbin/ts-dns # configure threat shield dns, if needed - ${adb_script} nft-reload - # End NethSecurity patch + f_write_local_lists + ${adb_script} nft-reload + # End NethSecurity patch rc_procd start_service reload } @@ -140,7 +168,7 @@ service_triggers() { for iface in ${trigger}; do procd_add_interface_trigger "interface.*.up" "${iface}" "${adb_init}" start done - # Start NethSecurity patch + # Start NethSecurity patch procd_add_reload_trigger adblock - # End NethSecurity patch + # End NethSecurity patch } diff --git a/packages/ns-api/README.md b/packages/ns-api/README.md index 6c2e38672..9ff9b2678 100644 --- a/packages/ns-api/README.md +++ b/packages/ns-api/README.md @@ -6171,12 +6171,15 @@ Response example: { "data": [ { - "address": "nethesis.it" + "address": "nethesis.it", + "description": "my allow1" } ] } ``` +The allow and block list methods work on UCI-staged data. Changes are visible immediately through the API and are written to `/etc/adblock/adblock.allowlist` and `/etc/adblock/adblock.blocklist` during the next adblock reload triggered by `ns.commit` or `reload_config`. + ### dns-add-allowed Add a domain which is always allowed: diff --git a/packages/ns-api/files/ns.threatshield b/packages/ns-api/files/ns.threatshield index f5bf8f97d..41293a482 100644 --- a/packages/ns-api/files/ns.threatshield +++ b/packages/ns-api/files/ns.threatshield @@ -101,14 +101,36 @@ def write_allow_list(allow_list, file='/etc/banip/banip.allowlist'): f.write('\n') subprocess.run(["/etc/init.d/banip", "reload"], capture_output=True) -def dns_write_local_list(local_list, file): - with open(file, 'w') as f: - for x in local_list: - f.write(x['address']) - if x['description']: - f.write(' #' + x['description']) - f.write('\n') - subprocess.run(["/etc/init.d/adblock", "restart"], capture_output=True) +def dns_get_local_list(e_uci, list_type): + values = e_uci.get('adblock', 'ns_lists', list_type, list=True, default=[]) + ret = [] + for value in values: + parts = value.split('#', 1) + ret.append({'address': parts[0].strip(), 'description': parts[1].strip() if len(parts) > 1 else ''}) + return ret + +def dns_write_local_list(e_uci, local_list, list_type): + option = 'allowlist' if list_type == 'allowlist' else 'blocklist' + e_uci.set('adblock', 'ns_lists', 'ns_lists') + + values = tuple( + f"{entry['address']} #{entry['description']}" if entry.get('description') else entry['address'] + for entry in local_list + ) + if values: + e_uci.set('adblock', 'ns_lists', option, values) + elif e_uci.get('adblock', 'ns_lists', option, list=True, default=[]): + e_uci.delete('adblock', 'ns_lists', option) + + e_uci.save('adblock') + +def restart_adblock(): + try: + subprocess.run(["/etc/init.d/adblock", "restart"], capture_output=True, check=True) + except subprocess.CalledProcessError: + return generic_error("restart_failed") + return None +>>>>>>> ead35d90 (fix(adblock): stage dns list changes) def write_block_list(block_list): write_allow_list(block_list, '/etc/banip/banip.blocklist') @@ -470,54 +492,54 @@ def dns_edit_settings(e_uci, payload): e_uci.save('adblock') return {'message': 'success'} -def dns_list_allowed(): - return { "data": get_allow_list('/etc/adblock/adblock.allowlist') } +def dns_list_allowed(e_uci): + return { "data": dns_get_local_list(e_uci, 'allowlist') } -def dns_list_blocked(): - return { "data": get_allow_list('/etc/adblock/adblock.blocklist') } +def dns_list_blocked(e_uci): + return { "data": dns_get_local_list(e_uci, 'blocklist') } -def dns_add_allowed(payload): - cur = get_allow_list('/etc/adblock/adblock.allowlist') +def dns_add_allowed(e_uci, payload): + cur = dns_get_local_list(e_uci, 'allowlist') # extract address from cur list if payload['address'] in [x['address'] for x in cur]: raise ValidationError('address', 'address_already_present', payload['address']) cur.append({ "address": payload['address'], "description": payload['description'] }) - dns_write_local_list(cur, '/etc/adblock/adblock.allowlist') + dns_write_local_list(e_uci, cur, 'allowlist') return {'message': 'success'} -def dns_add_blocked(payload): - cur = get_allow_list('/etc/adblock/adblock.blocklist') +def dns_add_blocked(e_uci, payload): + cur = dns_get_local_list(e_uci, 'blocklist') # extract address from cur list if payload['address'] in [x['address'] for x in cur]: raise ValidationError('address', 'address_already_present', payload['address']) cur.append({ "address": payload['address'], "description": payload.get('description') }) - dns_write_local_list(cur, '/etc/adblock/adblock.blocklist') + dns_write_local_list(e_uci, cur, 'blocklist') return {'message': 'success'} -def dns_edit_allowed(payload): - cur = get_allow_list('/etc/adblock/adblock.allowlist') +def dns_edit_allowed(e_uci, payload): + cur = dns_get_local_list(e_uci, 'allowlist') if payload['address'] not in [x['address'] for x in cur]: raise ValidationError('address', 'address_not_found', payload['address']) for i in range(len(cur)): if cur[i]['address'] == payload['address']: cur[i]['description'] = payload['description'] break - dns_write_local_list(cur, '/etc/adblock/adblock.allowlist') + dns_write_local_list(e_uci, cur, 'allowlist') return {'message': 'success'} -def dns_edit_blocked(payload): - cur = get_allow_list('/etc/adblock/adblock.blocklist') +def dns_edit_blocked(e_uci, payload): + cur = dns_get_local_list(e_uci, 'blocklist') if payload['address'] not in [x['address'] for x in cur]: raise ValidationError('address', 'address_not_found', payload['address']) for i in range(len(cur)): if cur[i]['address'] == payload['address']: cur[i]['description'] = payload.get('description') break - dns_write_local_list(cur, '/etc/adblock/adblock.blocklist') + dns_write_local_list(e_uci, cur, 'blocklist') return {'message': 'success'} -def dns_delete_allowed(payload): - cur = get_allow_list('/etc/adblock/adblock.allowlist') +def dns_delete_allowed(e_uci, payload): + cur = dns_get_local_list(e_uci, 'allowlist') if payload['address'] not in [x['address'] for x in cur]: raise ValidationError('address', 'address_not_found', payload['address']) # remove address from cur list @@ -525,11 +547,11 @@ def dns_delete_allowed(payload): if cur[i]['address'] == payload['address']: del cur[i] break - dns_write_local_list(cur, '/etc/adblock/adblock.allowlist') + dns_write_local_list(e_uci, cur, 'allowlist') return {'message': 'success'} -def dns_delete_blocked(payload): - cur = get_allow_list('/etc/adblock/adblock.blocklist') +def dns_delete_blocked(e_uci, payload): + cur = dns_get_local_list(e_uci, 'blocklist') if payload['address'] not in [x['address'] for x in cur]: raise ValidationError('address', 'address_not_found', payload['address']) # remove address from cur list @@ -537,7 +559,7 @@ def dns_delete_blocked(payload): if cur[i]['address'] == payload['address']: del cur[i] break - dns_write_local_list(cur, '/etc/adblock/adblock.blocklist') + dns_write_local_list(e_uci, cur, 'blocklist') return {'message': 'success'} def dns_list_bypass(e_uci): @@ -809,15 +831,15 @@ elif cmd == 'call': ret = dns_list_zones(e_uci) elif action == 'dns-add-allowed': payload = json.loads(sys.stdin.read()) - ret = dns_add_allowed(payload) + ret = dns_add_allowed(e_uci, payload) elif action == 'dns-edit-allowed': payload = json.loads(sys.stdin.read()) - ret = dns_edit_allowed(payload) + ret = dns_edit_allowed(e_uci, payload) elif action == 'dns-list-allowed': - ret = dns_list_allowed() + ret = dns_list_allowed(e_uci) elif action == 'dns-delete-allowed': payload = json.loads(sys.stdin.read()) - ret = dns_delete_allowed(payload) + ret = dns_delete_allowed(e_uci, payload) elif action == 'dns-list-bypass': ret = dns_list_bypass(e_uci) elif action == 'dns-add-bypass': @@ -827,16 +849,16 @@ elif cmd == 'call': payload = json.loads(sys.stdin.read()) ret = dns_delete_bypass(e_uci, payload) elif action == 'dns-list-blocked': - ret = dns_list_blocked() + ret = dns_list_blocked(e_uci) elif action == 'dns-add-blocked': payload = json.loads(sys.stdin.read()) - ret = dns_add_blocked(payload) + ret = dns_add_blocked(e_uci, payload) elif action == 'dns-edit-blocked': payload = json.loads(sys.stdin.read()) - ret = dns_edit_blocked(payload) + ret = dns_edit_blocked(e_uci, payload) elif action == 'dns-delete-blocked': payload = json.loads(sys.stdin.read()) - ret = dns_delete_blocked(payload) + ret = dns_delete_blocked(e_uci, payload) print(json.dumps(ret)) except ValidationError as ex: diff --git a/packages/ns-api/openapi.yml b/packages/ns-api/openapi.yml index c5372c489..cef18dc97 100644 --- a/packages/ns-api/openapi.yml +++ b/packages/ns-api/openapi.yml @@ -79,6 +79,29 @@ components: items: $ref: "#/components/schemas/ValidationErrorDetail" + SuccessResponse: + type: object + required: [message] + properties: + message: + type: string + example: success + + ThreatShieldDnsListEntry: + type: object + required: + - address + - description + properties: + address: + type: string + description: Domain name present in the local Threat Shield DNS list + example: nethesis.it + description: + type: string + description: Optional free-form description associated with the domain + example: my allow1 + securitySchemes: BearerAuth: type: http @@ -188,3 +211,539 @@ paths: example: success - $ref: "#/components/schemas/ValidationError" - $ref: "#/components/schemas/Error" + POST /ubus/ns.threatshield/dns-list-allowed: + post: + summary: List local Threat Shield DNS allowlist entries + description: Returns the allowlist entries currently staged in UCI. They are written to the adblock file on the next reload triggered by `ns.commit` or `reload_config`. + operationId: ns.threatshield.dns-list-allowed + tags: + - threatshield + responses: + "200": + description: Staged allowlist entries + content: + application/json: + schema: + oneOf: + - type: object + required: + - data + properties: + data: + type: array + items: + $ref: "#/components/schemas/ThreatShieldDnsListEntry" + - $ref: "#/components/schemas/Error" + POST /ubus/ns.threatshield/dns-add-allowed: + post: + summary: Add a local Threat Shield DNS allowlist entry + description: Stages the new allowlist entry in UCI. The physical adblock file is updated on the next reload triggered by `ns.commit` or `reload_config`. + operationId: ns.threatshield.dns-add-allowed + tags: + - threatshield + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - address + - description + properties: + address: + type: string + description: Domain to add to the local allowlist + example: nethesis.it + description: + type: string + description: Free-form description for the domain + example: my allow1 + responses: + "200": + description: Allowlist entry staged or validation failed + content: + application/json: + schema: + oneOf: + - $ref: "#/components/schemas/SuccessResponse" + - $ref: "#/components/schemas/ValidationError" + - $ref: "#/components/schemas/Error" + POST /ubus/ns.threatshield/dns-edit-allowed: + post: + summary: Edit a local Threat Shield DNS allowlist entry + description: Updates the staged allowlist description in UCI. The physical adblock file is updated on the next reload triggered by `ns.commit` or `reload_config`. + operationId: ns.threatshield.dns-edit-allowed + tags: + - threatshield + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - address + - description + properties: + address: + type: string + description: Existing domain in the local allowlist + example: nethesis.it + description: + type: string + description: Updated description for the domain + example: my new desc + responses: + "200": + description: Allowlist entry updated or validation failed + content: + application/json: + schema: + oneOf: + - $ref: "#/components/schemas/SuccessResponse" + - $ref: "#/components/schemas/ValidationError" + - $ref: "#/components/schemas/Error" + POST /ubus/ns.threatshield/dns-delete-allowed: + post: + summary: Delete a local Threat Shield DNS allowlist entry + description: Removes the staged allowlist entry from UCI. The physical adblock file is updated on the next reload triggered by `ns.commit` or `reload_config`. + operationId: ns.threatshield.dns-delete-allowed + tags: + - threatshield + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - address + properties: + address: + type: string + description: Existing domain in the local allowlist + example: nethesis.it + responses: + "200": + description: Allowlist entry deleted or validation failed + content: + application/json: + schema: + oneOf: + - $ref: "#/components/schemas/SuccessResponse" + - $ref: "#/components/schemas/ValidationError" + - $ref: "#/components/schemas/Error" + POST /ubus/ns.threatshield/dns-list-blocklist: + post: + summary: List available Threat Shield DNS blocklists + operationId: ns.threatshield.dns-list-blocklist + tags: + - threatshield + responses: + "200": + description: Available blocklists + content: + application/json: + schema: + oneOf: + - type: object + required: + - data + properties: + data: + type: array + items: + type: object + required: + - name + - type + - enabled + - confidence + - description + properties: + name: + type: string + description: Blocklist name + example: adguard + type: + type: string + enum: [enterprise, community] + description: Blocklist category + example: enterprise + enabled: + type: boolean + description: Whether the blocklist is enabled + example: true + confidence: + type: integer + description: Entitlement confidence score + example: 10 + description: + type: [string, "null"] + description: Blocklist description + example: OpenDNS family shield + - $ref: "#/components/schemas/Error" + POST /ubus/ns.threatshield/dns-list-blocked: + post: + summary: List local Threat Shield DNS blocklist entries + description: Returns the blocklist entries currently staged in UCI. They are written to the adblock file on the next reload triggered by `ns.commit` or `reload_config`. + operationId: ns.threatshield.dns-list-blocked + tags: + - threatshield + responses: + "200": + description: Staged blocklist entries + content: + application/json: + schema: + oneOf: + - type: object + required: + - data + properties: + data: + type: array + items: + $ref: "#/components/schemas/ThreatShieldDnsListEntry" + - $ref: "#/components/schemas/Error" + POST /ubus/ns.threatshield/dns-add-blocked: + post: + summary: Add a local Threat Shield DNS blocklist entry + description: Stages the new blocklist entry in UCI. The physical adblock file is updated on the next reload triggered by `ns.commit` or `reload_config`. + operationId: ns.threatshield.dns-add-blocked + tags: + - threatshield + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - address + properties: + address: + type: string + description: Domain to add to the local blocklist + example: nastydomain.net + description: + type: string + description: Optional free-form description for the domain + example: my block1 + responses: + "200": + description: Blocklist entry staged or validation failed + content: + application/json: + schema: + oneOf: + - $ref: "#/components/schemas/SuccessResponse" + - $ref: "#/components/schemas/ValidationError" + - $ref: "#/components/schemas/Error" + POST /ubus/ns.threatshield/dns-edit-blocked: + post: + summary: Edit a local Threat Shield DNS blocklist entry + description: Updates the staged blocklist description in UCI. The physical adblock file is updated on the next reload triggered by `ns.commit` or `reload_config`. + operationId: ns.threatshield.dns-edit-blocked + tags: + - threatshield + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - address + properties: + address: + type: string + description: Existing domain in the local blocklist + example: nastydomain.net + description: + type: string + description: Updated description for the domain + example: My new desc + responses: + "200": + description: Blocklist entry updated or validation failed + content: + application/json: + schema: + oneOf: + - $ref: "#/components/schemas/SuccessResponse" + - $ref: "#/components/schemas/ValidationError" + - $ref: "#/components/schemas/Error" + POST /ubus/ns.threatshield/dns-delete-blocked: + post: + summary: Delete a local Threat Shield DNS blocklist entry + description: Removes the staged blocklist entry from UCI. The physical adblock file is updated on the next reload triggered by `ns.commit` or `reload_config`. + operationId: ns.threatshield.dns-delete-blocked + tags: + - threatshield + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - address + properties: + address: + type: string + description: Existing domain in the local blocklist + example: nastydomain.net + responses: + "200": + description: Blocklist entry deleted or validation failed + content: + application/json: + schema: + oneOf: + - $ref: "#/components/schemas/SuccessResponse" + - $ref: "#/components/schemas/ValidationError" + - $ref: "#/components/schemas/Error" + POST /ubus/ns.threatshield/dns-list-settings: + post: + summary: Get Threat Shield DNS enforcement settings + operationId: ns.threatshield.dns-list-settings + tags: + - threatshield + responses: + "200": + description: Current DNS enforcement settings + content: + application/json: + schema: + oneOf: + - type: object + required: + - data + properties: + data: + type: object + required: + - enabled + - zones + - ports + properties: + enabled: + type: boolean + description: Whether Threat Shield DNS is enabled + example: true + zones: + type: array + description: Firewall zones where DNS redirection is enforced + items: + type: string + example: [lan] + ports: + type: array + description: DNS ports enforced locally + items: + type: string + example: ["53", "853"] + - $ref: "#/components/schemas/Error" + POST /ubus/ns.threatshield/dns-list-zones: + post: + summary: List firewall zones available for Threat Shield DNS + operationId: ns.threatshield.dns-list-zones + tags: + - threatshield + responses: + "200": + description: Available zones + content: + application/json: + schema: + oneOf: + - type: object + required: + - data + properties: + data: + type: array + items: + type: string + - $ref: "#/components/schemas/Error" + POST /ubus/ns.threatshield/dns-edit-blocklist: + post: + summary: Enable or disable a Threat Shield DNS blocklist + operationId: ns.threatshield.dns-edit-blocklist + tags: + - threatshield + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - blocklist + - enabled + properties: + blocklist: + type: string + description: DNS blocklist name + example: adguard + enabled: + type: boolean + description: Whether the blocklist should be enabled + example: true + responses: + "200": + description: Blocklist updated or validation failed + content: + application/json: + schema: + oneOf: + - type: object + required: + - message + properties: + message: + type: string + example: success + - $ref: "#/components/schemas/ValidationError" + - $ref: "#/components/schemas/Error" + POST /ubus/ns.threatshield/dns-edit-settings: + post: + summary: Update Threat Shield DNS enforcement settings + operationId: ns.threatshield.dns-edit-settings + tags: + - threatshield + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - enabled + properties: + enabled: + type: boolean + description: Enable or disable Threat Shield DNS + example: true + zones: + type: array + description: Firewall zones where DNS redirection is enforced + items: + type: string + example: [lan] + ports: + type: array + description: DNS ports enforced locally + items: + type: string + example: ["53", "853"] + responses: + "200": + description: Settings updated or validation failed + content: + application/json: + schema: + oneOf: + - type: object + required: + - message + properties: + message: + type: string + example: success + - $ref: "#/components/schemas/ValidationError" + - $ref: "#/components/schemas/Error" + POST /ubus/ns.threatshield/dns-list-bypass: + post: + summary: List Threat Shield DNS bypass entries + operationId: ns.threatshield.dns-list-bypass + tags: + - threatshield + responses: + "200": + description: DNS bypass entries + content: + application/json: + schema: + oneOf: + - type: object + required: + - data + properties: + data: + type: array + items: + type: string + - $ref: "#/components/schemas/Error" + POST /ubus/ns.threatshield/dns-add-bypass: + post: + summary: Add a Threat Shield DNS bypass entry + operationId: ns.threatshield.dns-add-bypass + tags: + - threatshield + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - address + properties: + address: + type: string + description: Source IP address or subnet that should bypass DNS redirection + example: 192.168.1.22 + responses: + "200": + description: Bypass entry added or validation failed + content: + application/json: + schema: + oneOf: + - type: object + required: + - message + properties: + message: + type: string + example: success + - $ref: "#/components/schemas/ValidationError" + - $ref: "#/components/schemas/Error" + POST /ubus/ns.threatshield/dns-delete-bypass: + post: + summary: Delete a Threat Shield DNS bypass entry + operationId: ns.threatshield.dns-delete-bypass + tags: + - threatshield + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - address + properties: + address: + type: string + description: Source IP address or subnet to remove from the DNS bypass list + example: 192.168.1.22 + responses: + "200": + description: Bypass entry removed or validation failed + content: + application/json: + schema: + oneOf: + - type: object + required: + - message + properties: + message: + type: string + example: success + - $ref: "#/components/schemas/ValidationError" + - $ref: "#/components/schemas/Error"