
    kjH                    F   d Z ddlmZ ddlZddlZddl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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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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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/m0Z0 ejb                  d"k  rdd#l2m3Z3 ndd#l	m3Z3  ejh                  e5      Z6	 	 	 	 	 	 d,d$Z7 G d% d&e8      Z9 G d' d(      Z:h d)Z;h d*Z<d-d+Z=y).a|  
This addon determines the next protocol layer in our proxy stack.
Whenever a protocol layer in the proxy wants to pass a connection to a child layer and isn't sure which protocol comes
next, it calls the `next_layer` hook, which ends up here.
For example, if mitmproxy runs as a regular proxy, we first need to determine if
new clients start with a TLS handshake right away (Secure Web Proxy) or send a plaintext HTTP CONNECT request.
This addon here peeks at the incoming bytes and then makes a decision based on proxy mode, mitmproxy options, etc.

For a typical HTTPS request, this addon is called a couple of times: First to determine that we start with an HTTP layer
which processes the `CONNECT` request, a second time to determine that the client then starts negotiating TLS, and a
third time when we check if the protocol within that TLS stream is actually HTTP or something else.

Sometimes it's useful to hardcode specific logic in next_layer when one wants to do fancy things.
In that case it's not necessary to modify mitmproxy's source, adding a custom addon with a next_layer event hook
that sets nextlayer.layer works just as well.
    )annotationsN)Iterable)Sequence)Any)cast)ctx)Address)starts_like_dtls_record)starts_like_tls_record)layer)layers)
mode_specs)tunnel)Context)Layer)ClientQuicLayer)ClientTLSLayer)DNSLayer)	HttpLayer)modes)RawQuicLayer)ServerQuicLayer)ServerTLSLayer)TCPLayer)UDPLayer)HTTPMode)&quic_parse_client_hello_from_datagrams)dtls_parse_client_hello)
HTTP_ALPNS)parse_client_hello)ClientHello)      )assert_neverc                    t        | j                        t        |      k7  ryt        d t        | j                  |      D              S )NFc              3  N   K   | ]  \  }}|t         u xs t        ||        y wN)r   
isinstance).0actualexpecteds      d/home/ubuntu/.cache/pipx/cdb5059130eadca/lib/python3.12/site-packages/mitmproxy/addons/next_layer.py	<genexpr>zstack_match.<locals>.<genexpr>D   s/      FH 	C7:fh77s   #%)lenr   allzip)contextr   s     r,   stack_matchr2   ?   sA     7>>c&k)  #GNNF ;      c                      e Zd ZdZy)NeedsMoreDatazdSignal that the decision on which layer to put next needs to be deferred within the NextLayer addon.N)__name__
__module____qualname____doc__ r3   r,   r5   r5   J   s    nr3   r5   c                      e Zd ZU dZded<   dZded<   dZded<   dZded<   d ZddZ		 	 	 	 	 	 	 	 dd	Z
	 	 	 	 	 	 	 	 dd
Ze	 	 	 	 	 	 	 	 dd       Zedd       Zedd       Zedd       Zedd       Zy)	NextLayerr:   zSequence[re.Pattern]ignore_hostsallow_hosts	tcp_hosts	udp_hostsc                   d|v rOt         j                  j                  D cg c]&  }t        j                  |t        j
                        ( c}| _        d|v rOt         j                  j                  D cg c]&  }t        j                  |t        j
                        ( c}| _        d|v sd|v rt         j                  j                  D cg c]&  }t        j                  |t        j
                        ( c}| _        t         j                  j                  D cg c]&  }t        j                  |t        j
                        ( c}| _        y y c c}w c c}w c c}w c c}w )Nr?   r@   r>   r=   )	r   optionsr?   recompile
IGNORECASEr@   r=   r>   )selfupdatedxs      r,   	configurezNextLayer.configureT   s   '!69kk6K6K12

1bmm,DN '!69kk6K6K12

1bmm,DN G#~'@69kk6N6N!12

1bmm,!D 7:kk6M6M 12

