|  | # SPDX-License-Identifier: AGPL-3.0-or-later
 | 
						
						
						
							|  | """A plugin to check if the ip address of the request is a Tor exit-node if the
 | 
						
						
						
							|  | user searches for ``tor-check``.  It fetches the tor exit node list from
 | 
						
						
						
							|  | :py:obj:`url_exit_list` and parses all the IPs into a list, then checks if the
 | 
						
						
						
							|  | user's IP address is in it.
 | 
						
						
						
							|  | 
 | 
						
						
						
							|  | Enable in ``settings.yml``:
 | 
						
						
						
							|  | 
 | 
						
						
						
							|  | .. code:: yaml
 | 
						
						
						
							|  | 
 | 
						
						
						
							|  |   enabled_plugins:
 | 
						
						
						
							|  |     ..
 | 
						
						
						
							|  |     - 'Tor check plugin'
 | 
						
						
						
							|  | 
 | 
						
						
						
							|  | """
 | 
						
						
						
							|  | 
 | 
						
						
						
							|  | from __future__ import annotations
 | 
						
						
						
							|  | 
 | 
						
						
						
							|  | import re
 | 
						
						
						
							|  | from flask_babel import gettext
 | 
						
						
						
							|  | from httpx import HTTPError
 | 
						
						
						
							|  | 
 | 
						
						
						
							|  | from searx.network import get
 | 
						
						
						
							|  | from searx.result_types import Answer
 | 
						
						
						
							|  | 
 | 
						
						
						
							|  | 
 | 
						
						
						
							|  | default_on = False
 | 
						
						
						
							|  | 
 | 
						
						
						
							|  | name = gettext("Tor check plugin")
 | 
						
						
						
							|  | '''Translated name of the plugin'''
 | 
						
						
						
							|  | 
 | 
						
						
						
							|  | description = gettext(
 | 
						
						
						
							|  |     "This plugin checks if the address of the request is a Tor exit-node, and"
 | 
						
						
						
							|  |     " informs the user if it is; like check.torproject.org, but from SearXNG."
 | 
						
						
						
							|  | )
 | 
						
						
						
							|  | '''Translated description of the plugin.'''
 | 
						
						
						
							|  | 
 | 
						
						
						
							|  | preference_section = 'query'
 | 
						
						
						
							|  | '''The preference section where the plugin is shown.'''
 | 
						
						
						
							|  | 
 | 
						
						
						
							|  | query_keywords = ['tor-check']
 | 
						
						
						
							|  | '''Query keywords shown in the preferences.'''
 | 
						
						
						
							|  | 
 | 
						
						
						
							|  | query_examples = ''
 | 
						
						
						
							|  | '''Query examples shown in the preferences.'''
 | 
						
						
						
							|  | 
 | 
						
						
						
							|  | # Regex for exit node addresses in the list.
 | 
						
						
						
							|  | reg = re.compile(r"(?<=ExitAddress )\S+")
 | 
						
						
						
							|  | 
 | 
						
						
						
							|  | url_exit_list = "https://check.torproject.org/exit-addresses"
 | 
						
						
						
							|  | """URL to load Tor exit list from."""
 | 
						
						
						
							|  | 
 | 
						
						
						
							|  | 
 | 
						
						
						
							|  | def post_search(request, search) -> list[Answer]:
 | 
						
						
						
							|  |     results = []
 | 
						
						
						
							|  | 
 | 
						
						
						
							|  |     if search.search_query.pageno > 1:
 | 
						
						
						
							|  |         return results
 | 
						
						
						
							|  | 
 | 
						
						
						
							|  |     if search.search_query.query.lower() == "tor-check":
 | 
						
						
						
							|  | 
 | 
						
						
						
							|  |         # Request the list of tor exit nodes.
 | 
						
						
						
							|  |         try:
 | 
						
						
						
							|  |             resp = get(url_exit_list)
 | 
						
						
						
							|  |             node_list = re.findall(reg, resp.text)  # type: ignore
 | 
						
						
						
							|  | 
 | 
						
						
						
							|  |         except HTTPError:
 | 
						
						
						
							|  |             # No answer, return error
 | 
						
						
						
							|  |             msg = gettext("Could not download the list of Tor exit-nodes from")
 | 
						
						
						
							|  |             Answer(results=results, answer=f"{msg} {url_exit_list}")
 | 
						
						
						
							|  |             return results
 | 
						
						
						
							|  | 
 | 
						
						
						
							|  |         x_forwarded_for = request.headers.getlist("X-Forwarded-For")
 | 
						
						
						
							|  | 
 | 
						
						
						
							|  |         if x_forwarded_for:
 | 
						
						
						
							|  |             ip_address = x_forwarded_for[0]
 | 
						
						
						
							|  |         else:
 | 
						
						
						
							|  |             ip_address = request.remote_addr
 | 
						
						
						
							|  | 
 | 
						
						
						
							|  |         if ip_address in node_list:
 | 
						
						
						
							|  |             msg = gettext("You are using Tor and it looks like you have the external IP address")
 | 
						
						
						
							|  |             Answer(results=results, answer=f"{msg} {ip_address}")
 | 
						
						
						
							|  | 
 | 
						
						
						
							|  |         else:
 | 
						
						
						
							|  |             msg = gettext("You are not using Tor and you have the external IP address")
 | 
						
						
						
							|  |             Answer(results=results, answer=f"{msg} {ip_address}")
 | 
						
						
						
							|  | 
 | 
						
						
						
							|  |     return results
 |