]>
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 EClose("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 EClose("Client closed")
86 raise EClose("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
, fname
106 if settings
['record']:
107 fname
= "%s.%s" % (settings
['record'],
108 settings
['handler_id'])
109 handler_msg("opening record file: %s" % fname
)
110 rec
= open(fname
, 'w+')
111 rec
.write("var VNC_frame_data = [\n")
113 handler_msg("connecting to: %s:%s" % (target_host
, target_port
))
114 tsock
= socket
.socket(socket
.AF_INET
, socket
.SOCK_STREAM
)
115 tsock
.connect((target_host
, target_port
))
117 if settings
['verbose'] and not settings
['daemon']:
121 do_proxy(client
, tsock
)
123 if tsock
: tsock
.close()
125 rec
.write("'EOF']\n")
129 if __name__
== '__main__':
130 usage
= "%prog [--record FILE]"
131 usage
+= " [source_addr:]source_port target_addr:target_port"
132 parser
= optparse
.OptionParser(usage
=usage
)
133 parser
.add_option("--verbose", "-v", action
="store_true",
134 help="verbose messages and per frame traffic")
135 parser
.add_option("--record",
136 help="record sessions to FILE.[session_number]", metavar
="FILE")
137 parser
.add_option("--foreground", "-f",
138 dest
="daemon", default
=True, action
="store_false",
139 help="stay in foreground, do not daemonize")
140 parser
.add_option("--cert", default
="self.pem",
141 help="SSL certificate file")
142 parser
.add_option("--key", default
=None,
143 help="SSL key file (if separate from cert)")
144 parser
.add_option("--ssl-only", action
="store_true",
145 help="disallow non-encrypted connections")
146 (options
, args
) = parser
.parse_args()
148 if len(args
) > 2: parser
.error("Too many arguments")
149 if len(args
) < 2: parser
.error("Too few arguments")
150 if args
[0].count(':') > 0:
151 host
,port
= args
[0].split(':')
153 host
,port
= '',args
[0]
154 if args
[1].count(':') > 0:
155 target_host
,target_port
= args
[1].split(':')
157 parser
.error("Error parsing target")
158 try: port
= int(port
)
159 except: parser
.error("Error parsing listen port")
160 try: target_port
= int(target_port
)
161 except: parser
.error("Error parsing target port")
163 if options
.ssl_only
and not os
.path
.exists(options
.cert
):
164 parser
.error("SSL only and %s not found" % options
.cert
)
165 elif not os
.path
.exists(options
.cert
):
166 print "Warning: %s not found" % options
.cert
168 settings
['verbose'] = options
.verbose
169 settings
['listen_host'] = host
170 settings
['listen_port'] = port
171 settings
['handler'] = proxy_handler
172 settings
['cert'] = os
.path
.abspath(options
.cert
)
174 settings
['key'] = os
.path
.abspath(options
.key
)
175 settings
['ssl_only'] = options
.ssl_only
176 settings
['daemon'] = options
.daemon
178 settings
['record'] = os
.path
.abspath(options
.record
)