1bmm, D	 (A! s   +E4+E+E+Ec                "   |j                   ry 	 | j                  |j                  |j                         |j	                               |_         y # t
        $ r7 t        j                  d|j                         j                                Y y w xY w)Nz+Deferring layer decision, not enough data: )	r   _next_layerr1   data_clientdata_serverr5   loggerdebughex)rF   	nextlayers     r,   
next_layerzNextLayer.next_layere   s~    ??		"..!!%%'%%'IO
  	LL=i>S>S>U>Y>Y>[=^_	s   >A =BBc                <   j                   sJ fd}j                  j                  dk(  }j                  j                  dk(  }| j                  ||      rb|r0t        j                  t
        j                  j                         S t        j                  t
        j                  j                         S  |t        j                        r| j                  |      S  |t        j                  t        j                  f      r| j                  |      S |xr t        |      xs |xr t!        |      }|rt#              }t%              |_        |S |r=t)        |j*                  j,                        rt/              }	t1              |	_        |	S |r1| j3                  | j4                        rt        j                        S |r1| j3                  | j6                        rt        j                        S j                  j8                  rpj                  j8                  t:        v r$t        j<                  t>        j@                        S j                  jB                  dk(  rt        jD                  d      S j*                  j,                  r0j*                  j,                  d   d	v rt        jF                        S |rt        j                        S tI        |      d
k  xsV d|vxsP |jK                  d      |jK                  d      kD  xs+ |d d
 jM                          xs |xs |jO                  d      }
t
        j                  jP                  r|
rt        j                        S t        j<                  t>        j@                        S )Nc                     t        |       S r'   )r2   )r   r1   s    r,   sz NextLayer._next_layer.<locals>.sx   s    w//r3   tcpudp)ignoreQUICv1T	force_raw   )5   i  r"          
s   SSH))r   clienttransport_protocol_ignore_connectionr   r   rB   show_ignored_hostsr   r   ReverseProxy_setup_reverse_proxy	HttpProxyHttpUpstreamProxy_setup_explicit_http_proxyr   r
   r   r   child_layer_starts_like_quicserveraddressr   r   _is_destination_in_hostsr?   r@   alpnr   r   r   transparenttls_versionr   r   r.   findisalpha
startswithrawtcp)rF   r1   rL   rM   rU   	tcp_based	udp_basedis_tls_or_dtls
server_tlsserver_quicprobably_no_https    `         r,   rK   zNextLayer._next_layers   s    ~~~	0 NN55>	NN55>	 ""7KE  CKK4R4R0RS __W9W9W5WX U ,,WkBBeoou6678227KHH
  4&{35 5'4	 	 '0J%3G%<J"*;8N8NO)'2K&5g&>K# 66wO??7++66wO??7++ >>~~""j0''1E1EFF++x7**7dCC>>!!gnn&<&<Q&?:&M??7++??7++ q  .;&.   &)9)9%)@@	.
 r?**,,. . %%f- 	 ;;"2??7++)=)=>>r3   c                `   t         j                  j                  st         j                  j                  syt	        |j
                  j                  t        j                        r|j                  j                  dk(  ryg }|j                  j                  r/|j                  j                  ^}}}|j                  | d|        |j                  j                  r|j                  j                  ^}}}|j                  | d|        | j                  |||      x}r.t        j                  d|      s| d| }|j                  |       | j!                  ||      x}	r,|	j"                  r |j                  |	j"                   d|        |j
                  j"                  r*|j                  |j
                  j"                   d|        |syt         j                  j                  rt%        d |D               }
|
ryt         j                  j                  rt%        d |D              }|ryy)z
        Returns:
            True, if the connection should be ignored.
            False, if it should not be ignored.

        Raises:
            NeedsMoreData, if we need to wait for more input data.
        F)z	10.0.0.53r]   :z:\d+$c              3     K   | ]H  }t         j                  j                  D ])  }t        j                  ||t        j
                         + J y wr'   )r   rB   r>   rC   searchrE   r)   hostrexs      r,   r-   z/NextLayer._ignore_connection.<locals>.<genexpr>   sH      ";;22"  		#tR]]3"3"   AATc              3     K   | ]H  }t         j                  j                  D ])  }t        j                  ||t        j
                         + J y wr'   )r   rB   r=   rC   r~   rE   r   s      r,   r-   z/NextLayer._ignore_connection.<locals>.<genexpr>   sH      ;;33  		#tR]]33r   )r   rB   r=   r>   r(   r`   
