o
    zqf*y  ã                   @   sf  d Z ddlZddlZddlZddlZddlZddlZddlZddl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ZddlmZ ddlmZ ddlmZmZ G dd	„ d	ejƒZG d
d„ dejƒZdd„ Ze
je
je
jB e
j B e
j!B e
je
jB e
j B e
j!B e
j"B e
je
jB e
j B e
j!B e
j"B e
j#B dœZ$dd„ Z%dd„ Z&G dd„ deeƒZ'e(dkr±e&ƒ  dS dS )aV  
A WebSocket to TCP socket proxy with support for "wss://" encryption.
Copyright 2011 Joel Martin
Licensed under LGPL version 3 (see docs/LICENSE.LGPL-3)

You can make a cert/key with openssl using:
openssl req -new -x509 -days 365 -nodes -out self.pem -keyout self.pem
as taken from http://docs.python.org/dev/library/ssl.html#certificates

é    N)ÚThreadingMixIn)Ú
HTTPServer)Úwebsockifyserver)Úauth_plugins)Úparse_qsÚurlparsec                   @   sD   e Zd ZdZdZdd„ Zdd„ Zdd„ Zd	d
„ Zdd„ Z	dd„ Z
dS )ÚProxyRequestHandleré   zÆ
Traffic Legend:
    }  - Client receive
    }. - Client receive partial
    {  - Target receive

    >  - Target send
    >. - Target send partial
    <  - Client send
    <. - Client send partial
c                 C   sH   |   |j|j¡ |  dd¡ |j ¡ D ]
\}}|  ||¡ q|  ¡  d S )NzContent-Typez	text/html)Úsend_responseÚcodeÚmsgÚsend_headerÚheadersÚitemsÚend_headers)ÚselfÚexÚnameÚval© r   úX/root/parts/websockify/install/lib/python3.10/site-packages/websockify/websocketproxy.pyÚsend_auth_error'   s
   z#ProxyRequestHandler.send_auth_errorc                 C   sF   | j jsd S |  | j j¡\}}|dkr|| j _d S || j _|| j _d S )NÚunix_socket)ÚserverÚtoken_pluginÚ
get_targetÚunix_targetÚtarget_hostÚtarget_port)r   ÚhostÚportr   r   r   Úvalidate_connection/   s   z'ProxyRequestHandler.validate_connectionc              
   C   sª   | j jsd S z| j ¡ }|d }tdd„ |D ƒƒ}|d | jd< W n tttfy-   Y nw z| j jj	| j| j j
| j jd W d S  tjyT   t ¡ d }|  |¡ ‚ w )NÚsubjectc                 S   s   g | ]}|d  ‘qS )r   r   )Ú.0Úxr   r   r   Ú
<listcomp>E   s    z7ProxyRequestHandler.auth_connection.<locals>.<listcomp>Ú
commonNameÚSSL_CLIENT_S_DN_CN)r   r   r   é   )r   Úauth_pluginÚrequestÚgetpeercertÚdictr   Ú	TypeErrorÚAttributeErrorÚKeyErrorÚauthenticater   r   ÚauthÚAuthenticationErrorÚsysÚexc_infor   )r   Úclient_cert_dataÚclient_cert_subjectr   r   r   r   Úauth_connection;   s(   
þ
þ
ýz#ProxyRequestHandler.auth_connectionc                 C   s¢  | j jrdd | j j¡| j jf }n| j jrd| j j }n
d| j j| j jf }| j jr/|d7 }|  |¡ ztj	j
| j j| j jd| j j| j jd}W n tyg } z|  d| j j| j j|¡ |  d	d
¡‚d}~ww | j jsv| j t
jt
jd¡ | j js‡| j js‡| t
jt
jd¡ |  | j¡ z&|  |¡ W |r°| t
j¡ | ¡  | jr²|  d| j j| j j¡ dS dS dS |rÏ| t
j¡ | ¡  | jrÐ|  d| j j| j j¡ w w w )zO
        Called after a new WebSocket connection has been established.
        z%connecting to command: '%s' (port %s)ú zconnecting to unix socket: %szconnecting to: %s:%sú (using SSL)T)ÚconnectÚuse_sslr   zFailed to connect to %s:%s: %sió  z&Failed to connect to downstream serverNr(   z%s:%s: Closed target)r   Úwrap_cmdÚjoinr   r   r   Ú
