o
    &æÑgz  ã                   @   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 dd„ | jD ƒ}|D ]}| j|= q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ye   t ¡ d }|  |¡ ‚ w )	Nc                 S   s   g | ]	}|  d ¡r|‘qS )ÚSSL_)Ú
startswith)Ú.0Úhr   r   r   Ú
<listcomp>A   s    z7ProxyRequestHandler.auth_connection.<locals>.<listcomp>Úsubjectc                 S   s   g | ]}|d  ‘qS )r   r   )r$   Úxr   r   r   r&   K   s    Ú
commonNameÚSSL_CLIENT_S_DN_CN)r   r   r   é   )r   Úauth_pluginr   ÚrequestÚgetpeercertÚdictÚ	TypeErrorÚAttributeErrorÚKeyErrorÚauthenticater   r   ÚauthÚAuthenticationErrorÚsysÚexc_infor   )r   Ússl_headersr%   Ú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_client[   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_pluginrY   Ú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yz   t 	¡ d }t
|dƒrn|j}n|d }|tjkrx‚ Y qw |
rt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 rZ| | j¡}t|ƒdkrPt|ƒdkr;d}|r9|  |¡}|s1g }| jrJ|  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ÚOSErrorr6   r7   Úhasattrrf   ÚEINTRrF   Úsend_framesÚrecv_framesÚextendr_   ÚpopÚsendrL   ÚinsertrR   rC   r   r   rG   ÚrecvÚbuffer_size)r   ÚtargetÚcqueueÚc_pendÚtqueueÚrlistÚnowÚwlistÚinsÚoutsÚexceptsÚexcÚerrÚbufsÚclosedÚdatÚsentÚbufr   r   r   rN   ³   s’   




ö






÷ÿ





ÿÿ

¦zProxyRequestHandler.do_proxyN)Ú__name__Ú
__module__Ú__qualname__ry   rM   r   r!   r;   rU   r   rN   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   rB   rj   r   r[   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)$ru   r   r   r@   r   r   rB   rj   r   r[   r,   Ú
wrap_timesÚosr^   Údirnamer6   ÚargvrA   ÚrebinderÚexistsrF   ÚabspathrE   ÚAF_INETÚSOCK_STREAMÚbindÚgetsocknamerQ   ÚfilterÚenvironr\   ÚupdateÚpathsepÚstrÚsuperÚ__init__)
r   ÚRequestHandlerClassrd   Ú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'r<   r   )ÚenvÚ
preexec_fnT)r   rA   r@   r—   rm   rk   ru   Ú
subprocessÚPopenr˜   r£   Ú_subprocess_setupÚcmdÚspawn_message)r   r   r   r   Úrun_wrap_cmdZ  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)r<   z%s:%sNÚinetdz/  - proxying from %s to targets generated by %sz  - proxying from %s to %sr=   z%s)r@   rA   r   r   r   Ú	listen_fdÚlisten_hostr”   r   Útyper‹   rB   r   rº   )r   Ú
dst_stringÚ
src_stringr   r   r   r   Ústartedb  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   r6   rÃ   rk   Úsumr—   r_   r¹   Úwarnrº   )r   Úretr   Úavgr   r   r   rÆ   ƒ  s*   





þñzWebSocketProxy.poll)r‹   rŒ   r   Ú__doc__ry   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-syslogrW   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   Úerrorr[   Úauth_sourcer,   Úweb_authÚwebÚlegacy_syslogÚsyslográ   Ússl_versionÚssl_optionsrô   r˜   r^   r   ÚFileHandlerÚcountÚrsplitÚ
ValueErrorÚwebsockify.sysloghandlerrö   rè   Ú
LOG_DAEMONÚLOG_USERrR   rð   r6   rš   r@   r   ÚsslrB   Ússl_onlyrœ   Úcertr»   ÚstdinÚfilenor¼   rH   Úunix_listen_modeÚstatÚS_IREADÚS_IWRITEr_   ru   r½   r”   Ústripr   r   r   Ú
__import__ÚgetattrÚmodulesÚ	libserverÚLibProxyServerÚ__dict__Úserve_foreverrŽ   Ústart_server)Ústderr_handlerÚlog_formatterÚrootrâ   ÚparserÚoptsrd   Ú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  



ÿÿÿþÿ
ÿ
ÿÿÿÿÿÿÿÿ
þÿÿÿÿÿ
ÿÿ
þþÿþ
ÿ
ÿÿ
ÿ
ÿÿþ
ÿÿÿ







ÿ
ý


ÿ

ÿ


ÿ
ÿr<  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   rB   r   r,   rj   Fr½   r’   r”   r  rR   ÚrecordÚrun_oncer   z1warning: option %s ignored when using --libserver)ru   r   r   r@   r   r   rB   r   r,   rj   rè   Úonly_upgraderR   r˜   r^   r   r=  r>  Ú
handler_idrÙ   ÚprintÚchdirr§   r¨   )r   r©   rª   r½   r”   r  r=  r7  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   rC    s   zLibProxyServer.process_request)r‹   rŒ   r   rÌ   r   r¨   rC  rÍ   r   r   r±   r   r(  ò  s    'r(  Ú__main__))rÌ   rÎ   rE   r  rk   r˜   r6   rµ   rÛ   rf   r  r   Úsocketserverr   Úhttp.serverr   rn   r‘   r   r   r4   Úurllib.parser   r   ÚWebSockifyRequestHandlerr   rD   rŽ   r·   ÚOP_ALLÚPROTOCOL_SSLv23ÚOP_NO_SSLv2ÚOP_NO_SSLv3ÚOP_NO_TLSv1ÚOP_NO_TLSv1_1ÚOP_NO_TLSv1_2r×   rá   r<  r(  r‹   r   r   r   r   Ú<module>   sN   X  	 ÿÿÿÿÿÿú
  53
ÿ