
    si:                         d Z ddlZddlZddlmZ ddlmZmZmZ ddl	m
Z
 ddlmZ ddlmZ ddlmZ dd	lmZ ddlZ ej(                  e      Z G d
 d      ZeZy)zW
Enhanced rate limiting middleware with bot detection and malicious request filtering.
    N)defaultdict)DictListTuple)HttpResponse)cache)settings)render_to_string)MiddlewareMixinc                   r    e Zd ZdZd Zd Zd Zd Zd Zd Z	d Z
dd	Zd
 Zd Zd Zd Zd Zd Zd Zd Zy)EnhancedRateLimitMiddlewareax  
    Enhanced middleware to rate limit requests and detect malicious bot behavior.
    
    Features:
    - IP-based rate limiting with configurable thresholds
    - Bot detection based on user agents and request patterns
    - Malicious request pattern detection
    - Different rate limits for suspicious vs normal traffic
    - Enhanced logging for security monitoring
    c                    || _         t        t        dd      | _        t        t        dd      | _        t        t        dd      | _        t        t        dd      | _        t        t        d	d
      | _        t        t        dd      | _        t        t        dd      | _	        t        t        dg d      | _
        g d| _        g d| _        g d| _        t        j                  dj!                  | j                        t        j"                        | _        t        j                  dj!                  | j                        t        j"                        | _        y )NRATE_LIMIT_REQUESTSd   RATE_LIMIT_WINDOWi  RATE_LIMIT_BLOCK_DURATIONi  RATE_LIMIT_ENABLEDTRATE_LIMIT_BOT_REQUESTS   RATE_LIMIT_BOT_BLOCK_DURATIONRATE_LIMIT_SUSPICIOUS_REQUESTS
   RATE_LIMIT_EXEMPT_PATHS)
z/static/z/media/z/favicon.icoz/robots.txtz/sitemap.xmlz/admin/jsi18n/z%/inbox/notifications/api/unread_list/z$/inbox/notifications/api/unread_listz/jsi18n/z/reload-messages)masscannmapzmapshodancensyssqlmapniktoacunetixburpzheadless.*chrome.*(?!normal)	phantomjs	scrapybotscrapynutch)curlwgetzpython-requestszpython-httpxjavazgo-httprubynodeaxiosfetchpostmaninsomniazmobile.*safariiphoneandroidchromefirefoxsafariedge)z\.php$z\.asp$z\.jsp$z\.cgi$z/adminz	/wp-adminz/administratorz/loginz/signinz/authz\.env$z	\.config$z	\.backup$z/api/v1z/api/v2z/rest/z1\.\./\.\./\.\./\.\./\.\./\.\./\.\./\.\./\.\./\.\.z<scriptzjavascript:z	vbscript:zunion.*selectzdrop.*tablezinsert.*into|)get_responsegetattrr	   requests_limittime_windowblock_durationenabledbot_requests_limitbot_block_durationsuspicious_requests_limitexempt_pathsbot_user_agents legitimate_user_agents_whitelistsuspicious_patternsrecompilejoin
IGNORECASEbot_user_agent_regexsuspicious_pattern_regex)selfr7   s     ?/var/www/python-projects/worksol/horilla/enhanced_middleware.py__init__z$EnhancedRateLimitMiddleware.__init__   s   ( &h0EsK"8-@$G%h0KTRx)=tD #*(4Mr"R")(4SUY"Z)0;[]_)`& $H.G J
  
1
-	$
  %'JJsxx8L8L/Mr}}$]!(*

388D<T<T3UWYWdWd(e%    c                 .   | j                   s| j                  |      S |j                  j                  d      t	        fd| j
                  D              r| j                  |      S d|j                  v r| j                  |      S t        |d      r'|j                  j                  r| j                  |      S | j                  |      }| j                  |      }| j                  ||      r$| j                  |||       | j                  |      S | j                  ||      r6| j                  ||       | j!                  |||       | j                  |      S | j#                  ||       |dv r| j%                  |||       | j                  |      }|S )N/c              3   ^   K   | ]$  }j                  |j                  d              & yw)rO   N)
startswithrstrip).0pathcurrent_paths     rK   	<genexpr>z7EnhancedRateLimitMiddleware.__call__.<locals>.<genexpr>`   s%     WT|&&t{{3'78Ws   *-z/inbox/notifications/api/user)bot
suspicious)r<   r7   rT   rR   anyr@   hasattrrW   is_authenticatedget_client_ipclassify_request
is_blockedlog_blocked_requestcreate_rate_limit_responseis_rate_limitedblock_iplog_rate_limit_exceededrecord_requestlog_suspicious_request)rJ   request
ip_addressrequest_typeresponserU   s        @rK   __call__z$EnhancedRateLimitMiddleware.__call__Z   sz   ||$$W-- ||**3/WTEVEVWW$$W-- '',,6$$W-- 7F#(E(E$$W--''0
 ,,W5 ??:|4$$Z,G22<@@ 