ssl_targetÚlog_messager   ÚWebSockifyServerÚsocketÚ	ExceptionÚCCloseÚunix_listenr*   Ú
setsockoptÚSOL_TCPÚTCP_NODELAYÚprint_trafficÚtraffic_legendÚdo_proxyÚshutdownÚ	SHUT_RDWRÚcloseÚverbose)r   r   ÚtsockÚer   r   r   Únew_websocket_clientU   sb   ÿ

üÿ€ýÿüýÿüz(ProxyRequestHandler.new_websocket_clientc                 C   sž   | j r| j d¡}|r| d¡d }ntt| jƒd ƒ}d|v r0t|d ƒr0|d d  d¡}nd}|du r<| j	 
d¡‚| |¡}|durG|S | j	 
d	| ¡‚)
zò
        Gets a token from either the path or the host,
        depending on --host-token, and looks up a target
        for that token using the token plugin. Used by
        validate_connection() to set target_host and target_port.
        ÚHostú:r   é   ÚtokenÚ
NzToken not presentzToken '%s' not found)Ú
host_tokenr   ÚgetÚ	partitionr   r   ÚpathÚlenÚrstripr   ÚECloseÚlookup)r   Útarget_pluginrU   ÚargsÚresult_pairr   r   r   r   †   s   
€
zProxyRequestHandler.get_targetc              	   C   s¼  g }d}g }| j |g}| jjrt ¡ }|| jj | _nd| _	 g }| jdur:t ¡ }|| jkr:|| jj | _|  ¡  |rA| |¡ |sE|rK| | j ¡ zt ||g d¡\}}	}
W n% tjtfy}   t	 
¡ d }t|dƒrq|j}n|d }|tjkr{‚ Y qw |
r„tdƒ‚| j |	v r|  |¡}g }| j |v rë|  ¡ \}}| |¡ |rët|ƒdkrÓ| d¡}| |¡}|t|ƒkr¾|  d¡ n| d||d… ¡ |  d¡ t|ƒdks¨| jrá|  d	| jj| jj¡ |  |d
 |d ¡‚||	v r| d¡}| |¡}|t|ƒkr|  d¡ n| d||d… ¡ |  d¡ ||v r]| | j¡}t|ƒdkrSt|ƒdkr>d}|r<|  |¡}|s4g }| jrM|  d| jj| jj¡ |  dd¡‚| |¡ |  d¡ q)zA
        Proxy client WebSocket to normal target socket.
        r   NTr(   ÚerrnozSocket exceptionú>z.>z%s:%s: Client closed connectionr   Úreasonz%s:%s: Target closed connectioniè  zTarget closedÚ{)r*   r   Ú	heartbeatÚtimeÚ	send_pingÚappendÚselectÚerrorÚOSErrorr3   r4   Úhasattrrb   ÚEINTRrB   Úsend_framesÚrecv_framesÚextendr[   ÚpopÚsendrH   ÚinsertrN   r?   r   r   rC   ÚrecvÚbuffer_size)r   ÚtargetÚcqueueÚc_pendÚtqueueÚrlistÚnowÚwlistÚinsÚoutsÚexceptsÚexcÚerrÚbufsÚclosedÚdatÚsentÚbufr   r   r   rJ   ­   s’   




ö






÷ÿ





ÿÿ

¦zProxyRequestHandler.do_proxyN)Ú__name__Ú
__module__Ú__qualname__rv   rI   r   r!   r7   rQ   r   rJ   r   r   r   r   r      s    1'r   c                       s@   e Zd ZdZdZef‡ fdd„	Zdd„ Zdd„ Zd	d
„ Z	‡  Z
S )ÚWebSocketProxyza
    Proxy traffic to and from a WebSockets client to a normal TCP
    socket server target.
    r	   c           
         sÈ  |  dd ¡| _|  dd ¡| _|  dd ¡| _|  dd ¡| _|  dd ¡| _|  dd ¡| _|  dd ¡| _|  dd ¡| _|  d	d ¡| _	|  d
