summaryrefslogtreecommitdiff
path: root/searx/botdetection/ip_lists.py
diff options
context:
space:
mode:
authorMarkus Heiser <markus.heiser@darmarit.de>2023-06-03 13:43:34 +0200
committerMarkus Heiser <markus.heiser@darmarit.de>2023-06-05 14:07:19 +0200
commitf3763d73ad8cf93ea32d7e12713662f7963d950f (patch)
treed64964ad9d6c49e0c2c7b1d6da14ccca9d4a7c55 /searx/botdetection/ip_lists.py
parentde2f396e5020228db2a88babdd818fa20d7c44e3 (diff)
[mod] limiter: blocklist and passlist (ip_lists)
A blocklist and a passlist can be configured in /etc/searxng/limiter.toml:: [botdetection.ip_lists] pass_ip = [ '51.15.252.168', # IPv4 of check.searx.space ] block_ip = [ '93.184.216.34', # IPv4 of example.org ] Closes: https://github.com/searxng/searxng/issues/2127 Closes: https://github.com/searxng/searxng/pull/2129 Signed-off-by: Markus Heiser <markus.heiser@darmarit.de>
Diffstat (limited to 'searx/botdetection/ip_lists.py')
-rw-r--r--searx/botdetection/ip_lists.py85
1 files changed, 85 insertions, 0 deletions
diff --git a/searx/botdetection/ip_lists.py b/searx/botdetection/ip_lists.py
new file mode 100644
index 000000000..456ef4365
--- /dev/null
+++ b/searx/botdetection/ip_lists.py
@@ -0,0 +1,85 @@
+# SPDX-License-Identifier: AGPL-3.0-or-later
+# lint: pylint
+""".. _botdetection.ip_lists:
+
+Method ``ip_lists``
+-------------------
+
+The ``ip_lists`` method implements IP :py:obj:`block- <block_ip>` and
+:py:obj:`pass-lists <pass_ip>`.
+
+.. code:: toml
+
+ [botdetection.ip_lists]
+
+ pass_ip = [
+ '140.238.172.132', # IPv4 of check.searx.space
+ '192.168.0.0/16', # IPv4 private network
+ 'fe80::/10' # IPv6 linklocal
+ ]
+ block_ip = [
+ '93.184.216.34', # IPv4 of example.org
+ '257.1.1.1', # invalid IP --> will be ignored, logged in ERROR class
+ ]
+
+"""
+# pylint: disable=unused-argument
+
+from __future__ import annotations
+from typing import Tuple
+from ipaddress import (
+ ip_network,
+ IPv4Address,
+ IPv6Address,
+)
+
+from searx.tools import config
+from ._helpers import logger
+
+logger = logger.getChild('ip_limit')
+
+SEARXNG_ORG = [
+ # https://github.com/searxng/searxng/pull/2484#issuecomment-1576639195
+ '140.238.172.132', # IPv4 check.searx.space
+ '2603:c022:0:4900::/56', # IPv6 check.searx.space
+]
+"""Passlist of IPs from the SearXNG organization, e.g. `check.searx.space`."""
+
+
+def pass_ip(real_ip: IPv4Address | IPv6Address, cfg: config.Config) -> Tuple[bool, str]:
+ """Checks if the IP on the subnet is in one of the members of the
+ ``botdetection.ip_lists.pass_ip`` list.
+ """
+
+ if cfg.get('botdetection.ip_lists.pass_searxng_org', default=True):
+ for net in SEARXNG_ORG:
+ net = ip_network(net, strict=False)
+ if real_ip.version == net.version and real_ip in net:
+ return True, f"IP matches {net.compressed} in SEARXNG_ORG list."
+ return ip_is_subnet_of_member_in_list(real_ip, 'botdetection.ip_lists.pass_ip', cfg)
+
+
+def block_ip(real_ip: IPv4Address | IPv6Address, cfg: config.Config) -> Tuple[bool, str]:
+ """Checks if the IP on the subnet is in one of the members of the
+ ``botdetection.ip_lists.block_ip`` list.
+ """
+
+ block, msg = ip_is_subnet_of_member_in_list(real_ip, 'botdetection.ip_lists.block_ip', cfg)
+ if block:
+ msg += " To remove IP from list, please contact the maintainer of the service."
+ return block, msg
+
+
+def ip_is_subnet_of_member_in_list(
+ real_ip: IPv4Address | IPv6Address, list_name: str, cfg: config.Config
+) -> Tuple[bool, str]:
+
+ for net in cfg.get(list_name, default=[]):
+ try:
+ net = ip_network(net, strict=False)
+ except ValueError:
+ logger.error("invalid IP %s in %s", net, list_name)
+ continue
+ if real_ip.version == net.version and real_ip in net:
+ return True, f"IP matches {net.compressed} in {list_name}."
+ return False, f"IP is not a member of an item in the f{list_name} list"