This commit is contained in:
GitHub Merge Button 2012-05-01 15:28:46 -07:00
commit 252d9e70f0
28 changed files with 114 additions and 89 deletions

View File

@ -48,7 +48,7 @@ read binary data off of the receive queue.
The Websock API is documented on the [websock.js API wiki page](https://github.com/kanaka/websockify/wiki/websock.js) The Websock API is documented on the [websock.js API wiki page](https://github.com/kanaka/websockify/wiki/websock.js)
See the "Wrap a Program" section below for an example of using Websock See the "Wrap a Program" section below for an example of using Websock
and websockify as a browser telnet client (`wstelnet.html`). and websockify as a browser telnet client (`www/wstelnet.html`).
### Additional websockify features ### Additional websockify features
@ -107,10 +107,16 @@ port is moved to a new localhost/loopback free high port. websockify
then proxies WebSockets traffic directed to the original port to the then proxies WebSockets traffic directed to the original port to the
new (moved) port of the program. new (moved) port of the program.
You can build rebind.so like so:
cd rebind
make
cd ..
The program wrap mode is invoked by replacing the target with `--` The program wrap mode is invoked by replacing the target with `--`
followed by the program command line to wrap. followed by the program command line to wrap.
`./websockify 2023 -- PROGRAM ARGS` `bin/websockify 2023 -- PROGRAM ARGS`
The `--wrap-mode` option can be used to indicate what action to take The `--wrap-mode` option can be used to indicate what action to take
when the wrapped program exits or daemonizes. when the wrapped program exits or daemonizes.
@ -119,15 +125,15 @@ Here is an example of using websockify to wrap the vncserver command
(which backgrounds itself) for use with (which backgrounds itself) for use with
[noVNC](https://github.com/kanaka/noVNC): [noVNC](https://github.com/kanaka/noVNC):
`./websockify 5901 --wrap-mode=ignore -- vncserver -geometry 1024x768 :1` `bin/websockify 5901 --wrap-mode=ignore -- vncserver -geometry 1024x768 :1`
Here is an example of wrapping telnetd (from krb5-telnetd).telnetd Here is an example of wrapping telnetd (from krb5-telnetd).telnetd
exits after the connection closes so the wrap mode is set to respawn exits after the connection closes so the wrap mode is set to respawn
the command: the command:
`sudo ./websockify 2023 --wrap-mode=respawn -- telnetd -debug 2023` `sudo bin/websockify 2023 --wrap-mode=respawn -- telnetd -debug 2023`
The `wstelnet.html` page demonstrates a simple WebSockets based telnet The `www/wstelnet.html` page demonstrates a simple WebSockets based telnet
client. client.

90
bin/websockify Executable file
View File

@ -0,0 +1,90 @@
#!/usr/bin/env python
'''
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
'''
import optparse, os, sys
from websockify.proxy import WebSocketProxy
def websockify_init():
usage = "\n %prog [options]"
usage += " [source_addr:]source_port target_addr:target_port"
usage += "\n %prog [options]"
usage += " [source_addr:]source_port -- WRAP_COMMAND_LINE"
parser = optparse.OptionParser(usage=usage)
parser.add_option("--verbose", "-v", action="store_true",
help="verbose messages and per frame traffic")
parser.add_option("--record",
help="record sessions to FILE.[session_number]", metavar="FILE")
parser.add_option("--daemon", "-D",
dest="daemon", action="store_true",
help="become a daemon (background process)")
parser.add_option("--run-once", action="store_true",
help="handle a single WebSocket connection and exit")
parser.add_option("--timeout", type=int, default=0,
help="after TIMEOUT seconds exit when not connected")
parser.add_option("--cert", default="self.pem",
help="SSL certificate file")
parser.add_option("--key", default=None,
help="SSL key file (if separate from cert)")
parser.add_option("--rebind_path", default="./",
help="Directory containing rebind.so")
parser.add_option("--ssl-only", action="store_true",
help="disallow non-encrypted connections")
parser.add_option("--web", default=None, metavar="DIR",
help="run webserver on same port. Serve files from DIR.")
parser.add_option("--wrap-mode", default="exit", metavar="MODE",
choices=["exit", "ignore", "respawn"],
help="action to take when the wrapped program exits "
"or daemonizes: exit (default), ignore, respawn")
(opts, args) = parser.parse_args()
# Sanity checks
if len(args) < 2:
parser.error("Too few arguments")
if sys.argv.count('--'):
opts.wrap_cmd = args[1:]
else:
opts.wrap_cmd = None
if len(args) > 2:
parser.error("Too many arguments")
if opts.ssl_only and not os.path.exists(opts.cert):
parser.error("SSL only and %s not found" % opts.cert)
# Parse host:port and convert ports to numbers
if args[0].count(':') > 0:
opts.listen_host, opts.listen_port = args[0].rsplit(':', 1)
else:
opts.listen_host, opts.listen_port = '', args[0]
try: opts.listen_port = int(opts.listen_port)
except: parser.error("Error parsing listen port")
if opts.wrap_cmd:
opts.target_host = None
opts.target_port = None
else:
if args[1].count(':') > 0:
opts.target_host, opts.target_port = args[1].rsplit(':', 1)
else:
parser.error("Error parsing target")
try: opts.target_port = int(opts.target_port)
except: parser.error("Error parsing target port")
# Create and start the WebSockets proxy
server = WebSocketProxy(**opts.__dict__)
server.start_server()
if __name__ == '__main__':
websockify_init()

View File

@ -22,9 +22,5 @@ setup(name=name,
include_package_data=True, include_package_data=True,
install_requires=['numpy'], install_requires=['numpy'],
zip_safe=False, zip_safe=False,
entry_points={ scripts=['bin/websockify'],
'console_scripts': [
'websockify = websockify:websockify_init',
]
},
) )

View File

@ -12,7 +12,7 @@ as taken from http://docs.python.org/dev/library/ssl.html#certificates
import os, sys, select, optparse import os, sys, select, optparse
sys.path.insert(0,os.path.dirname(__file__) + "/../") sys.path.insert(0,os.path.dirname(__file__) + "/../")
from websocket import WebSocketServer from websockify.websocket import WebSocketServer
class WebSocketEcho(WebSocketServer): class WebSocketEcho(WebSocketServer):
""" """

View File

@ -1 +1 @@
../include ../www/include

View File

@ -8,7 +8,7 @@ given a sequence number. Any errors are reported and counted.
import sys, os, select, random, time, optparse import sys, os, select, random, time, optparse
sys.path.insert(0,os.path.dirname(__file__) + "/../") sys.path.insert(0,os.path.dirname(__file__) + "/../")
from websocket import WebSocketServer from websockify.websocket import WebSocketServer
class WebSocketLoad(WebSocketServer): class WebSocketLoad(WebSocketServer):

View File

@ -7,7 +7,7 @@ import sys, os, socket, ssl, time, traceback
from select import select from select import select
sys.path.insert(0,os.path.dirname(__file__) + "/../") sys.path.insert(0,os.path.dirname(__file__) + "/../")
from websocket import WebSocketServer from websockify.websocket import WebSocketServer
if __name__ == '__main__': if __name__ == '__main__':
print "val: hixie | hybi_base64 | hybi_binary" print "val: hixie | hybi_base64 | hybi_binary"

View File

@ -1 +0,0 @@
websockify

0
websockify/__init__.py Normal file
View File

82
websockify → websockify/proxy.py Executable file → Normal file
View File

@ -43,15 +43,20 @@ Traffic Legend:
self.target_port = kwargs.pop('target_port') self.target_port = kwargs.pop('target_port')
self.wrap_cmd = kwargs.pop('wrap_cmd') self.wrap_cmd = kwargs.pop('wrap_cmd')
self.wrap_mode = kwargs.pop('wrap_mode') self.wrap_mode = kwargs.pop('wrap_mode')
self.rebind_path = kwargs.pop('rebind_path')
# Last 3 timestamps command was run # Last 3 timestamps command was run
self.wrap_times = [0, 0, 0] self.wrap_times = [0, 0, 0]
if self.wrap_cmd: if self.wrap_cmd:
rebinder_path = ['./', os.path.dirname(sys.argv[0])] rebinder_path = [self.rebind_path,
self.rebind_path + '/rebind.so',
'./rebind.so',
os.path.dirname(sys.argv[0]) + 'rebind.so',
'rebind/rebind.so',
'../rebind/rebind.so']
self.rebinder = None self.rebinder = None
for rdir in rebinder_path: for rpath in rebinder_path:
rpath = os.path.join(rdir, "rebind.so")
if os.path.exists(rpath): if os.path.exists(rpath):
self.rebinder = rpath self.rebinder = rpath
break break
@ -212,74 +217,3 @@ Traffic Legend:
if closed: if closed:
# TODO: What about blocking on client socket? # TODO: What about blocking on client socket?
raise self.CClose(closed['code'], closed['reason']) raise self.CClose(closed['code'], closed['reason'])
def websockify_init():
usage = "\n %prog [options]"
usage += " [source_addr:]source_port target_addr:target_port"
usage += "\n %prog [options]"
usage += " [source_addr:]source_port -- WRAP_COMMAND_LINE"
parser = optparse.OptionParser(usage=usage)
parser.add_option("--verbose", "-v", action="store_true",
help="verbose messages and per frame traffic")
parser.add_option("--record",
help="record sessions to FILE.[session_number]", metavar="FILE")
parser.add_option("--daemon", "-D",
dest="daemon", action="store_true",
help="become a daemon (background process)")
parser.add_option("--run-once", action="store_true",
help="handle a single WebSocket connection and exit")
parser.add_option("--timeout", type=int, default=0,
help="after TIMEOUT seconds exit when not connected")
parser.add_option("--cert", default="self.pem",
help="SSL certificate file")
parser.add_option("--key", default=None,
help="SSL key file (if separate from cert)")
parser.add_option("--ssl-only", action="store_true",
help="disallow non-encrypted connections")
parser.add_option("--web", default=None, metavar="DIR",
help="run webserver on same port. Serve files from DIR.")
parser.add_option("--wrap-mode", default="exit", metavar="MODE",
choices=["exit", "ignore", "respawn"],
help="action to take when the wrapped program exits "
"or daemonizes: exit (default), ignore, respawn")
(opts, args) = parser.parse_args()
# Sanity checks
if len(args) < 2:
parser.error("Too few arguments")
if sys.argv.count('--'):
opts.wrap_cmd = args[1:]
else:
opts.wrap_cmd = None
if len(args) > 2:
parser.error("Too many arguments")
if opts.ssl_only and not os.path.exists(opts.cert):
parser.error("SSL only and %s not found" % opts.cert)
# Parse host:port and convert ports to numbers
if args[0].count(':') > 0:
opts.listen_host, opts.listen_port = args[0].rsplit(':', 1)
else:
opts.listen_host, opts.listen_port = '', args[0]
try: opts.listen_port = int(opts.listen_port)
except: parser.error("Error parsing listen port")
if opts.wrap_cmd:
opts.target_host = None
opts.target_port = None
else:
if args[1].count(':') > 0:
opts.target_host, opts.target_port = args[1].rsplit(':', 1)
else:
parser.error("Error parsing target")
try: opts.target_port = int(opts.target_port)
except: parser.error("Error parsing target port")
# Create and start the WebSockets proxy
server = WebSocketProxy(**opts.__dict__)
server.start_server()
if __name__ == '__main__':
websockify_init()