diff options
| author | Markus Heiser <markus.heiser@darmarit.de> | 2023-06-01 15:41:48 +0200 |
|---|---|---|
| committer | Markus Heiser <markus.heiser@darmarit.de> | 2023-06-01 15:51:14 +0200 |
| commit | 281e36f4b7848374535d5e953050ae73423191ca (patch) | |
| tree | f7bda906459c8e796ec688a0007191f3c3609d63 /searx/botdetection/_helpers.py | |
| parent | 38431d2e142b7da6a9b48aad203f02a2eff7e6fd (diff) | |
[fix] limiter: replace real_ip by IPv4/v6 network
Closes: https://github.com/searxng/searxng/issues/2477
Signed-off-by: Markus Heiser <markus.heiser@darmarit.de>
Diffstat (limited to 'searx/botdetection/_helpers.py')
| -rw-r--r-- | searx/botdetection/_helpers.py | 44 |
1 files changed, 36 insertions, 8 deletions
diff --git a/searx/botdetection/_helpers.py b/searx/botdetection/_helpers.py index b034b980b..8e0156d6e 100644 --- a/searx/botdetection/_helpers.py +++ b/searx/botdetection/_helpers.py @@ -1,11 +1,19 @@ # SPDX-License-Identifier: AGPL-3.0-or-later # lint: pylint # pylint: disable=missing-module-docstring, invalid-name - -from typing import Optional +from __future__ import annotations + +from ipaddress import ( + IPv4Network, + IPv6Network, + IPv6Address, + ip_address, + ip_network, +) import flask import werkzeug +from searx.tools import config from searx import logger logger = logger.getChild('botdetection') @@ -13,7 +21,7 @@ logger = logger.getChild('botdetection') def dump_request(request: flask.Request): return ( - "%s: %s" % (get_real_ip(request), request.path) + request.path + " || X-Forwarded-For: %s" % request.headers.get('X-Forwarded-For') + " || X-Real-IP: %s" % request.headers.get('X-Real-IP') + " || form: %s" % request.form @@ -27,12 +35,30 @@ def dump_request(request: flask.Request): ) -def too_many_requests(request: flask.Request, log_msg: str) -> Optional[werkzeug.Response]: - log_prefix = 'BLOCK %s: ' % get_real_ip(request) - logger.debug(log_prefix + log_msg) +def too_many_requests(network: IPv4Network | IPv6Network, log_msg: str) -> werkzeug.Response | None: + """Returns a HTTP 429 response object and writes a ERROR message to the + 'botdetection' logger. This function is used in part by the filter methods + to return the default ``Too Many Requests`` response. + + """ + + logger.debug("BLOCK %s: %s", network.compressed, log_msg) return flask.make_response(('Too Many Requests', 429)) +def get_network(real_ip: str, cfg: config.Config) -> IPv4Network | IPv6Network: + """Returns the (client) network of whether the real_ip is part of.""" + + ip = ip_address(real_ip) + if isinstance(ip, IPv6Address): + prefix = cfg['real_ip.ipv6_prefix'] + else: + prefix = cfg['real_ip.ipv4_prefix'] + network = ip_network(f"{real_ip}/{prefix}", strict=False) + # logger.debug("get_network(): %s", network.compressed) + return network + + def get_real_ip(request: flask.Request) -> str: """Returns real IP of the request. Since not all proxies set all the HTTP headers and incoming headers can be faked it may happen that the IP cannot @@ -63,7 +89,9 @@ def get_real_ip(request: flask.Request) -> str: forwarded_for = request.headers.get("X-Forwarded-For") real_ip = request.headers.get('X-Real-IP') remote_addr = request.remote_addr - logger.debug("X-Forwarded-For: %s || X-Real-IP: %s || request.remote_addr: %s", forwarded_for, real_ip, remote_addr) + # logger.debug( + # "X-Forwarded-For: %s || X-Real-IP: %s || request.remote_addr: %s", forwarded_for, real_ip, remote_addr + # ) if not forwarded_for: logger.error("X-Forwarded-For header is not set!") @@ -89,5 +117,5 @@ def get_real_ip(request: flask.Request) -> str: logger.warning("IP from WSGI environment (%s) is not equal to IP from X-Real-IP (%s)", remote_addr, real_ip) request_ip = forwarded_for or real_ip or remote_addr or '0.0.0.0' - logger.debug("get_real_ip() -> %s", request_ip) + # logger.debug("get_real_ip() -> %s", request_ip) return request_ip |