Project

General

Profile

Mod wstunnel » History » Revision 11

Revision 10 (gstrauss, 2021-07-22 22:52) → Revision 11/17 (gstrauss, 2021-07-22 23:34)

h1. mod_wstunnel 

 {{>toc}} 

 *Module: mod_wstunnel* 

 (since lighttpd 1.4.46) 

 WebSocket tunnel endpoint.    This module terminates the websocket tunnel from a client.    This module then passes data (without websocket frames) to a backend and encodes responses from backend in websocket frames before sending responses to client. 

 Note: if looking to proxy websockets to a backend, then see [[Docs_ModProxy]], [[Docs_ModCGI]], or other backends, some of which can be enabled to be transparent proxies to backends after client sends @Upgrade: websocket@ 

 h2. Description 

 Brief description of [[Docs_ConfigurationOptions#mod_wstunnel|mod_wstunnel directives]] 

 table{margin-left: 2em}. 
 |_.option |_. description | 
 | wstunnel.server | backend server definition(s) for hosts to which to send requests; [[Docs_ConfigurationOptions#gw_backend-gateway-server-host-options|options]] for each backend host | 
 | wstunnel.balance | load-balancing algorithm for backends ("fair", "least-connection", "round-robin", "hash", or "sticky") | 
 | wstunnel.debug | debug level (value between 0 and 65535) | 
 | wstunnel.frame-type | websocket frame type: "text" or "binary" | 
 | wstunnel.map-extensions | map multiple extensions to the same backend | 
 | wstunnel.origins | list of permitted origins in Origin request header (optional) | 
 | wstunnel.ping-interval | send websocket PING frame at given interval in sec (default 0; none sent) | 

 Details for @wstunnel.server@ parameters can be found in [[Docs_ModFastCGI|mod_fastcgi]] documentation, since the wstunnel module shares the same code infrastructure with the FastCGI module, and fastcgi.server parameters are very similar. 

 h3. Example: websocket tunnel to VNC server via noVNC client 

 Follow instructions to download and install, or use available packages for your Linux/*BSD distribution. 
 https://github.com/novnc/noVNC 
 x11vnc 

 If noVNC files are installed in /usr/share/novnc, and x11vnc is running as VNC server with @x11vnc -localhost -forever -display :0@ then lighttpd mod_wstunnel can be configured with: 
 <pre> 
 server.document-root = "/usr/share/novnc" 
 server.indexfiles = ("index.html") 
 server.modules += ( "mod_wstunnel" ) 
 $HTTP["url"] =~ "^/websockify" { 
     wstunnel.server = ( "" => ( ( "host" => "127.0.0.1", "port" => "5900" ) ) ) 
     wstunnel.frame-type = "binary" 
     server.stream-request-body    = 2 
     server.stream-response-body = 2 
 } 
 </pre> 
 Please take proper precautions to limit access to the VNC server, possibly including requiring proper authentication and limiting access to certain source IPs. 

 h3. Example: websocket tunnel to a trivial "echo" script which reads and echoes line-by-line 

 Simple example showing lighttpd [[Docs_ModProxy|mod_proxy]] supporting websockets to another lighttpd instance using [[Docs_ModWSTunnel|mod_wstunnel]] to terminate the websocket tunnel and send/receive payloads to backend "echo" script. 
 (Using mod_proxy as an intermediate is not required at all, and the example would be simpler without it.    However, this example demonstrates WebSockets works through [[Docs_ModProxy|mod_proxy]] and through [[Docs_ModWSTunnel|mod_wstunnel]]) 

 * /dev/shm/echo.pl 
 <pre> 
 #!/usr/bin/perl -Tw 
 $SIG{PIPE} = 'IGNORE'; 
 for (my $FH; accept($FH, STDIN); close $FH) { 
     select($FH); $|=1; 
     print $FH $_ while (<$FH>); 
 } 
 </pre> 
 * /dev/shm/lighttpd-wstunnel.conf (listening on port 8081; start with @lighttpd -D -f /dev/shm/lighttpd-wstunnel.conf@; Ctrl-C to quit) 
 <pre> 
 server.document-root = "/tmp"    # not used in this example 
 server.bind = "127.0.0.1" 
 server.port = 8081 

 server.modules += ("mod_wstunnel") 
 wstunnel.server = ( 
   "/ws/" "" => ( 
     ( 
       "socket" => "/dev/shm/psock", 
       "bin-path" => "/dev/shm/echo.pl", 
       "max-procs" => 1 
     ) 
   ) 
 ) 
 </pre> 
 * /dev/shm/lighttpd-proxy.conf (listening on port 8080; start with @lighttpd -D -f /dev/shm/lighttpd-proxy.conf@ in another shell; Ctrl-C to quit) 
 <pre> 
 server.document-root = "/tmp"    # not used in this example 
 server.bind = "127.0.0.1" 
 server.port = 8080 

 server.modules += ("mod_proxy") 
 proxy.server = ( "/" => (( "host" => "127.0.0.1", "port" => "8081" ))) 
 proxy.header = ( "upgrade" => "enable" ) 
 </pre> 
 * /dev/shm/count.html (load into local browser as ///dev/shm/count.html and watch it count 1 .. 5; connects to localhost:8080) 
   (Alternatively, place in /tmp/count.html (i.e. under @server.document-root@) and load in browser as http://127.0.0.1:8080/count.html) 
 <pre> 
 <!DOCTYPE html> 
 <!-- modified from example in https://github.com/joewalnes/websocketd README.md --> 
 <pre id="log"></pre> 
 <script> 
   // helper function: log message to screen 
   var logelt = document.getElementById('log'); 
   function log(msg) { logelt.textContent += msg + '\n'; } 
   // helper function: send websocket msg with count (1 .. 5) 
   var ll = 0; 
   function send_msg() { if (++ll <= 5) { log('SEND: '+ll); ws.send(ll+'\n'); } } 
   // setup websocket with callbacks 
   var ws = new WebSocket('ws://localhost:8080/ws/'); WebSocket('ws://localhost:8080/'); 
   ws.onopen = function()           { log('CONNECT\n'); send_msg(); }; 
   ws.onclose = function()          { log('DISCONNECT'); }; 
   ws.onmessage = function(event) { log('RECV: ' + event.data); send_msg(); }; 
 </script> 
 </pre>