Add traffic plugins
This commit is contained in:
parent
a1346552fb
commit
20b8c798c1
|
|
@ -110,6 +110,10 @@ These are not necessary for the basic operation.
|
||||||
options, where CLASS is usually one from token_plugins.py and ARG is
|
options, where CLASS is usually one from token_plugins.py and ARG is
|
||||||
the plugin's configuration.
|
the plugin's configuration.
|
||||||
|
|
||||||
|
* Traffic plugins: an instance per connection to intercept and modify traffic
|
||||||
|
This functionality is activated with the `--traffic-plugin CLASS`, where
|
||||||
|
CLASS is an implementation of the traffic_plugin BasePlugin.
|
||||||
|
|
||||||
### Other implementations of websockify
|
### Other implementations of websockify
|
||||||
|
|
||||||
The primary implementation of websockify is in python. There are
|
The primary implementation of websockify is in python. There are
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,7 @@ class JSONTokenApi(BaseTokenAPI):
|
||||||
|
|
||||||
def process_result(self, resp):
|
def process_result(self, resp):
|
||||||
resp_json = resp.json()
|
resp_json = resp.json()
|
||||||
return (resp_json['host'], resp_json['port'])
|
return (resp_json['host'], resp_json['port'], resp_json)
|
||||||
|
|
||||||
|
|
||||||
class JWTTokenApi(BasePlugin):
|
class JWTTokenApi(BasePlugin):
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
class BasePlugin():
|
||||||
|
def __init__(self, handler, tsock):
|
||||||
|
self.handler = handler
|
||||||
|
self.tsock = tsock
|
||||||
|
def from_client(self, s):
|
||||||
|
return s
|
||||||
|
def from_target(self, s):
|
||||||
|
return s
|
||||||
|
|
@ -48,13 +48,15 @@ Traffic Legend:
|
||||||
if not self.server.token_plugin:
|
if not self.server.token_plugin:
|
||||||
return
|
return
|
||||||
|
|
||||||
host, port = self.get_target(self.server.token_plugin)
|
host, port, *rest = self.get_target(self.server.token_plugin)
|
||||||
if host == 'unix_socket':
|
if host == 'unix_socket':
|
||||||
self.server.unix_target = port
|
self.server.unix_target = port
|
||||||
|
|
||||||
else:
|
else:
|
||||||
self.server.target_host = host
|
self.server.target_host = host
|
||||||
self.server.target_port = port
|
self.server.target_port = port
|
||||||
|
if len(rest) > 0: # rest is an array of all remaining parts
|
||||||
|
self.target_attribtues = rest[0]
|
||||||
|
|
||||||
def auth_connection(self):
|
def auth_connection(self):
|
||||||
if not self.server.auth_plugin:
|
if not self.server.auth_plugin:
|
||||||
|
|
@ -122,6 +124,8 @@ Traffic Legend:
|
||||||
|
|
||||||
# Start proxying
|
# Start proxying
|
||||||
try:
|
try:
|
||||||
|
if self.traffic_plugin: # replace class with instance
|
||||||
|
self.traffic_plugin = self.traffic_plugin(self, tsock)
|
||||||
self.do_proxy(tsock)
|
self.do_proxy(tsock)
|
||||||
finally:
|
finally:
|
||||||
if tsock:
|
if tsock:
|
||||||
|
|
@ -246,6 +250,9 @@ Traffic Legend:
|
||||||
if target in outs:
|
if target in outs:
|
||||||
# Send queued client data to the target
|
# Send queued client data to the target
|
||||||
dat = tqueue.pop(0)
|
dat = tqueue.pop(0)
|
||||||
|
if self.traffic_plugin:
|
||||||
|
dat = self.traffic_plugin.from_client(dat)
|
||||||
|
if not dat: continue
|
||||||
sent = target.send(dat)
|
sent = target.send(dat)
|
||||||
if sent == len(dat):
|
if sent == len(dat):
|
||||||
self.print_traffic(">")
|
self.print_traffic(">")
|
||||||
|
|
@ -258,6 +265,9 @@ Traffic Legend:
|
||||||
if target in ins:
|
if target in ins:
|
||||||
# Receive target data, encode it and queue for client
|
# Receive target data, encode it and queue for client
|
||||||
buf = target.recv(self.buffer_size)
|
buf = target.recv(self.buffer_size)
|
||||||
|
if self.traffic_plugin:
|
||||||
|
buf = self.traffic_plugin.from_target(buf)
|
||||||
|
if not buf: continue
|
||||||
if len(buf) == 0:
|
if len(buf) == 0:
|
||||||
|
|
||||||
# Target socket closed, flushing queues and closing client-side websocket
|
# Target socket closed, flushing queues and closing client-side websocket
|
||||||
|
|
@ -298,6 +308,7 @@ class WebSocketProxy(websockifyserver.WebSockifyServer):
|
||||||
self.token_plugin = kwargs.pop('token_plugin', None)
|
self.token_plugin = kwargs.pop('token_plugin', None)
|
||||||
self.host_token = kwargs.pop('host_token', None)
|
self.host_token = kwargs.pop('host_token', None)
|
||||||
self.auth_plugin = kwargs.pop('auth_plugin', None)
|
self.auth_plugin = kwargs.pop('auth_plugin', None)
|
||||||
|
self.traffic_plugin = kwargs.pop('traffic_plugin', None)
|
||||||
|
|
||||||
# Last 3 timestamps command was run
|
# Last 3 timestamps command was run
|
||||||
self.wrap_times = [0, 0, 0]
|
self.wrap_times = [0, 0, 0]
|
||||||
|
|
@ -537,6 +548,9 @@ def websockify_init():
|
||||||
parser.add_option("--auth-plugin", default=None, metavar="CLASS",
|
parser.add_option("--auth-plugin", default=None, metavar="CLASS",
|
||||||
help="use a Python class, usually one from websockify.auth_plugins, "
|
help="use a Python class, usually one from websockify.auth_plugins, "
|
||||||
"such as BasicHTTPAuth, to determine if a connection is allowed")
|
"such as BasicHTTPAuth, to determine if a connection is allowed")
|
||||||
|
parser.add_option("--traffic-plugin", default=None, metavar="CLASS",
|
||||||
|
help="use a Python class, usually one from websockify.traffic_plugins, "
|
||||||
|
"to modify the traffic")
|
||||||
parser.add_option("--auth-source", default=None, metavar="ARG",
|
parser.add_option("--auth-source", default=None, metavar="ARG",
|
||||||
help="an argument to be passed to the auth plugin "
|
help="an argument to be passed to the auth plugin "
|
||||||
"on instantiation")
|
"on instantiation")
|
||||||
|
|
@ -732,6 +746,17 @@ def websockify_init():
|
||||||
|
|
||||||
del opts.auth_source
|
del opts.auth_source
|
||||||
|
|
||||||
|
if opts.traffic_plugin is not None:
|
||||||
|
if '.' not in opts.traffic_plugin:
|
||||||
|
opts.traffic_plugin = 'websockify.traffic_plugins.%s' % opts.traffic_plugin
|
||||||
|
|
||||||
|
traffic_plugin_module, traffic_plugin_cls = opts.traffic_plugin.rsplit('.', 1)
|
||||||
|
|
||||||
|
__import__(traffic_plugin_module)
|
||||||
|
traffic_plugin_cls = getattr(sys.modules[traffic_plugin_module], traffic_plugin_cls)
|
||||||
|
|
||||||
|
opts.traffic_plugin = traffic_plugin_cls
|
||||||
|
|
||||||
# Create and start the WebSockets proxy
|
# Create and start the WebSockets proxy
|
||||||
libserver = opts.libserver
|
libserver = opts.libserver
|
||||||
del opts.libserver
|
del opts.libserver
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,7 @@ class WebSockifyRequestHandler(WebSocketRequestHandlerMixIn, SimpleHTTPRequestHa
|
||||||
if self.logger is None:
|
if self.logger is None:
|
||||||
self.logger = WebSockifyServer.get_logger()
|
self.logger = WebSockifyServer.get_logger()
|
||||||
|
|
||||||
|
self.traffic_plugin = getattr(server, "traffic_plugin", None)
|
||||||
super().__init__(req, addr, server)
|
super().__init__(req, addr, server)
|
||||||
|
|
||||||
def log_message(self, format, *args):
|
def log_message(self, format, *args):
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue