.oO SearXNG Developer Documentation Oo.
Loading...
Searching...
No Matches
ip_lists.py
Go to the documentation of this file.
1# SPDX-License-Identifier: AGPL-3.0-or-later
2""".. _botdetection.ip_lists:
3
4Method ``ip_lists``
5-------------------
6
7The ``ip_lists`` method implements :py:obj:`block-list <block_ip>` and
8:py:obj:`pass-list <pass_ip>`.
9
10.. code:: toml
11
12 [botdetection.ip_lists]
13
14 pass_ip = [
15 '167.235.158.251', # IPv4 of check.searx.space
16 '192.168.0.0/16', # IPv4 private network
17 'fe80::/10', # IPv6 linklocal
18 ]
19
20 block_ip = [
21 '93.184.216.34', # IPv4 of example.org
22 '257.1.1.1', # invalid IP --> will be ignored, logged in ERROR class
23 ]
24
25"""
26# pylint: disable=unused-argument
27
28from __future__ import annotations
29from typing import Tuple
30from ipaddress import (
31 ip_network,
32 IPv4Address,
33 IPv6Address,
34)
35
36from . import config
37from ._helpers import logger
38
39logger = logger.getChild('ip_limit')
40
41SEARXNG_ORG = [
42 # https://github.com/searxng/searxng/pull/2484#issuecomment-1576639195
43 '167.235.158.251', # IPv4 check.searx.space
44 '2a01:04f8:1c1c:8fc2::/64', # IPv6 check.searx.space
45]
46"""Passlist of IPs from the SearXNG organization, e.g. `check.searx.space`."""
47
48
49def pass_ip(real_ip: IPv4Address | IPv6Address, cfg: config.Config) -> Tuple[bool, str]:
50 """Checks if the IP on the subnet is in one of the members of the
51 ``botdetection.ip_lists.pass_ip`` list.
52 """
53
54 if cfg.get('botdetection.ip_lists.pass_searxng_org', default=True):
55 for net in SEARXNG_ORG:
56 net = ip_network(net, strict=False)
57 if real_ip.version == net.version and real_ip in net:
58 return True, f"IP matches {net.compressed} in SEARXNG_ORG list."
59 return ip_is_subnet_of_member_in_list(real_ip, 'botdetection.ip_lists.pass_ip', cfg)
60
61
62def block_ip(real_ip: IPv4Address | IPv6Address, cfg: config.Config) -> Tuple[bool, str]:
63 """Checks if the IP on the subnet is in one of the members of the
64 ``botdetection.ip_lists.block_ip`` list.
65 """
66
67 block, msg = ip_is_subnet_of_member_in_list(real_ip, 'botdetection.ip_lists.block_ip', cfg)
68 if block:
69 msg += " To remove IP from list, please contact the maintainer of the service."
70 return block, msg
71
72
74 real_ip: IPv4Address | IPv6Address, list_name: str, cfg: config.Config
75) -> Tuple[bool, str]:
76 for net in cfg.get(list_name, default=[]):
77 try:
78 net = ip_network(net, strict=False)
79 except ValueError:
80 logger.error("invalid IP %s in %s", net, list_name)
81 continue
82 if real_ip.version == net.version and real_ip in net:
83 return True, f"IP matches {net.compressed} in {list_name}."
84 return False, f"IP is not a member of an item in the f{list_name} list"
Tuple[bool, str] block_ip(IPv4Address|IPv6Address real_ip, config.Config cfg)
Definition ip_lists.py:62
Tuple[bool, str] ip_is_subnet_of_member_in_list(IPv4Address|IPv6Address real_ip, str list_name, config.Config cfg)
Definition ip_lists.py:75
Tuple[bool, str] pass_ip(IPv4Address|IPv6Address real_ip, config.Config cfg)
Definition ip_lists.py:49