.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 IP :py:obj:`block- <block_ip>` and
8:py:obj:`pass-lists <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 block_ip = [
20 '93.184.216.34', # IPv4 of example.org
21 '257.1.1.1', # invalid IP --> will be ignored, logged in ERROR class
22 ]
23
24"""
25# pylint: disable=unused-argument
26
27from __future__ import annotations
28from typing import Tuple
29from ipaddress import (
30 ip_network,
31 IPv4Address,
32 IPv6Address,
33)
34
35from . import config
36from ._helpers import logger
37
38logger = logger.getChild('ip_limit')
39
40SEARXNG_ORG = [
41 # https://github.com/searxng/searxng/pull/2484#issuecomment-1576639195
42 '167.235.158.251', # IPv4 check.searx.space
43 '2a01:04f8:1c1c:8fc2::/64', # IPv6 check.searx.space
44]
45"""Passlist of IPs from the SearXNG organization, e.g. `check.searx.space`."""
46
47
48def pass_ip(real_ip: IPv4Address | IPv6Address, cfg: config.Config) -> Tuple[bool, str]:
49 """Checks if the IP on the subnet is in one of the members of the
50 ``botdetection.ip_lists.pass_ip`` list.
51 """
52
53 if cfg.get('botdetection.ip_lists.pass_searxng_org', default=True):
54 for net in SEARXNG_ORG:
55 net = ip_network(net, strict=False)
56 if real_ip.version == net.version and real_ip in net:
57 return True, f"IP matches {net.compressed} in SEARXNG_ORG list."
58 return ip_is_subnet_of_member_in_list(real_ip, 'botdetection.ip_lists.pass_ip', cfg)
59
60
61def block_ip(real_ip: IPv4Address | IPv6Address, cfg: config.Config) -> Tuple[bool, str]:
62 """Checks if the IP on the subnet is in one of the members of the
63 ``botdetection.ip_lists.block_ip`` list.
64 """
65
66 block, msg = ip_is_subnet_of_member_in_list(real_ip, 'botdetection.ip_lists.block_ip', cfg)
67 if block:
68 msg += " To remove IP from list, please contact the maintainer of the service."
69 return block, msg
70
71
73 real_ip: IPv4Address | IPv6Address, list_name: str, cfg: config.Config
74) -> Tuple[bool, str]:
75
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:61
Tuple[bool, str] ip_is_subnet_of_member_in_list(IPv4Address|IPv6Address real_ip, str list_name, config.Config cfg)
Definition ip_lists.py:74
Tuple[bool, str] pass_ip(IPv4Address|IPv6Address real_ip, config.Config cfg)
Definition ip_lists.py:48