L9MM*l3((WlK22<@@ 	J5 00''
G\J$$W-rM   c                    |j                   j                  dd      j                         }|j                  j                         }| j	                  |      }|rOt        j                  dj                  | j                        t
        j                        }|j                  |      ry|j                  dk(  r7| j                  j                  |      s| j                  j                  |      ry| j                  |      ry|r| j                  j                  |      ry|j                   j                  d      s|sy| j                  |      ryy)	z/Classify request as normal, bot, or suspicious.HTTP_USER_AGENT r6   normalPOSTrY   rX   HTTP_ACCEPT)METAgetlowerrT   r]   rD   rE   rF   rB   rG   searchmethodrI   is_high_frequency_requestrH   is_scanning_behavior)rJ   rg   
user_agentrT   rh   legitimate_regexs         rK   r^   z,EnhancedRateLimitMiddleware.classify_request   s   \\%%&7<BBD
||!!#''0
 !zz#((43X3X*Y[][h[hi&&z2 >>V#,,33D9T=Z=Z=a=abl=m# ))*5 T66==jI ||.z $$W-rM   c                 4    g d}t        fd|D              S )z,Detect if this looks like scanning behavior.)z/admin/z
/wp-admin/z/phpmyadmin/z/.envz/config.phpc              3   T   K   | ]  }j                   j                  |       ! y w)N)rT   rQ   )rS   rT   rg   s     rK   rV   zCEnhancedRateLimitMiddleware.is_scanning_behavior.<locals>.<genexpr>   s      NT7<<**40Ns   %()rZ   )rJ   rg   suspicious_pathss    ` rK   rx   z0EnhancedRateLimitMiddleware.is_scanning_behavior   s     ]N=MNNNrM   c                    d| }t        j                          }t        j                  |g       }|D cg c]  }||z
  dk  s| }}|j                  |       t        j                  ||dd d       t        |      dkD  S c c}w )z6Check if IP is making more than 3 requests per second.rate_limit_frequency_g      ?iN      )timer   rs   appendsetlen)rJ   rh   frequency_keycurrent_timerequest_timestrecent_timess          rK   rw   z5EnhancedRateLimitMiddleware.is_high_frequency_request   s    /
|<yy{ 		-4 $1LaL14D4KLL 	L) 			-cd!3Q7 < 1$$ Ms   BBc                     |dk(  r| j                   | j                  fS |dk(  r| j                  | j                  fS | j                  | j                  fS )z&Get rate limits based on request type.rY   rX   )r?   r>   r=   r9   r;   )rJ   ri   s     rK   get_limits_for_typez/EnhancedRateLimitMiddleware.get_limits_for_type   sW    <'1143J3JJJU"**D,C,CCC&&(;(;;;rM   c                 4   |j                   j                  d      }|r$|j                  d      d   j                         }|S |j                   j                  d      xs9 |j                   j                  d      xs |j                   j                  dd      }|S )zGet the real client IP address.HTTP_X_FORWARDED_FOR,r   HTTP_X_REAL_IPHTTP_CF_CONNECTING_IPREMOTE_ADDRrn   )rr   rs   splitstrip)rJ   rg   x_forwarded_forips       rK   r]   z)EnhancedRateLimitMiddleware.get_client_ip   s     ",,**+AB &&s+A.446B 	 ,,""#34 6,,""#:;6,,""="5  	rM   c                     d| d| d| S )z3Generate cache key for IP address and request type.rate_limit__ )rJ   rh   key_typeri   s       rK   get_cache_keyz)EnhancedRateLimitMiddleware.get_cache_key   s    XJa~QzlCCrM   c                    | j                  |d|      }|dk(  rl| j                  |dd      }| j                  |dd      }t        j                  |d      xs. t        j                  |d      xs t        j                  |d      S |dk(  rA| j                  |dd      }t        j                  |d      xs t        j                  |d      S t        j                  |d      S )z?Check if IP address is currently blocked for this request type.blockro   rX   rY   F)r   r   rs   )rJ   rh   ri   	block_keybot_block_keysuspicious_block_keys         rK   r_   z&EnhancedRateLimitMiddleware.is_blocked   s    &&z7LI	8# ..z7EJM#'#5#5j'<#X IIi/ ;IImU3;II2E:< U"#'#5#5j'<#X 99Y.X%))<PRW2XX99Y..rM   c                     | j                  |      \  }}| j                  |d|      }t        j                  |d|       | j                  |d|      }t        j                  |       y)zEBlock an IP address for the specified duration based on request type.r   TcountN)r   r   r   r   delete)rJ   rh   ri   r   r;   r   	count_keys          rK   rc   z$EnhancedRateLimitMiddleware.block_ip   s]     44\B>&&z7LI			)T>2 &&z7LI	YrM   c                    | j                  |      \  }}| j                  |d|      }t        j                  |dt	        j                         d      }t	        j                         }|d   }|d   }	||z
  | j
                  kD  ry|	|k\  S )zFCheck if IP address has exceeded the rate limit for this request type.r   r   r   window_startr   F)r   r   r   rs   r   r:   )
rJ   rh   ri   r9   r   r   request_datar   r   r   s
             rK   rb   z+EnhancedRateLimitMiddleware.is_rate_limited   s     44\B&&z7LI	yya,UVyy{#N3W% ,&)9)99 &&rM   c                 D   | j                  |d|      }t        j                  |dt        j                         d      }t        j                         }|d   }|d   }||z
  | j                  kD  rd|d}n|dz   |d<   t        j
                  ||| j                  dz          y)zBRecord a request from an IP address for the specific request type.r   r   r   r      i,  N)r   r   rs   r   r:   r   )rJ   rh   ri   r   r   r   r   r   s           rK   re   z*EnhancedRateLimitMiddleware.record_request
  s    &&z7LI	yya,UVyy{#N3W% ,&)9)99%&EL$)AIL!		)\4+;+;c+ABrM   c                     |dk(  rt        ddd      S 	 t        d      }t        |dd      S #  t        d	dd      cY S xY w)
z6Create appropriate response for rate limited requests.rY   zBad Requesti  z
text/plain)statuscontent_typez429.htmli  z	text/htmlz,Rate limit exceeded. Please try again later.)r   r
   )rJ   ri   contents      rK   ra   z6EnhancedRateLimitMiddleware.create_rate_limit_response  sT    <'cUU*:6#GCkRR#B!- s	   . A c                     |j                   j                  dd      }t        j                  d|j	                          d| d|j
                   d|j                   d|dd	  d
       y)z$Log blocked requests for monitoring.rm   UnknownzBLOCKED  request from 	: method= path= ua='Nr   ')rr   rs   loggerwarningupperrv   rT   rJ   rh   rg   ri   ry   s        rK   r`   z/EnhancedRateLimitMiddleware.log_blocked_request,  sm    \\%%&7C
