]>
git.proxmox.com Git - mirror_novnc.git/blob - utils/wsproxy.py
4 A WebSocket to TCP socket proxy with support for "wss://" encryption.
5 Copyright 2010 Joel Martin
6 Licensed under LGPL version 3 (see docs/LICENSE.LGPL-3)
8 You can make a cert/key with openssl using:
9 openssl req -new -x509 -days 365 -nodes -out self.pem -keyout self.pem
10 as taken from http://docs.python.org/dev/library/ssl.html#certificates
14 import socket
, optparse
, time
15 from select
import select
16 from websocket
import *
24 }. - Client receive partial
28 >. - Target send partial
30 <. - Client send partial
33 def do_proxy(client
, target
):
34 """ Proxy WebSocket to normal socket. """
39 rlist
= [client
, target
]
40 tstart
= int(time
.time()*1000)
44 tdelta
= int(time
.time()*1000) - tstart
45 if tqueue
: wlist
.append(target
)
46 if cqueue
: wlist
.append(client
)
47 ins
, outs
, excepts
= select(rlist
, wlist
, [], 1)
48 if excepts
: raise Exception("Socket exception")
52 sent
= target
.send(dat
)
56 tqueue
.insert(0, dat
[sent
:])
58 ##if rec: rec.write("Target send: %s\n" % map(ord, dat))
62 sent
= client
.send(dat
)
65 ##if rec: rec.write("Client send: %s ...\n" % repr(dat[0:80]))
66 if rec
: rec
.write("%s,\n" % repr("{%s{" % tdelta
+ dat
[1:-1]))
68 cqueue
.insert(0, dat
[sent
:])
70 ##if rec: rec.write("Client send partial: %s\n" % repr(dat[0:send]))
74 buf
= target
.recv(buffer_size
)
75 if len(buf
) == 0: raise Exception("Target closed")
77 cqueue
.append(encode(buf
))
79 ##if rec: rec.write("Target recv (%d): %s\n" % (len(buf), map(ord, buf)))
82 buf
= client
.recv(buffer_size
)
83 if len(buf
) == 0: raise Exception("Client closed")
86 raise Exception("Client sent orderly close frame")
87 elif buf
[-1] == '\xff':
88 if buf
.count('\xff') > 1:
89 traffic(str(buf
.count('\xff')))
91 ##if rec: rec.write("Client recv (%d): %s\n" % (len(buf), repr(buf)))
92 if rec
: rec
.write("%s,\n" % (repr("}%s}" % tdelta
+ buf
[1:-1])))
94 tqueue
.extend(decode(cpartial
+ buf
))
97 tqueue
.extend(decode(buf
))
100 ##if rec: rec.write("Client recv partial (%d): %s\n" % (len(buf), repr(buf)))
101 cpartial
= cpartial
+ buf
103 def proxy_handler(client
):
104 global target_host
, target_port
, options
, rec
106 if settings
['record']:
107 print "Opening record file: %s" % settings
['record']
108 rec
= open(settings
['record'], 'w+')
109 rec
.write("var VNC_frame_data = [\n")
111 print "Connecting to: %s:%s" % (target_host
, target_port
)
112 tsock
= socket
.socket(socket
.AF_INET
, socket
.SOCK_STREAM
)
113 tsock
.connect((target_host
, target_port
))
118 do_proxy(client
, tsock
)
120 if tsock
: tsock
.close()
122 rec
.write("'EOF']\n")
126 if __name__
== '__main__':
127 usage
= "%prog [--record FILE]"
128 usage
+= " [source_addr:]source_port target_addr:target_port"
129 parser
= optparse
.OptionParser(usage
=usage
)
130 parser
.add_option("--record",
131 help="record session to a file", metavar
="FILE")
132 parser
.add_option("--foreground", "-f",
133 dest
="daemon", default
=True, action
="store_false",
134 help="stay in foreground, do not daemonize")
135 parser
.add_option("--ssl-only", action
="store_true",
136 help="disallow non-encrypted connections")
137 parser
.add_option("--cert", default
="self.pem",
138 help="SSL certificate")
139 (options
, args
) = parser
.parse_args()
141 if len(args
) > 2: parser
.error("Too many arguments")
142 if len(args
) < 2: parser
.error("Too few arguments")
143 if args
[0].count(':') > 0:
144 host
,port
= args
[0].split(':')
146 host
,port
= '',args
[0]
147 if args
[1].count(':') > 0:
148 target_host
,target_port
= args
[1].split(':')
150 parser
.error("Error parsing target")
151 try: port
= int(port
)
152 except: parser
.error("Error parsing listen port")
153 try: target_port
= int(target_port
)
154 except: parser
.error("Error parsing target port")
156 if options
.ssl_only
and not os
.path
.exists(options
.cert
):
157 parser
.error("SSL only and %s not found" % options
.cert
)
159 settings
['listen_host'] = host
160 settings
['listen_port'] = port
161 settings
['handler'] = proxy_handler
162 settings
['cert'] = os
.path
.abspath(options
.cert
)
163 settings
['ssl_only'] = options
.ssl_only
164 settings
['daemon'] = options
.daemon
166 settings
['record'] = os
.path
.abspath(options
.record
)