
    i5                         d Z ddlZddlmZ ddlmZmZmZm	Z	m
Z
mZ ddlmZ ddlmZ ddlmZmZ ej&                  rdd	lmZ dd
lmZ ddlmZ ej0                   G d d             Zy)zImplementation of a middleware to determine the real IP of an HTTP request
(:py:obj:`flask.request.remote_addr`) behind a proxy chain.    N)abc)IPv4AddressIPv6Address
ip_address
ip_networkIPv4NetworkIPv6Network)parse_list_header   )config)log_error_only_oncelogger)StartResponse)WSGIApplication)WSGIEnvironmentc                       e Zd ZdZddZdeeez     fdZdee	e
z     deeez     defdZd	d
dddej                  e   fdZy)ProxyFixa9  A middleware like the ProxyFix_ class, where the ``x_for`` argument is
    replaced by a method that determines the number of trusted proxies via the
    ``botdetection.trusted_proxies`` setting.

    .. sidebar:: :py:obj:`flask.Request.remote_addr`

       SearXNG uses Werkzeug's ProxyFix_ (with it default ``x_for=1``).

    The remote IP (:py:obj:`flask.Request.remote_addr`) of the request is taken
    from (first match):

    - X-Forwarded-For_: If the header is set, the first untrusted IP that comes
      before the IPs that are still part of the ``botdetection.trusted_proxies``
      is used.

    - `X-Real-IP <https://github.com/searxng/searxng/issues/1237#issuecomment-1147564516>`__:
      If X-Forwarded-For_ is not set, `X-Real-IP` is used
      (``botdetection.trusted_proxies`` is ignored).

    If none of the header is set, the REMOTE_ADDR_ from the WSGI layer is used.
    If (for whatever reasons) none IP can be determined, an error message is
    displayed and ``100::`` is used instead (:rfc:`6666`).

    .. _ProxyFix:
       https://werkzeug.palletsprojects.com/middleware/proxy_fix/

    .. _X-Forwarded-For:
       https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For

    .. _REMOTE_ADDR:
       https://wsgi.readthedocs.io/en/latest/proposals-2.0.html#making-some-keys-required

    returnNc                     || _         y )N)wsgi_app)selfr   s     3/root/searxng/searx/botdetection/trusted_proxies.py__init__zProxyFix.__init__:   s	         c                     t        j                         }|j                  dg       }|D cg c]  }t        |d       c}S c c}w )Nzbotdetection.trusted_proxies)defaultF)strict)r   get_global_cfggetr   )r   cfg
proxy_listnets       r   trusted_proxieszProxyFix.trusted_proxies=   s?    ##% #(FPR S
9CD#
3u-DDDs   Ax_forwarded_forr#   c                     t        |      D ]T  }d}|D ];  }|j                  |j                  k(  s||v s"t        j                  d||       d} n |rH|j                  c S  |d   j                  S )NFztrust proxy %s (member of %s)Tr   )reversedversionr   debug
compressed)r   r$   r#   addrtrustr"   s         r   trusted_remote_addrzProxyFix.trusted_remote_addrB   s}     _- 	'DE& <<3;;.43;LL!@$L E	 &	' q!,,,r   environr   start_responser   c                    | j                         }|j                  d      }|r?	 t        |      }|j                  dk(  r|j                  r|j                  }|j
                  }|j                  d      }|r?	 t        |      }|j                  dk(  r|j                  r|j                  }|j
                  }g }|j                  d      rlt        t        |j                  d                  D ]F  }		 t        |	      }|j                  dk(  r|j                  r|j                  }|j                  |       H |s|st        d       |r|st        d	       g }|j                  d
d|ii       |r| j                  ||      |d<   n*|r||d<   n"|r||d<   nt        j                  d       d|d<   	 t        |d         }
t        j                   d|d          | j#                  ||      S # t        $ r#}t        j                  d|       d }Y d }~d }~ww xY w# t        $ r4}t        j                  d|       |j                  d       d }Y d }~d }~ww xY w# t        $ r5}t        j                  d|       |j                  d       g }Y d }~ Yd }~ww xY w# t        $ r&}t        j                  d|       d|d<   Y d }~d }~ww xY w)NREMOTE_ADDR   z;REMOTE_ADDR: %s / discard REMOTE_ADDR from WSGI environmentHTTP_X_REAL_IPz<X-Real-IP: %s / discard HTTP_X_REAL_IP from WSGI environmentHTTP_X_FORWARDED_FORzHX-Forwarded-For: %s / discard HTTP_X_FORWARDED_FOR from WSGI environmentz,X-Forwarded-For nor X-Real-IP header is set!z+missing botdetection.trusted_proxies configz!botdetection.trusted_proxies.origz?No remote IP could be determined, use black-hole address: 100::z100::z.REMOTE_ADDR: %s, use black-hole address: 100::zfinal REMOTE_ADDR is: %s)r#   popr   r'   ipv4_mappedr)   
ValueErrorr   errorr   r
   strappendr   updater,   r(   r   )r   r-   r.   r#   orig_remote_addrr*   exc	x_real_ipr$   x_for_ip_s              r   __call__zProxyFix.__call__X   s    ..0 (/{{='A
 (!"23<<1$)9)9++D#'?? 
 !(,< =	!!),<<1$)9)9++D OO	 <>;;-.-c'++>T2U.VW -%h/D <<1$)9)9++D&&t,- y NO? MN !O 	;mM]=^_` %)%=%=o%_GM"%.GM"%5GM" LLZ[%,GM"	-7=12A
 	/1GH}}Wn55I  (Z\_`#' (  ![]`a,- 	! " LL!kmpqKK 67&(O	T  	-LLI3O%,GM"	-s_   >G% 7>H /I,J %	H.HH	I)II	J)JJ	KJ??K)r   r   r   N)__name__
__module____qualname____doc__r   listr   r	   r#   r   r   r8   r,   r   Iterablebytesr@    r   r   r   r      s     D!EkK&?!@ E
-kK78- kK78- 
	-,X6 1 X6? X6WZWcWcdiWj X6r   r   )rD   typingtcollectionsr   	ipaddressr   r   r   r   r   r	   werkzeug.httpr
    r   _helpersr   r   TYPE_CHECKING_typeshed.wsgir   r   r   finalr   rH   r   r   <module>rS      sQ   ?
   ` ` +  1??,.. Y6 Y6 	Y6r   