|))+,N:, Gnn%VGLL>z$3?O>PPQS	
rM   c                    |j                   j                  dd      }| j                  |      \  }}t        j	                  d|j                          d| d|j                   d|j                   d| d| j                   d	| d
|dd  d       y)z Log when rate limit is exceeded.rm   r   zRATE LIMIT EXCEEDED for z from r   r   z limit=rO   zs blocked_for=zs ua='Nr   r   )	rr   rs   r   r   r   r   rv   rT   r:   )rJ   rh   rg   ri   ry   limitsdurations          rK   rd   z3EnhancedRateLimitMiddleware.log_rate_limit_exceeded4  s    \\%%&7C
33LA&|'9'9';&<F:, Onn%VGLL> :HAd../~hZ Hds#$A'	
rM   c                     |j                   j                  dd      }t        j                  d|j	                          d| d|j
                   d|j                   d|dd	  d
       y)z'Log suspicious requests for monitoring.rm   r   zSUSPICIOUS r   r   r   r   Nr   r   )rr   rs   r   infor   rv   rT   r   s        rK   rf   z2EnhancedRateLimitMiddleware.log_suspicious_request?  sm    \\%%&7C
,,,./~j\ Jnn%VGLL>z$3?O>PPQS	
rM   N)ro   )__name__
__module____qualname____doc__rL   rk   r^   rx   rw   r   r]   r   r_   rc   rb   re   ra   r`   rd   rf   r   rM   rK   r   r      s^    	:fx*X"HO%(<D/  '"C""
	

rM   r   )r   r   rD   collectionsr   typingr   r   r   django.httpr   django.core.cacher   django.confr	   django.template.loaderr
   django.utils.deprecationr   logging	getLoggerr   r   r   RateLimitMiddlewarer   rM   rK   <module>r      sT     	 # $ $ $ #   3 4 			8	$s
 s
n	 2 rM   