diff options
| author | Markus Heiser <markus.heiser@darmarit.de> | 2023-06-03 13:43:34 +0200 |
|---|---|---|
| committer | Markus Heiser <markus.heiser@darmarit.de> | 2023-06-05 14:07:19 +0200 |
| commit | f3763d73ad8cf93ea32d7e12713662f7963d950f (patch) | |
| tree | d64964ad9d6c49e0c2c7b1d6da14ccca9d4a7c55 /searx/botdetection/ip_lists.py | |
| parent | de2f396e5020228db2a88babdd818fa20d7c44e3 (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.py | 85 |
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" |