d ¡| _
g d¢| _| jrÕtj tjd ¡}tj |dd¡tj |ddd¡tj |d¡|g}d | _|D ]}tj |d¡}tj |¡rˆ|| _ nqt| jstdƒ‚tj | j¡| _d| _t tjtj¡}| d¡ | ¡ d | _| ¡  td | jtj dd ¡gƒ}	tj tj  |	¡t!|d ƒt!| jƒdœ¡ t"ƒ j#|g|¢R i |¤Ž d S )Nr   r   r<   Ú	wrap_moder   r>   rf   r   rW   r)   )r   r   r   r   z..ÚlibÚ
websockifyz	rebind.soz1rebind.so not found, perhaps you need to run makez	127.0.0.1)Ú r   r(   Ú
LD_PRELOADÚlisten_port)r   ÚREBIND_OLD_PORTÚREBIND_NEW_PORT)$rr   r   r   r<   rŒ   r   r>   rf   r   rW   r)   Ú
wrap_timesÚosrZ   Údirnamer3   Úargvr=   ÚrebinderÚexistsrB   ÚabspathrA   ÚAF_INETÚSOCK_STREAMÚbindÚgetsocknamerM   ÚfilterÚenvironrX   ÚupdateÚpathsepÚstrÚsuperÚ__init__)
r   ÚRequestHandlerClassr`   ÚkwargsÚwsdirÚrebinder_pathÚrdirÚrpathÚsockÚld_preloads©Ú	__class__r   r   r¥      sP   
ýþ


ýzWebSocketProxy.__init__c                 C   sP   |   dd | j¡¡ | j t ¡ ¡ | j d¡ tj| jt	j
td| _d| _d S )NzStarting '%s'r8   r   )ÚenvÚ
preexec_fnT)r   r=   r<   r”   ri   rg   rr   Ú
subprocessÚPopenr•   r    Ú_subprocess_setupÚcmdÚspawn_message)r   r   r   r   Úrun_wrap_cmdT  s   
ÿ
zWebSocketProxy.run_wrap_cmdc                 C   s´   | j rdd | j ¡| jf }n| jr| j}nd| j| jf }| jdkr&d}nd| j| jf }| jr<d|t	| jƒj
f }nd||f }| jrI|d7 }|  d	|¡ | j rX|  ¡  dS dS )
zO
        Called after Websockets server startup (i.e. after daemonize)
        z'%s' (port %s)r8   z%s:%sNÚinetdz/  - proxying from %s to targets generated by %sz  - proxying from %s to %sr9   z%s)r<   r=   r   r   r   Ú	listen_fdÚlisten_hostr‘   r   Útyperˆ   r>   r   r·   )r   Ú
dst_stringÚ
src_stringr   r   r   r   Ústarted\  s*   
ÿÿÿzWebSocketProxy.startedc                 C   sÐ   | j r| jr| j ¡ }|d kr|  d| ¡ d | _| j rb| jd krd| jdkr(d S | jdkr4t |¡ d S | jdkrft ¡ }t| j	ƒt
| j	ƒ }|| dk r\| jrZ|  d¡ d| _d S d S |  ¡  d S d S d S d S )Nz/Wrapped command exited (or daemon). Returned %sÚignoreÚexitÚrespawné
   zCommand respawning too fastF)r<   rµ   ÚpollÚvmsgrŒ   r3   rÀ   rg   Úsumr”   r[   r¶   Úwarnr·   )r   Úretr|   Úavgr   r   r   rÃ   }  s*   





þñzWebSocketProxy.poll)rˆ   r‰   rŠ   Ú__doc__rv   r   r¥   r·   r¾   rÃ   Ú__classcell__r   r   r®   r   r‹     s    4!r‹   c                   C   s   t   t jt j¡ d S )N)ÚsignalÚSIGPIPEÚSIG_DFLr   r   r   r   r´   ˜  s   r´   ©ÚdefaultÚtlsv1_1Útlsv1_2Útlsv1_3c                 C   sN   | t v rt |  S tt  ¡ ƒ}| ¡  |d }t tj¡}| d| |¡ t | S )zXReturns SSL options for the most secure TSL version available on this
    Python versionéÿÿÿÿz.TLS version %s unsupported. Falling back to %s)	ÚSSL_OPTIONSÚlistÚkeysÚsortÚloggingÚ	getLoggerr‹   Ú
log_prefixrÆ   )ÚversionrÖ   ÚfallbackÚloggerr   r   r   Úselect_ssl_version¨  s   ÿrÞ   c                  C   sn  t  ¡ } |  t j¡ t  d¡}|  |¡ t  ¡ }| | ¡ | t j¡ d}|d7 }|d7 }|d7 }|d7 }|d7 }|d7 }|d7 }t	j
|d}|jdd	d
dd |jdd
dd |jdddd |jdddd
dd |jdd
dd |jdtddd |jdtddd |jd d!d"d# |jd$d d%d# |jd&d d'd# |jd(d
d)d |jd*d
d+d |jd,d
d-d |jd.dd/d0 |jd1d2d3g d4¢d5d6d7 |jd8d5d9d |jd:d;dd d< |jd=d d>d# |jd?d@dd |jdAdBd
dC |jdDd dEdFdG |jdHd
dId |jdJdKdLg dM¢dNdO |jdPdQd
dRdSdT |jdUd
dVd |jdWddXdYdZ |jd[d d\d]dG |jd^d d_d`dG |jdad
dbd |jdcd d\dddG |jded d_dfdG |jdgtddhdidj |jdkddldmdZ |jdnd dodpdG |jdqd
drd |jdsd
dtd | ¡ \}}|jr•|js•| du¡ |jr¢|js¢| dv¡ |jr¯|js¯| dw¡ |jr¼|js¼| dx¡ |jrÉ|jsÉ| dy¡ |jrÖ|jsÖ| dz¡ t|jƒ|_|`|jrtj |j¡|_t  |j¡}| t j¡ | |¡ t  ¡ }| |¡ |`|jrj|j  d{¡r5|j !d{d|¡\}}	zt|	ƒ}	W n t"y/   | d}¡ Y nw ||	f}
ntj |j¡}
dd~l#m$} |j%rJ|j&}n|j'}||
|d|jd€}| t j¡ | |¡ t  ¡ }| |¡ |`|`|j(r|t  ¡ }| t j¡ |j)rˆtj |j)¡|_)|j)r“d|_|j)|_|`)t*j+  d‚¡r¤|d|d … |_,nd |_,t-j.s´|j/r´| dƒ¡ |j0rÈtj 1|j2¡sÈ| d„|j2 ¡ |j3rÓt*j4 5¡ |_6ns|j7rü|j8rôz	t|j8d…ƒ|_8W na t"yó   | d†¡ Y nSw t9j:t9j;B |_8nJt<|ƒd|k r| d‡¡ | =d¡}|  d{¡dkr'| !d{d|¡\|_>|_?|j> @dˆ¡|_>nd‰||_>|_?zt|j?ƒ|_?W n t"yE   | dŠ¡ Y nw |`3|j,sT|jAsT|jr[d |_Bd |_CnHt<|ƒd|k rg| d‡¡ | =d¡}|  d{¡dkr†| !d{d|¡\|_B|_C|jB @dˆ¡|_Bn| d‹¡ zt|jCƒ|_CW n t"y¢   | dŒ¡ Y nw t<|ƒdkrµ|j,d krµ| d¡ |jd urâdŽ|jvrÇd|j |_|j !dŽd|¡\}}tD|ƒ tEt*jF| |ƒ}||jƒ|_|`|jd urdŽ|jvröd|j |_|j !dŽd|¡\}}tD|ƒ tEt*jF| |ƒ}||jƒ|_|`|jG}|`G|r)tHd‘i |jI¤Ž}| J¡  d S tKd‘i |jI¤Ž}| L¡  d S )’Nz%(message)sz
    %prog [options]z2 [source_addr:]source_port target_addr:target_portz/ --token-plugin=CLASS [source_addr:]source_portz- --unix-target=FILE [source_addr:]source_portz/ [source_addr:]source_port -- WRAP_COMMAND_LINE)Úusagez	--verbosez-vÚ
store_truezverbose messages)ÚactionÚhelpz	--trafficzper frame trafficz--recordz(record sessions to FILE.[session_number]ÚFILE)râ   Úmetavarz--daemonz-DÚdaemonz$become a daemon (background process))Údestrá   râ   z
--run-oncez-handle a single WebSocket connection and exitz	--timeoutr   z-after TIMEOUT seconds exit when not connected)r»   rÏ   râ   z--idle-timeoutzEserver exits after TIMEOUT seconds if there are no active connectionsz--certzself.pemzSSL certificate file)rÏ   râ   z--keyz$SSL key file (if separate from cert)z--key-passwordzSSL key passwordz
--ssl-onlyz)disallow non-encrypted client connectionsz--ssl-targetz#connect to SSL target as SSL clientz--verify-clientzlrequire encrypted client to present a valid certificate (needs Python 2.7.9 or newer or Python 3.4 or newer)z--cafilez¦file of concatenated certificates of authorities trusted for validating clients (only effective with --verify-client). If omitted, system default list of CAs is used.)rä   râ   z--ssl-versionÚchoicerÏ   rÎ   Ústorez?minimum TLS version to use (default, tlsv1_1, tlsv1_2, tlsv1_3))r»   rÏ   Úchoicesrá   râ   z--ssl-ciphersz]list of ciphers allowed for connection. For a list of supported ciphers run `openssl ciphers`z--unix-listenzlisten to unix socket)râ   rä   rÏ   z--unix-listen-modez/specify mode for unix socket (defaults to 0600)z--unix-targetzconnect to unix socket targetz--inetdz/inetd mode, receive listening socket from stdin)râ   rá   z--webÚDIRz1run webserver on same port. Serve files from DIR.)rÏ   rä   râ   z
--web-authz+require authentication to access webserver.z--wrap-moderÀ   ÚMODE)rÀ   r¿   rÁ   z\action to take when the wrapped program exits or daemonizes: exit (default), ignore, respawn)rÏ   rä   ré   râ   z--prefer-ipv6z-6Úsource_is_ipv6z&prefer IPv6 when resolving source_addr)rá   ræ   râ   z--libserverz&use Python library SocketServer enginez--target-configÚ
target_cfgzíConfiguration file containing valid targets in the form 'token: host:port' or, alternatively, a directory containing configuration files of this form (DEPRECATED: use `--token-plugin TokenFile --token-source  path/to/token/file` instead))rä   ræ   râ   z--token-pluginÚCLASSzxuse a Python class, usually one from websockify.token_plugins, such as TokenFile, to process tokens into host:port pairsz--token-sourceÚARGz=an argument to be passed to the token plugin on instantiationz--host-tokenzJuse the host HTTP header as token instead of the token URL query parameterz--auth-pluginz|use a Python class, usually one from websockify.auth_plugins, such as BasicHTTPAuth, to determine if a connection is allowedz--auth-sourcez<an argument to be passed to the auth plugin on instantiationz--heartbeatÚINTERVALz0send a ping to the client every INTERVAL seconds)r»   rÏ   rä   râ   z
--log-fileÚlog_filezFile where logs will be savedz--syslogÚSERVERz\Log to syslog server. SERVER can be local socket, such as /dev/log, or a UDP host:port pair.z--legacy-syslogzoUse the old syslog protocol instead of RFC 5424. Use this if the messages produced by websockify seem abnormal.z--file-onlyz5use this to disable directory listings in web server.z1You must use --token-plugin to use --token-sourcez/You must use --token-plugin to use --host-tokenz/You must use --auth-plugin to use --auth-sourcez,You must use --auth-plugin to use --web-authz$You must use --web to use --web-authz,You must use --syslog to use --legacy-syslogrS   r(   zError parsing syslog port)ÚWebsockifySysLogHandlerrŽ   )ÚaddressÚfacilityÚidentÚlegacyÚ	TokenFilez--z6SSL target requested and Python SSL module not loaded.zSSL only and %s not foundé   z%Error parsing listen unix socket modezToo few argumentsz[]r   zError parsing listen portzError parsing targetzError parsing target portzToo many argumentsÚ.zwebsockify.token_plugins.%szwebsockify.auth_plugins.%sr   )MrØ   ÚStreamHandlerÚsetLevelÚDEBUGÚ	FormatterÚsetFormatterrÙ   Ú
addHandlerÚINFOÚoptparseÚOptionParserÚ
add_optionÚintÚ
parse_argsÚtoken_sourcer   rk   rW   Úauth_sourcer)   Úweb_authÚwebÚlegacy_syslogÚsyslogrÞ   Ússl_versionÚssl_optionsrñ   r•   rZ   rš   ÚFileHandlerÚcountÚrsplitÚ
ValueErrorÚwebsockify.sysloghandlerró   rå   Ú
LOG_DAEMONÚLOG_USERrN   rí   r3   r—   r<   r   Ússlr>   Ússl_onlyr™   Úcertr¸   ÚstdinÚfilenor¹   rD   Úunix_listen_modeÚstatÚS_IREADÚS_IWRITEr[   rr   rº   r‘   Ústripr   r   r   Ú
__import__ÚgetattrÚmodulesÚ	libserverÚLibProxyServerÚ__dict__Úserve_foreverr‹   Ústart_server)Ústderr_handlerÚlog_formatterÚrootrß   ÚparserÚoptsr`   Úlog_file_handlerÚsyslog_hostÚsyslog_portÚsyslog_destró   Úsyslog_facilityÚsyslog_handlerÚargÚtoken_plugin_moduleÚtoken_plugin_clsÚauth_plugin_moduleÚauth_plugin_clsr#  r   r   r   r   Úwebsockify_init¹  s  



ÿÿÿþÿ
ÿ
ÿÿÿÿÿÿÿÿ
þÿÿÿÿÿ
ÿÿ
þþÿþ
ÿ
ÿÿ
ÿ
ÿÿþ
ÿÿÿ







ÿ
ý


ÿ

ÿ


ÿ
ÿr8  c                       s0   e Zd ZdZef‡ fdd„	Z‡ fdd„Z‡  ZS )r$  zX
    Just like WebSocketProxy, but uses standard Python SocketServer
    framework.
    c                    s:  |  dd ¡| _|  dd ¡| _|  dd ¡| _|  dd ¡| _|  dd ¡| _|  dd ¡| _|  dd ¡| _|  dd ¡| _|  d	d ¡| _	d | _d | _d
| _
|  dd¡}|  dd ¡}|  dd¡}| | _|  dd
¡| _|  dd¡}|rttj |¡| _|  dd
¡| _d| _| ¡ D ]}td| ƒ q‚|r’t |¡ tƒ  ||f|¡ d S )Nr   r   r<   rŒ   r   r>   r   r)   rf   Frº   r   r‘   r
  rN   ÚrecordÚrun_oncer   z1warning: option %s ignored when using --libserver)rr   r   r   r<   rŒ   r   r>   r   r)   rf   rå   Úonly_upgraderN   r•   rZ   rš   r9  r:  Ú
handler_idrÖ   ÚprintÚchdirr¤   r¥   )r   r¦   r§   rº   r‘   r
  r9  r3  r®   r   r   r¥   ò  s6   
zLibProxyServer.__init__c                    s    |  j d7  _ tƒ  ||¡ dS )z/Override process_request to implement a counterr(   N)r<  r¤   Úprocess_request)r   r*   Úclient_addressr®   r   r   r?    s   zLibProxyServer.process_request)rˆ   r‰   rŠ   rÉ   r   r¥   r?  rÊ   r   r   r®   r   r$  ì  s    'r$  Ú__main__))rÉ   rË   rA   r  rg   r•   r3   r²   rØ   rb   r  r  Úsocketserverr   Úhttp.serverr   rj   rŽ   r   r   r1   Úurllib.parser   r   ÚWebSockifyRequestHandlerr   r@   r‹   r´   ÚOP_ALLÚPROTOCOL_SSLv23ÚOP_NO_SSLv2ÚOP_NO_SSLv3ÚOP_NO_TLSv1ÚOP_NO_TLSv1_1ÚOP_NO_TLSv1_2rÔ   rÞ   r8  r$  rˆ   r   r   r   r   Ú<module>   sN   X   ÿÿÿÿÿÿú
  53
ÿ