• Stars
    star
    220
  • Rank 180,422 (Top 4 %)
  • Language
    Go
  • License
    MIT License
  • Created almost 11 years ago
  • Updated about 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Web-sockets tunnel for HTTP requests: facilitates requests to an HTTP server sitting behind a firewall

WStunnel - Web Sockets Tunnel

  • Master: Build Status Coverage
  • 1.0.7: Build Status Coverage

WStunnel creates an HTTPS tunnel that can connect servers sitting behind an HTTP proxy and firewall to clients on the internet. It differs from many other projects by handling many concurrent tunnels allowing a central client (or set of clients) to make requests to many servers sitting behind firewalls. Each client/server pair are joined through a rendez-vous token.

At the application level the situation is as follows, an HTTP client wants to make request to an HTTP server behind a firewall and the ingress is blocked by a firewall:

  HTTP-client ===> ||firewall|| ===> HTTP-server

The WStunnel app implements a tunnel through the firewall. The assumption is that the WStunnel client app running on the HTTP-server box can make outbound HTTPS requests. In the end there are 4 components running on 3 servers involved:

  • the http-client application on a client box initiates HTTP requests
  • the http-server application on a server box behind a firewall handles the HTTP requests
  • the WStunnel server application on a 3rd box near the http-client intercepts the http-client's requests in order to tunnel them through (it acts as a surrogate "server" to the http-client)
  • the WStunnel client application on the server box hands the http requests to the local http-server app (it acts as a "client" to the http-server) The result looks something like this:
HTTP-client ==>\                      /===> HTTP-server
                |                      |
                \----------------------/
            WStunsrv <===tunnel==== WStuncli

But this is not the full picture. Many WStunnel clients can connect to the same server and many http-clients can make requests. The rendez-vous between these is made using secret tokens that are registered by the WStunnel client. The steps are as follows:

  • WStunnel client is initialized with a token, which typically is a sizeable random string, and the hostname of the WStunnel server to connect to
  • WStunnel client connects to the WStunnel server using WSS or HTTPS and verifies the hostname-certificate match
  • WStunnel client announces its token to the WStunnel server
  • HTTP-client makes an HTTP request to WStunnel server with a std URI and a header containing the secret token
  • WStunnel server forwards the request through the tunnel to WStunnel client
  • WStunnel client receives the request and issues the request to the local server
  • WStunnel client receives the HTTP response and forwards that back through the tunnel, where WStunnel server receives it and hands it back to HTTP-client on the still-open original HTTP request

In addition to the above functionality, wstunnel does some queuing in order to handle situations where the tunnel is momentarily not open. However, during such queing any HTTP connections to the HTTP-server/client remain open, i.e., they are not made aware of the queueing happening.

The implementation of the actual tunnel is intended to support two methods (but only the first is currently implemented).
The preferred high performance method is websockets: the WStunnel client opens a secure websockets connection to WStunnel server using the HTTP CONNECT proxy traversal connection upgrade if necessary and the two ends use this connection as a persistent bi-directional tunnel.
The second (Not yet implemented!) lower performance method is to use HTTPS long-poll where the WStunnel client makes requests to the server to shuffle data back and forth in the request and response bodies of these requests.

Getting Started

You will want to have 3 machines handy (although you could run everything on one machine to try it out):

  • www.example.com will be behind a firewall running a simple web site on port 80
  • wstun.example.com will be outside the firewall running the tunnel server
  • client.example.com will be outside the firewall wanting to make HTTP requests to www.example.com through the tunnel

Download

Release branches are named '1.N.M' and a '1.N' package is created with each revision as a form of 'latest'. Download the latest Linux binary and extract the binary. To compile for OS-X or Linux ARM clone the github repo and run make depend; make (this is not tested).

Set-up tunnel server

