diff --git a/docs/src/searx.plugins.tor_check.rst b/docs/src/searx.plugins.tor_check.rst new file mode 100644 index 000000000..905328ebf --- /dev/null +++ b/docs/src/searx.plugins.tor_check.rst @@ -0,0 +1,9 @@ +.. _tor check plugin: + +================ +Tor check plugin +================ + +.. automodule:: searx.plugins.tor_check + :members: + diff --git a/searx/plugins/tor_check.py b/searx/plugins/tor_check.py new file mode 100644 index 000000000..7d50bbcb5 --- /dev/null +++ b/searx/plugins/tor_check.py @@ -0,0 +1,88 @@ +# SPDX-License-Identifier: AGPL-3.0-or-later +# lint: pylint +"""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 +https://check.torproject.org/exit-addresses 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' + +""" + +import re +from flask_babel import gettext +from httpx import HTTPError +from searx.network import get + +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+") + + +def post_search(request, search): + + if search.search_query.pageno > 1: + return True + + if search.search_query.query.lower() == "tor-check": + + # Request the list of tor exit nodes. + try: + resp = get("https://check.torproject.org/exit-addresses") + node_list = re.findall(reg, resp.text) + + except HTTPError: + # No answer, return error + search.result_container.answers["tor"] = { + "answer": gettext( + "The TOR exit node list (https://check.torproject.org/exit-addresses) is unreachable." + ) + } + return True + + 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: + search.result_container.answers["tor"] = { + "answer": gettext( + "You are using TOR. Your IP address seems to be: {ip_address}.".format(ip_address=ip_address) + ) + } + else: + search.result_container.answers["tor"] = { + "answer": gettext( + "You are not using TOR. Your IP address seems to be: {ip_address}.".format(ip_address=ip_address) + ) + } + + return True diff --git a/searx/settings.yml b/searx/settings.yml index 2b12c8330..21f0f20b3 100644 --- a/searx/settings.yml +++ b/searx/settings.yml @@ -187,6 +187,7 @@ outgoing: # - 'Hostname replace' # see hostname_replace configuration below # - 'Open Access DOI rewrite' # - 'Vim-like hotkeys' +# - 'Tor check plugin' # Configuration of the "Hostname replace" plugin: #