Comments (14)
I did not find "attach file"
So it is published just as a comment. I hope it will not be damaged by formatter.
# websockify proxy to serve noVNC (http://kanaka.github.com/noVNC/)
# with Apache + mod_python + pywebsocket
# Inspired by websockify project (https://github.com/kanaka/websockify)
#
# Supports noVNC path feature
# but in different way than original websockify do:
# GET parameters have to be specified
# like http://your.host.dom/vnc/ws/websockify?host=localhost&port=5900
# or just http://your.host.dom/vnc/ws/websockify?port=5900
# as localhost is default
#
# Created by Daniel Podolsky, [email protected], 22 Nov 2011
#
# Install
# 1) Install Apache 2.2 (http://httpd.apache.org/) with mod_python
# 2) Install pywebsocket (http://code.google.com/p/pywebsocket/)
# 3) Place websockify_wsh.py somewhere. Say, /var/www/vnc/ws/websockify_wsh.py
# 4) Configure apache:
# PythonOption mod_pywebsocket.handler_root /var/www/vnc
# PythonOption mod_pywebsocket.handler_scan /var/www/vnc/ws
#
# <Location /vnc/ws>
# PythonHeaderParserHandler mod_pywebsocket.headerparserhandler
# PythonDebug On
# </Location>
#
# Note: 'PythonOption mod_pywebsocket.handler_*' must be placed
# in the global Apache config scope
# (see http://www.mailinglistarchive.com/html/[email protected]/2006-09/msg00720.html)
import socket
from sys import exc_info
from urlparse import parse_qs
from base64 import b64encode, b64decode
from mod_python import apache
from mod_pywebsocket import msgutil
def list_value(array, key, def_val=None):
if key in array:
return array[key]
if def_val is not None:
return def_val
raise ValueError("websockify: '%s' is not specified" % (key))
def web_socket_do_extra_handshake(request):
request.ws_protocol = request.ws_requested_protocols[0]
request.log_error("websockify: ws_protocol = '%s' (%s)" % (request.ws_protocol, request.ws_requested_protocols), apache.APLOG_DEBUG)
pass # Always accept.
def web_socket_transfer_data(request):
args_parsed = parse_qs(request.args, False, True)
target_port = list_value(args_parsed, 'port')[0]
target_host = list_value(args_parsed, 'host', def_val=['localhost'])[0]
target = connect(target_host, target_port)
request.log_error("websockify: %s:%s connected" % (target_host,target_port), apache.APLOG_INFO)
try:
do_proxy("%s:%s" % (target_host, target_port), request, target)
except:
if target:
target.shutdown(socket.SHUT_RDWR)
target.close()
raise
def do_proxy(sock_name, request, target):
buffer_size = 65536
def read_message(message):
buf = b64decode(message)
request.log_error("websockify: %s %d (%d decoded) bytes come from client" % (sock_name, len(message), len(buf)), apache.APLOG_DEBUG)
sent = 0
while (sent < len(buf)):
sent += target.send(buf[sent:])
request.log_error("websockify: %s %d of %d bytes passed to backend" % (sock_name, sent, len(buf)), apache.APLOG_DEBUG)
receiver = msgutil.MessageReceiver(request, read_message)
while True:
message = target.recv(buffer_size)
if len(message) == 0:
raise socket.error('websockify: %s backend connection closed unexpectedly' % (sock_name))
buf = b64encode(message)
request.ws_stream.send_message(buf, binary=False)
request.log_error("websockify: %s %d (%d encoded) bytes passed to client" % (sock_name, len(message), len(buf)), apache.APLOG_DEBUG)
def connect(host, port):
try:
return socket.create_connection((socket.gethostbyname(host), port))
except:
raise socket.error("websockify: can not connect to '%s:%s': %s" % (host, port, exc_info()[1]))
# vi:sts=4 sw=4 et
from websockify.
@onokonem. There are a couple of ways to post code like this. If you are wanting for changes to get back into a project, then github makes it trivial to fork the project, add the code and then issue a pull request back to the original project.
Alternately, github provides a gist mechanism for posting single files and examples: gist.github.com which you can then link.
And lastly, you can just put them in a comment with proper formatting (which you have done).
Anyways, I really like the idea of making a modpython+pywebsocket version of websockify. Your code is simple and clean and I would like to pull a version of this into websockify.
However, the I can't accept this change as is because the generic host and port mechanism poses a huge security risk. I discuss this issue here:
novnc/noVNC#49 (comment)
One common way that people have used to solve the "arbitrary target" issue is to pass a token in the query args that is used to lookup the host and port target from a limited list of options.
So the change I would suggest is that when a new connection is made, a configuration file is read that contains a mapping of tokens to host/port targets. Something like this in /etc/websockify:
default = localhost:5900
my_desktop = localhost:5900
my_media_server = joel-media:5900
my_windows_system = joel-win:5901
The websockify path would then include something like "...?target=my_desktop". In the above example, default would be the target that would be used if no "target" is specified in the query parameters. I think loading the config file on every connection would probably be the best option, that way a new target can be added without restarting the web server.
I have considered adding support for this to the standard websockify. If you do this for the mod_python/pywebsocket version then I might be motivated to make this a more standard convention for websockify.
Thanks for your work on this.
from websockify.
Hi,
yes you right about security risk.
This code is a part of some bigger work, which will include authentication and authorization. This is why I did not think about security too much.
So, conf file looks like a good solution. I'll post new code in a couple of days.
from websockify.
# websockify proxy to serve noVNC (http://kanaka.github.com/noVNC/)
# with Apache + mod_python + pywebsocket
# Inspired by websockify project (https://github.com/kanaka/websockify)
#
# Supports noVNC path feature
# but in different way than original websockify do:
# GET parameter have to be specified
# like http://your.host.dom/vnc/ws/websockify?host=hostName
#
# hostName must be defined in the vncHosts file (see below)
#
# Install
# 1) Install Apache 2.2 (http://httpd.apache.org/) with mod_python
# 2) Install pywebsocket (http://code.google.com/p/pywebsocket/)
# 3) Place websockify_wsh.py somewhere. Say, /var/www/vnc/ws/websockify_wsh.py
# 4) Configure apache:
# PythonOption mod_pywebsocket.handler_root /var/www/vnc
# PythonOption mod_pywebsocket.handler_scan /var/www/vnc/ws
# # Note: 'PythonOption mod_pywebsocket.handler_*' lines have to be placed
# # in the global Apache config scope
# # (see http://www.mailinglistarchive.com/html/[email protected]/2006-09/msg00720.html)
#
# <Location /vnc/ws>
# PythonOption websockify.vncHosts /etc/vncHosts
#
# PythonHeaderParserHandler mod_pywebsocket.headerparserhandler
# PythonDebug On
# </Location>
# 5) Create vncHosts file:
# [vncHosts] # Just to satisfy Python ConfigParser
# hostName1 = ipOrName1:portNumber1
# hostName2 = ipOrName2:portNumber2
# ...
#
# Created by Daniel Podolsky, [email protected], 22 Nov 2011
import socket
import ConfigParser
from sys import exc_info
from urlparse import parse_qs
from base64 import b64encode, b64decode
from mod_python import apache
from mod_pywebsocket import msgutil, handshake
def list_value(array, key, def_val=None):
if key in array:
return array[key]
if def_val is not None:
return def_val
raise ValueError("key '%s' is not specified" % (key))
def web_socket_do_extra_handshake(request):
try:
request.add_common_vars()
request.subprocess_env['vncHostName'] = list_value(parse_qs(request.args, False, True), 'host')[0]
config = ConfigParser.ConfigParser()
config.read(list_value(request.get_options(), 'websockify.vncHosts'))
vncHost = config.get('vncHosts', request.subprocess_env['vncHostName']).split(':', 2)
request.subprocess_env['vncHostAddr'] = vncHost[0]
request.subprocess_env['vncHostPort'] = vncHost[1]
except:
raise handshake.AbortedByUserException("websockify: connection denied: %s" % (exc_info()[1]))
request.ws_protocol = request.ws_requested_protocols[0]
request.log_error("websockify: ws_protocol = '%s' (%s)" % (request.ws_protocol, request.ws_requested_protocols), apache.APLOG_INFO)
pass # Always accept.
def web_socket_transfer_data(request):
target = connect(request.subprocess_env['vncHostAddr'], request.subprocess_env['vncHostPort'])
sockName = "%s(%s:%s)" % (request.subprocess_env['vncHostName'],
request.subprocess_env['vncHostAddr'],
request.subprocess_env['vncHostPort']
)
request.log_error("websockify: %s connected" % (sockName), apache.APLOG_NOTICE)
try:
do_proxy(sockName, request, target)
except:
if target:
target.shutdown(socket.SHUT_RDWR)
target.close()
raise
def do_proxy(sock_name, request, target):
buffer_size = 65536
def read_message(message):
buf = b64decode(message)
request.log_error("websockify: %s %d (%d decoded) bytes come from client" % (sock_name, len(message), len(buf)), apache.APLOG_DEBUG)
sent = 0
while (sent < len(buf)):
sent += target.send(buf[sent:])
request.log_error("websockify: %s %d of %d bytes passed to backend" % (sock_name, sent, len(buf)), apache.APLOG_DEBUG)
receiver = msgutil.MessageReceiver(request, read_message)
while True:
message = target.recv(buffer_size)
if len(message) == 0:
raise socket.error('websockify: %s backend connection closed unexpectedly' % (sock_name))
buf = b64encode(message)
request.ws_stream.send_message(buf, binary=False)
request.log_error("websockify: %s %d (%d encoded) bytes passed to client" % (sock_name, len(message), len(buf)), apache.APLOG_DEBUG)
def connect(host, port):
try:
return socket.create_connection((socket.gethostbyname(host), port))
except:
raise socket.error("websockify: can not connect to '%s:%s': %s" % (host, port, exc_info()[1]))
# vi:sts=4 sw=4 et
from websockify.
Where to put the javascript files, and do we need to make changes in any of those javascript files?
from websockify.
anywhere you like :) and no you do not need to modify js
from websockify.
But you have written that the
GET parameters have to be specified
like http://your.host.dom/vnc/ws/websockify?host=localhost&port=5900
or just http://your.host.dom/vnc/ws/websockify?port=5900
But the javascript provided gives GET parameter as websockify only.
I am not able to understand that where we have to tell the javascript to connect to apache server rather than the old websockify proxy server? Should I write in the connection parameter on vnc.html as apache_server_address and in port as port 80?
from websockify.
As per the apache config,
# <Location /vnc/ws> # PythonOption websockify.vncHosts /etc/vncHosts # # PythonHeaderParserHandler mod_pywebsocket.headerparserhandler # PythonDebug On # </Location>
I understand that the PythonHandler is used when the path matches /vnc/ws, but without modifying js, how can we do this?
I put javascripts and vnc.html in var/www folder. If I use apache server address as the connection parameter on vnc.html and tries to connect it gives the error,
[Wed Mar 28 11:24:08 2012] [error] [client 127.0.0.1] File does not exist: /var/www/websockify
from websockify.
Look at http://kanaka.github.com/noVNC/noVNC/vnc.html.
Under the Settings button you should see a menu with path field.
from websockify.
I gave vnc/ws/websockify in the path field and host as localhost and port 80(for my apache server) and VNC password. I places websockify_wsh.py in the directory /var/www/vnc/ws. I am getting error
[Wed Mar 28 15:03:45 2012] [info] mod_pywebsocket.headerparserhandler: Initializing Dispatcher
[Wed Mar 28 15:03:45 2012] [error] [client 127.0.0.1] File does not exist: /var/www/vnc/ws/websockify
~
Am I doing something wrong?
from websockify.
Hi,
the script works fine, but in the function "web_socket_do_extra_handshake" i had to insert an "if":
if request.ws_requested_protocols is not None:
request.ws_protocol = request.ws_requested_protocols[0]
in the documentation of pywebsockets you can read this:
For HyBi 06 and later, ws_protocol is always set to None when
web_socket_do_extra_handshake is called. If ws_requested_protocols is not
None, you must choose one subprotocol from this list and set it to
ws_protocol.
And if you use pywebsockets and this script you should play with the apache-settings, for the request-timeouts, otherwise your connection will be killed after some time. Look at the apache-Module (http://httpd.apache.org/docs/trunk/mod/mod_reqtimeout.html).
For simple tests you can use:
RequestReadTimeout header=60,MinRate=1 body=60,MinRate=1
But be careful with this!
from websockify.
Hi ,
Thanks adding that support for old websocket protocol solved my problem :)
Thanks a lot,
Rakesh Roshan
On Sat, Apr 14, 2012 at 7:47 AM, ulrichSchreiner <
[email protected]
wrote:
Hi,
the script works fine, but in the function "web_socket_do_extra_handshake"
i had to insert an "if":if request.ws_requested_protocols is not None:
request.ws_protocol = request.ws_requested_protocols[0]in the documentation of pywebsockets you can read this:
For HyBi 06 and later, ws_protocol is always set to None when
web_socket_do_extra_handshake is called. If ws_requested_protocols is not
None, you must choose one subprotocol from this list and set it to
ws_protocol.And if you use pywebsockets and this script you should play with the
apache-settings, for the request-timeouts, otherwise your connection will
be killed after some time. Look at the apache-Module (
http://httpd.apache.org/docs/trunk/mod/mod_reqtimeout.html).For simple tests you can use:
RequestReadTimeout header=60,MinRate=1 body=60,MinRate=1
But be careful with this!
Reply to this email directly or view it on GitHub:
#19 (comment)
from websockify.
I’ve more details now.
fact is, the websocket-handshake is OK and run. after the ws-handshake the noVNC Page receive the message from the pywebsockify handler, but there is no answer from the page. I guess there are two possibilities: 1. the web-page receive the b64 text "RFB 003.008\n" but can't decode it, or 2. the web-page receives and decode the VNC-Handshake but sends no answer to the ws-server/gateway.
can someone tell me, how I can check this possibilities? the rQ-message in util.js is empty, but the recv_message Data is OK. in the recv_message is the b64 encoded "RBF 003.008\n"
is it possible to turn the b64 function in this websockify_wsh handler off and use binary only?
from websockify.
ok, i've solved the problem. it was the encode/decode with b64. without the b64 coding, it works fine.
my next problem is, i want to split the server into a server an a second client. first the websockify-server should run on the apache2 with the mod_python handler but don't connect to the local port 5900. it should work as "server in the middle" and serve a websocket-connection to a second client too. the second client (pyhton) should connect to the websockify-server an bridge the traffic to the local port 5900.
can anyone help me for the second client? i want to implement it in python.
it should be like the following image
from websockify.
Related Issues (20)
- systemd script to startup
- about target-config HOT 1
- tests failed on macos
- Logging and monitor HOT 1
- How to Revoking a Certificate of VNCServer? HOT 1
- TypeError: 'str' object cannot be interpreted as an integer
- noVNC & websockify in Docker Compose on Raspberry Pi 4 using RealVNC Server HOT 1
- Installation fails HOT 1
- wss: via ssl on linux debian board HOT 1
- Readme is missing examples HOT 1
- Failed when connecting: Connection closed (code: 1005) HOT 2
- soft reload possibility HOT 1
- novnc session getting disconnected after 30 min if left idle HOT 5
- Server disconnected (code: 1015). Open developer tools (F12/Ctrl+Shift+I on Windows, Option+Command+I on Mac OS) and switch to "Console" for details HOT 1
- Exception when use JSONTokenApi as token plugin
- how to connect to tls vnc server HOT 4
- Extra parameters HOT 2
- Connection pooling HOT 1
- which option disabling directory listings HOT 1
- Websockify: Integrate xterm.js HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from websockify.