On wstun.example.com start WStunnel server (I'll pick a port other than 80 for sake of example)

$ ./wstunnel srv -port 8080 &
2014/01/19 09:51:31 Listening on port 8080
$ curl http://localhost:8080/_health_check
WSTUNSRV RUNNING
$

Start tunnel

On www.example.com verify that you can access the local web site:

$ curl http://localhost/some/web/page
<html> .......

Now set-up the tunnel:

$ ./wstunnel cli -tunnel ws://wstun.example.com:8080 -server http://localhost -token 'my_b!g_$secret!!'
2014/01/19 09:54:51 Opening ws://wstun.example.com/_tunnel

Make a request through the tunnel

On client.example.com use curl to make a request to the web server running on www.example.com:

$ curl 'https://wstun.example.com:8080/_token/my_b!g_$secret!!/some/web/page'
<html> .......
$ curl '-HX-Token:my_b!g_$secret!!' https://wstun.example.com:8080/some/web/page
<html> .......

Targeting multiple web servers

The above example tells WStunnel client to only forward requests to http://localhost. It is possible to allow the wstunnel to target multiple hosts too. For this purpose the original HTTP client must pass an X-Host header to name the host and WStunnel client must be configured with a regexp that limits the destination web server hostnames it allows. For example, to allow access to *.some.example.com over https use:

  • wstunnel cli -regexp 'https://.*\.some\.example\.com' -server https://default.some.example.com ...
  • curl '-HX-Host: https://www.some.example.com'

Or to allow access to www.example.com and blog.example.com over http you might use:

  • wstunnel cli -regexp 'http://(www\.example\.com|blog\.example\.com)' -server http://www.example.com ...
  • curl '-HX-Host: http://blog.example.com'

Note the use of -server and -regexp, this is because the server named in -server is used when there is no X-Host header. The host in the -server option does not have to match the regexp but it is recommended for it match.

Using a Proxy

WStunnel client may use a proxy as long as that proxy supports HTTPS CONNECT. Basic authentication may be used if the username and password are embedded in the url. For example, -proxy http://myuser:[email protected]:3128. In addition, the command line client will also respect the https_proxy/http_proxy environment variables if they're set. As websocket connections are very long lived, please set read timeouts on your proxy as high as possible.

Using Secure Web Sockets (SSL)

WStunnel does not support SSL natively (although that would not be a big change). The recommended approach for using WSS (web sockets through SSL) is to use nginx, which uses the well-hardened openssl library, whereas WStunnel would be using the non-hardened Go SSL implementation. In order to connect to a secure tunnel server from WStunnel client use the wss URL scheme, e.g. wss://wstun.example.com. Here is a sample nginx configuration:

server {
  listen       443;
  server_name  wstunnel.test.rightscale.com;

  ssl_certificate        <path to crt>;
  ssl_certificate_key    <path to key>;

  # needed for HTTPS
  proxy_set_header X-Forwarded-Proto https;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header Host $http_host;
  proxy_set_header X-Forwarded-Host $host;
  proxy_redirect off;
  proxy_max_temp_file_size 0;

  #configure ssl
  ssl on;
  ssl_protocols SSLv3 TLSv1;
  ssl_ciphers HIGH:!ADH;
  ssl_prefer_server_ciphers on; # don't trust the client
  # caches 10 MB of SSL sessions in memory, faster than OpenSSL's cache:
  ssl_session_cache shared:SSL:10m;
  # cache the SSL sessions for 5 minutes, just as long as today's browsers
  ssl_session_timeout 5m;

  location / {
    root /mnt/nginx;

    proxy_redirect     off;
    proxy_http_version 1.1;

    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";
    proxy_set_header Host $http_host;
    proxy_set_header X-Forwarded-For    $proxy_add_x_forwarded_for;
    proxy_buffering off;

    proxy_pass http://127.0.0.1:8080;   # assume wstunsrv runs on port 8080
  }
}

Reading wstunnel server logs

Sample:

Apr  4 17:40:29 srv1 wstunsrv[7808]: INFO HTTP RCV      pkg=WStunsrv token=tech_x... id=19 verb=GET url=/ addr="10.210.2.11, 53.5.22.247" x-host= try=
Apr  4 17:40:29 srv1 wstunsrv[7808]: INFO WS   SND      pkg=WStunsrv token=tech_x... id=19 info="GET /"
Apr  4 17:40:29 srv1 wstunsrv[7808]: INFO WS   RCV      token=tech_x... id=19 ws=0xc20a416d20 len=393
Apr  4 17:40:29 srv1 wstunsrv[7808]: INFO HTTP RET      pkg=WStunsrv token=tech_x... id=19 status=401

The first line says that wstunsrv received an HTTP request to be tunneled and assigned it id 19. The second line says that wstunsrv sent the request onto the appropriate websocket ("WS") to wstuncli. The third line says that it has received a response to request 19 over the websocket. The fourth line says that wstunsrv sent an HTTP response back to request 19, and that the status is a 401. What may not be obvious is that because it went round-trip to wstuncli the status code comes from wstuncli.

Release instructions

  • Run the following bash commands.
make depend
git tag -a $VERSION
git push --tags
  • Create a branch for the changelog.
  • Create the changelog:
git-chglog -o CHANGELOG.md
git add CHANGELOG.md
  • Update Readme to reflect new $VERSION.
  • Commit and push README and CHANGLOG Changes.

More Repositories

1

right_aws

RightScale Amazon Web Services Ruby Gems
Ruby
451
star
2

cookbooks_public

Ruby
78
star
3

rightscale_cookbooks

Ruby
76
star
4

right_link

RightLink: server agent for RightScale
Ruby
54
star
5

scheduled_job

A thin flexible interface that enables you to define recurring jobs using DelayedJob
Ruby
44
star
6

cookbooks_public_windows

RightScale cookbooks used on Windows
Ruby
40
star
7

policy_templates

Flexera CMP built-in Policy Templates to provide effortless governance via automation.
Ruby
40
star
8

right_http_connection

Ruby
31
star
9

right_api_client

Ruby
30
star
10

rsc

Generic RightScale API client Go package and command line tool
Go
27
star
11

behaveJS

Ruby
16
star
12

right_popen

Asynchronous multiplatform popen implementation relying on EventMachine
Ruby
16
star
13

rightimage

Ruby
15
star
14

persist

Simple persistence or replay log for golang
Go
13
star
15

flexera-plugins

Library of open source Flexera plugins
Ruby
13
star
16

right_aws_api

Ruby gem to access many AWS services
Ruby
11
star
17

cookbooks_opensource

Ruby
11
star
18

right_st

RightScale ServerTemplate and RightScript tool
Go
11
star
19

cmdb

Command-line tool for configuration management databases
Ruby
10
star
20

right_scraper

Download and incrementally update git, SVN and tar repositories
Ruby
9
star
21

design-kit

A branding guide for RightScale products
JavaScript
8
star
22

right_chimp

The chimp automation tool, created for RightScale operations
Ruby
7
star
23

go_middleware

A set of common Go web application middleware
Go
7
star
24

go-boilerplate

Starting point for a Golang project
Go
7
star
25

sql_partitioner

Ruby
6
star
26

right_agent

Fundation code for RightNet agents
Ruby
6
star
27

rs-premium_free_trial

Ruby
6
star
28

right_api_cmd

CLI app for RightScale RightAPI 1.5 & 1.6 with capability to extract response fields.
Go
5
star
29

mock_em

Gem to mock EventMachine for testing
Ruby
5
star
30

process_watcher

Cross platform process watching solution
Ruby
5
star
31

right_amqp

RightScale AMQP client rubygem
Ruby
5
star
32

cbi-oi-kubecost-exporter

Go
5
star
33

rsssh

RightScale Secure Shell
Rust
4
star
34

rightlink_scripts

RightScripts for RightScale's RightLink10 (aka RightLinkLite) agent
Shell
4
star
35

sca-codeinsight-reports-project-vulnerabilities

Code Insight report showing project vulnerabilities
Python
4
star
36

collectd-container

Run collectd in a container to monitor the host, support CoreOS
Shell
4
star
37

terraform-provider-rightscale

[ Archived ] A Terraform provider that leverages the RightScale platform - Moved here: https://github.com/terraform-providers/terraform-provider-rightscale
Go
4
star
38

examples

3
star
39

sca-codeinsight-utilities-inventory-search

Code Insight v7 Inventory Keyword Search Script
Python
3
star
40

sca-codeinsight-reports-claim-files

Report to allow users to show files they can claim based on evidience
Python
3
star
41

aws-control-tower

Flexera Optima Integration with AWS Control Tower
Ruby
2
star
42

public_resources

Set of cross-product code samples, snippets and other helpful resources.
Ruby
2
star
43

ldap-group-sync

Script used to synchronize groups between LDAP and RightScale Governance
PowerShell
2
star
44

bulk-rightlink10-enablement

Install RightLink 10 on a group of servers. Uses ssh keys or a password to access servers.
Shell
2
star
45

sca-codeinsight-restapi-example

Example script utilizing the Code Insight REST API interface
Python
2
star
46

sca-codeinsight-reports-cyclonedx

Python
2
star
47

rackspace_cookbooks

Python
2
star
48

sca-codeinsight-reports-third-party-notices

The sca-codeinsight-reports-third-party-notices repository is a report for Revenera's Code Insight product. This report allows a user to generate a Third Party Notices report to satisfy the attribution requirement of open source licenses. This report will automatically include licenses with attribution data where available.
Python
2
star
49

sca-codeinsight-reports-spdx

Code Insight SPDX report
Python
2
star
50

gojiutil

Helpers for the golang goji web framework
Go
2
star
51

cassandra

Ruby
2
star
52

croner

A simple cron implementation with an HTTP status interface
Go
2
star
53

equinix-public

Ruby
2
star
54

policy_sdk

Go
2
star
55

right_develop

Developer tools
Ruby
1
star
56

ui-charts

TypeScript
1
star
57

sca-codeinsight-reports-project-inventory-license-audit

Report to flag when restricted license are modified for an inventory item
Python
1
star
58

libnss-rightscale

Unix Name Service Switch (NSS) module that pulls passwd/shadow information from RightLink system management agent.
C
1
star
59

cbi-oi-mongodb-atlas

MongoDB Atlas CBI Upload
Ruby
1
star
60

RightGridWindowsImplementation

This is a purely c# implementation of the rightgrid features. This is for windows users and in .net 4.0
C#
1
star
61

sca-codeinsight-reports-project-sbom

Python
1
star
62

netflix-tools

1
star
63

aws-xray-daemon

Dockerfile for the AWS X-Ray daemon.
1
star
64

self-service-assets

CMP Self Service Assets
Ruby
1
star
65

aad_oauth

Command line tool that generates Oauth tokens from Azure Active Directory
Go
1
star
66

rightscale-docs

New github org, same rightscale Docs
Slim
1
star
67

scfld-rs-app

JavaScript
1
star
68

rightscale_upload

Ruby
1
star
69

self-service-plugins

Self-service namespaces
Ruby
1
star
70

mysql

Version 2.8.2 of mysql gem
C
1
star
71

sca-codeinsight-workflow-v6

Script that allows users to correlate inventory items in Code Insight v7 with requests in Code Insight v6
Python
1
star
72

sca-codeinsight-reports-project-vulnerability-exclusions

An Code Insight report to display the vulnerabilities that were excluded for each inventory as well as the reason why it was excluded
Python
1
star
73

sca-codeinsight-restapi-python

A common repo containing python based RESTAPI calls for Code Insight
Python
1
star