Skip to content

Token based target selection

Pierre Ossman (Work account) edited this page Feb 19, 2018 · 3 revisions

Token based target selection

Allowing websockify connections to select arbitrary host and port targets is a large security issue and will not be supported by websockify. However, it is possible to configure websockify to connect to different hosts and ports based on an opaque token provided by the client. How the token is interpreted is controlled by a TokenPlugin. Several plugins are included (the most commonly used one is detailed below), and it is also possible to create custom plugins.

TokenFile Plugin

This plugin allows you to pass in a file or set of files containing pairings of tokens with host:port information.

Example

The token based target configuration in websockify can be activated like this:

$ ./run ... --token-plugin TokenFile --token-source /path/to/target.config.d/

In this case target.config.d is a directory containing configuration files. Each configuration file contains one or more lines like this:

token1: host1:port1

Now consider a new connection to websockify with the following request line:

GET /path?token=token1
...

Given the above config file and request line, websockify will attempt to connect to the target host:port1.

Other notes

  • The --token-source option can refer to a single file, in which case only that file is used for the configuration.
  • The TokenFile plugin scans and reads the configuration file(s) for every new connection. Alternately you can use the ReadOnlyTokenFile plugin which will only read the configuration once for the first new connection. Using the TokenFile plugin allows the administrator to dynamically add and remove configuration for websockify. One common pattern is to use a file per token/target pair which allows removal of that target without the need to parse a config file containing multiple token/targets.
  • If you are using websockify with noVNC, the token may be passed as part of the "path" query parameter.

Custom Plugins

Custom plugins should match the format of the BasePlugin class found in websockify/token_plugins.py. Namely, they should implement an __init__(self, src) method (where src is the value of --token-source), and a lookup(self, token) method which either returns a (host, port) tuple, or None.

The plugin can be placed in any module that's importable by websockify, and then be used as such:

$ ./run ... --token-plugin some.module.TokenClass --token-source 'some information here'

Example

This custom plugin (originally provided by @Ziris85) loads JSON from a memcached server in order to resolve the token.

import memcache
import simplejson

class TokenMemc(object):
    def __init__(self, src):
        self._server = src

    def lookup(self, token):
        client = memcache.Client([self._server], debug=0)
        stuff = client.get(token)
        combo = simplejson.loads(stuff)
        pair = combo["host"]
        return pair.split(':')