proxy_moder   WireGuardModerk   rl   peernameappend_get_host_headerrC   r~   _get_client_hellosniany)rF   r1   rL   rM   	hostnamesr   port_host_headerclient_hellonot_allowedignoreds               r,   rb   zNextLayer._ignore_connection   s    {{''0G0GNN%%z'?'?
nn$$(99!	>>""$^^44ND$vQtf-.>>!!$^^33ND$vQtf-.
 #33G[+VV{Vyy;7%0M4&"9K  - $ 6 6w LLL""  L$4$4#5Qtf!=>~~!!  GNN$6$6#7q!?@;;""! "%"  K
 ;;## % G
 r3   c                0   | j                   j                  dk7  s|ryt        j                  d|t        j                        }|rSt        j
                  d|t        j                        x}r&|j                  d      x}r|j                  dd      S yt        y)z
        Try to read a host header from data_client.

        Returns:
            The host header value, or None, if no host header was found.

        Raises:
            NeedsMoreData, if the HTTP request is incomplete.
        rV   Ns   [A-Z]{3,}.+HTTP/s   \r\n(?:Host:\s+(.+?)\s*)?\r\nr\   zutf-8surrogateescape)	r`   ra   rC   matchrE   r~   groupdecoder5   )r1   rL   rM   host_header_expectedmr   s         r,   r   zNextLayer._get_host_header	  s     >>,,5!xx +r}} 
  II1; q  771:%4%;;w0ABB##r3   c                f   | j                   j                  xdk(  r# t        |      r	 t        |      }|t        |S ydk(  r	 t        |g      S 	 t        | j                   j                         y# t
        $ r Y yw xY w# t
        $ r Y nw xY w	 t        |      }|t        |S # t
        $ r Y yw xY w)z
        Try to read a TLS/DTLS/QUIC ClientHello from data_client.

        Returns:
            A complete ClientHello, or None, if no ClientHello was found.

        Raises:
            NeedsMoreData, if the ClientHello is incomplete.
        rV   NrW   )	r`   ra   r   r    r5   
ValueErrorr   r   r$   )r1   rL   chs      r,   r   zNextLayer._get_client_hello+  s     nn//)+6"/< :"//!	A;-PP W^^>>?/ & 
  " 0=B z++I " 
 s5   A0 A? 0	A<;A<?	B
BB$ $	B0/B0c                   t        t        j                  | j                  j                        }t        j                         }|j                  xdk(  r< t        |      r|t        |       z  }|t        | t        j                        z  }|d   S xdk(  r | j                  j                  dk(  r>|t        |       z  }|t        |       z  }|t        | t        j                        z  }|d   S |t!        |       z  }t        |      r|t        |       z  }|t        | t        j                        z  }|d   S xdk(  r- t        |      r|t        |       z  }|t#        |       z  }|d   S xdk(  r; |t!        |       z  }t        |      r|t        |       z  }|t#        |       z  }|d   S xdk(  r- t%        |      r|t        |       z  }|t'        |       z  }|d   S xdk(  r; |t!        |       z  }t%        |      r|t        |       z  }|t'        |       z  }|d   S xdk(  r |t)        |       z  }|d   S xdk(  r? |t        |       z  }|t        |       z  }|t        | t        j                        z  }|d   S d	k(  r1|t        |       z  }|t        |       z  }|t+        | d
      z  }|d   S 	 t-        |j                         |d   S )NhttphttpsrW   rV   tlsdtlsdnshttp3quicTrZ   r   )r   r   ReverseModer`   r   r   
LayerStackschemer   r   r   r   ro   ra   r   r   r   r   r
   r   r   r   r$   )r1   rL   specstacks       r,   re   zNextLayer._setup_reverse_proxyT  s   J**GNN,E,EF!!#kk)+6^G44E7H,@,@AAn Qxm >>44=_W55E_W55EYw0D0DEEEd Qxa ^G44E-k:!88Yw0D0DEEEZ QxW )+6^G44E'**P QxO 00)+6^G44E'**F QxC *;7^G44E'**< Qx; 00*;7^G44E'**2 Qx/  '** Qx 11117H,@,@AA Qx 1111g>>
 Qx T[[)Qxr3   c                   t        j                         }| j                  j                  dk(  r|t	        j
                  |       z  }n#t        |      r|t	        j                  |       z  }t        | j                  d   t        j                        r,|t	        j                  | t        j                        z  }|d   S |t	        j                  | t        j                        z  }|d   S )NrW   r   )r   r   r`   ra   r   r   r   r   r(   r   rg   r   r   upstreamregular)r1   rL   r   s      r,   rh   z$NextLayer._setup_explicit_http_proxy  s    !!#>>,,5V++G44E#K0V**733EgnnQ')@)@AV%%gx/@/@AAE Qx V%%gx/?/?@@EQxr3   c                ,     t         fd|D              S )Nc              3    K   | ]  }j                   j                  xr( |j                  j                   j                  d          xs= j                  j                  xr% |j                  j                  j                          yw)r   N)rk   rl   r~   r`   r   )r)   r   r1   s     r,   r-   z5NextLayer._is_destination_in_hosts.<locals>.<genexpr>  ss      
  ^^##M

7>>3I3I!3L(M G""Eszz'..2D2D'EG
s   B	B)r   )r1   hostss   ` r,   rm   z"NextLayer._is_destination_in_hosts  s     
 
 
 	
r3   N)rQ   zlayer.NextLayer)r1   r   rL   bytesrM   r   returnzLayer | None)r1   r   rL   r   rM   r   r   zbool | None)r1   r   rL   r   rM   r   r   z
str | None)r1   r   rL   r   r   zClientHello | None)r1   r   rL   r   r   r   )r1   r   r   zIterable[re.Pattern]r   bool)r6   r7   r8   r=   __annotations__r>   r?   r@   rI   rR   rK   rb   staticmethodr   r   re   rh   rm   r:   r3   r,   r<   r<   N   s!   )+L&+(*K%*&(I#(&(I#("Q?Q?-2Q?AFQ?	Q?fAA A 	A
 
AF   
	 B &@ &@P ? ?B   
 
r3   r<   >   050Q340Q640QPpC3kr\   >        P   c                    t        |       dk  ryt        |       ry| d   dz  r+t        j                  | dd d      }|t        v ry|d	z  d
k(  ry	 t        |xr |d   t        v       S )a  
    Make an educated guess on whether this could be QUIC.
    This turns out to be quite hard in practice as 1-RTT packets are hardly distinguishable from noise.

    Returns:
        True, if the passed bytes could be the start of a QUIC packet.
        False, otherwise.
       Fr      r\      bigTii



)r.   r
   int
from_bytesKNOWN_QUIC_VERSIONSr   TYPICAL_QUIC_PORTS)rL   server_addressversions      r,   rj   rj     s     ;"{+ 1~..Qq!159)) Z:- 	J>!#48J#JKKr3   )r1   r   r   z/Sequence[type[Layer] | tuple[type[Layer], ...]]r   r   )rL   r   r   zAddress | Noner   r   )>r9   
__future__r   loggingrC   syscollections.abcr   r   typingr   r   	mitmproxyr   mitmproxy.connectionr	   mitmproxy.net.tlsr
   r   mitmproxy.proxyr   r   r   r   mitmproxy.proxy.contextr   mitmproxy.proxy.layerr   mitmproxy.proxy.layersr   r   r   r   r   r   r   r   r   r   mitmproxy.proxy.layers.httpr   mitmproxy.proxy.layers.quicr   mitmproxy.proxy.layers.tlsr   r   r    mitmproxy.tlsr!   version_infotyping_extensionsr$   	getLoggerr6   rN   r2   	Exceptionr5   r<   r   r   rj   r:   r3   r,   <module>r      s   " #  	 
 $ $    ( 5 4 ! " & " + ' 2 1 + , ( / 2 1 + + 0 N > 1 9 %g.#			8	$M	oI o^
 ^
D  % Lr3   