| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384 | 
							- # SPDX-License-Identifier: AGPL-3.0-or-later
 
- """.. _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 = [
 
-     '167.235.158.251', # 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 . import config
 
- from ._helpers import logger
 
- logger = logger.getChild('ip_limit')
 
- SEARXNG_ORG = [
 
-     # https://github.com/searxng/searxng/pull/2484#issuecomment-1576639195
 
-     '167.235.158.251',  # IPv4 check.searx.space
 
-     '2a01:04f8:1c1c:8fc2::/64',  # 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"
 
 
  |