You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 2 Next »

 

This KIP discusses the Websocket support for Apache Knox.

Status

Current state: Implemented
JIRAKNOX-752

Motivation

Websocket is a communication protocol that allows full duplex communication over single TCP connection (for more information see RFC 6455). As more and more web UIs are using websocket for communication with servers it is important that Knox supports proxying of websocket connections so that the UIs which include them can function seamlessly over Knox for e.g. Apache Zeppelin.

KNOX-752 is an initial attempt to enable websocket support for Knox as a result following requirements will be addressed in the initial release:

  • Text message support for proxying - As majority of implementations use text over binary.
  • Use of existing configuration files (topology and service definitions) to configure backend websocket url.
  • Secure websocket support from browser to Knox (wss://)

Design

The main considerations for design are:

  • Compatibility with the current configuration (service definitions, topologies)
  • Reuse of existing components and functionality

We take advantage of Jetty's websocket support (both native and JSR 356 implementations) and leverage it to support websocket connection proxying. We register our websocket handler with Jetty during startup which is then used to intercept websocket connections from the browsers (Http connection upgrade request). After the connection is established it remains open until the browser socket or the backend  service socket closes the connection or in an error event.

A pipe is created between the browser socket and the backend service socket served behind Knox. Websocket traffic can then pass through this pipe. There are hooks to inspect the traffic and enforce rewrite rules, the initial implementation does not address these. An attempt is made to relay accurate error messages and events to the browser, which can be improved and customized in future iterations.

Implementation

 

The above diagram describes, at a high level, how websocker requests are handled.

A browser initiates websocket connection by sending an HTTP connection upgrade request, Knox's websocket handler intercepts this request and returns a secure socket (wss://) to the browser - acting as a websocket server. Knox's websocket handler also establishes another connection with the backend websocker server - acting as a websocket client.

By default websocket functionality is disabled, one can enable it by changing the 'gateway.websocket.feature.enabled' property to 'true' in <KNOX-HOME>/conf/gateway-site.xml file.

	<property>
        <name>gateway.websocket.feature.enabled</name>
        <value>true</value>
        <description>Enable/Disable websocket feature.</description>
    </property>

Service and rewrite rules need to changed accordingly to match the appropriate websocket context (e.g. ws://myhost:9999/ws)

example of <KNOX-HOME>/data/services/{myservice}/{version}/rewrite.xml where myservice = websocket and version = 0.6.0

<rules>
  <rule dir="IN" name="WEBSOCKET/ws/inbound" pattern="*://*:*/**/ws">
    <rewrite template="{$serviceUrl[WEBSOCKET]}/ws"/>
  </rule>
</rules>

example of <KNOX-HOME>/data/services/{myservice}/{version}/service.xml where myservice = websocket and version = 0.6.0

<service role="WEBSOCKET" name="websocket" version="0.6.0">
  <policies>
        <policy role="webappsec"/>
        <policy role="authentication" name="Anonymous"/>
        <policy role="rewrite"/>
        <policy role="authorization"/>
  </policies>
  <routes>
    <route path="/ws">
        <rewrite apply="WEBSOCKET/ws/inbound" to="request.url"/>
    </route>
  </routes>
</service>

 

Finally, update the topology file at <KNOX-HOME>/conf/{topology}.xml  with the backend service url

	<service>
        <role>WEBSOCKET</role>
        <url>ws://myhost:9999/ws</url>
    </service>

 

 A detailed example demonstrating websocket configuration (using docker containers for simplicity) can be found here https://github.com/moresandeep/knox-dev-docker#demo-knox-dev-container–zeppelin

Future work

  • Implement binary protocol
  • Better handling of security on the dispatch side
  • Async and non blocking support
  • Extract the functionality to parse the service defination and topology files, preferably into a framework, that can be used by other similar components.
  • Handle rewrite rules, currently we simply proxy packets, this would be a bit tricky with binary payload.
  • Address scalability, 1000s of multiple concurren connections
  • No labels