Giter Club home page Giter Club logo

wstunnel's Introduction

wstunnel

Establish a TCP socket tunnel over web socket connection, for circumventing strict firewalls.

Installation

npm install -g wstunnel

Usage

Run the websocket tunnel server at port 8080 on all interfaces:

wstunnel -s 0.0.0.0:8080

Run the websocket tunnel client:

wstunnel -t 33:2.2.2.2:33 ws://host:8080

In the above example, client picks the final tunnel destination, similar to ssh tunnel. Alternatively for security reason, you can lock tunnel destination on the server end, example:

Server:
    wstunnel -s 0.0.0.0:8080 -t 2.2.2.2:33

Client:
    wstunnel -t 33 ws://server:8080

In both examples, connection to localhost:33 on client will be tunneled to 2.2.2.2:33 on server via websocket connection in between.

To tell client to connect via http proxy, do:

wstunnel -t 33:2.2.2.2:33 -p http://[user:pass@]proxyhost:proxyport wss://server:443

For dev/test purpose, client can set '-c' option to disable ssl certificate check.

This also makes you vulnerable to MITM attack, so use with caution.

To get help, just run

wstunnel

Docker

A public docker image "mhzed/wstunnel" is now available.

Example:

# run as client to connect to wss://server.com, tunnel localhost:2244 to target.ip:22
docker run --rm -d -p 2244:2244 mhzed/wstunnel -t 0.0.0.0:2244:target.ip:22 wss://server.com

Notice "-t 0.0.0.0:2244..." above. By default wstunnel binds to localhost which is unreachable inside a docker container, so make sure to specify "0.0.0.0" to bind to all local IPs.

Use cases

For tunneling over strict firewalls: WebSocket is a part of the HTML5 standard, any reasonable firewall will unlikely be so strict as to break HTML5.

SSL setup

Currently wstunnel in server mode supports plain tcp socket only. For SSL support (highly recommended), setup a NGINX reverse proxy.

On server, wstunnel listens on localhost:8080:

wstunnel -s 8080

On server, run NGINX (>=1.3.13) with sample configuration:

server {
    listen   443;
    server_name  mydomain.com;

    ssl  on;
    ssl_certificate  /path/to/my.crt
    ssl_certificate_key  /path/to/my.key
    ssl_session_timeout  5m;
    ssl_protocols  SSLv2 SSLv3 TLSv1;
    ssl_ciphers  ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
    ssl_prefer_server_ciphers   on;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header        Host            $host;
        proxy_set_header        X-Real-IP       $remote_addr;
        proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header        X-Forwarded-Proto $scheme;
    }
}

Then on client:

wstunnel -t 99:targethost:targetport wss://mydomain.com

SSH Proxy

To use as a proxy for "ssh", run:

ssh -o ProxyCommand="wstunnel -t stdio:%h:%p https://server" user@sshDestination

Above command will ssh to "user@sshDestination" via wstunnel server at "https://server".

RDP use case

Let's say you want to use a Remote Desktop connection to a machine with IP 2.2.2.2
Run the wstunnel server on a different machine, tunneling to the destination on the RDP port 3389:

     wstunnel -s 0.0.0.0:8080 -t 2.2.2.2:3389

On the destination, you need to tweak some registry settings to relax the security policy for Remote Desktop.

    Open RegEdit, and navigate to the following key:
    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp
    Change "SecurityLayer" to 0
    Change "SelectNetworkDetect" to 0
    Reboot

On the client, first start wstunnel:

    wstunnel -t 3389 ws://server:8080

Now you can just open Remote Desktop Connection and connect to localhost

Proxy

When using socks proxy, ensure the host is IP address only, DNS name is not supported. For example:

# "localhost" won't work
wstunnel -t 2255:sshhost:22 --proxy socks://localhost:3111 http://wsserver
# instead, do:
wstunnel -t 2255:sshhost:22 --proxy socks://127.0.0.1:3111 https://wsserver

Http tunnel

An http tunnel will be established if websocket connection fails. Two long live http connections are established for sending and receiving data.

wstunnel's People

Contributors

asyncer avatar bylevel avatar dependabot[bot] avatar mhzed avatar micahfocht avatar mihaifm avatar notjulian avatar takuya-o avatar tamasbakos avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

wstunnel's Issues

websocket native extensions doesn't build

With the current dependency setting for websocket "^1.0.24" nodejs pulls an very old version of websocket (1.0.8) which doesn't build correct.
I tested a change to ">=1.0.24" which than pulls 1.0.25 and builds without any problems.
Could you please change the dependency?
I didn't checked the other ^... dependencies, but perhaps there are also used unnecessary old versions.

Support for shadowsocks?

Is it possible and convenient to make this project work as a SIP003 plugin for shadowsocks? If so, it would be amazing to use shadowsocks through websocket, or even through Cloudflare free CDN.

proxy setting seems not to work

When running wstunnel as client and using the -p switch to enable proxy usage the program fails because it tries to resolve the hostname of the remote machine. But that's why i'm using the proxy. The remote server can neither be resolved in DNS nor can a TCP connection beeing opend for it.

I'm in a corporate network behind an HTTP proxy using authentication. No Internet DNS, no default route to the internet.

Commandlines used:
U:\node_modules>node wstunnel/bin/wstt.js -c -t stdio::8080 -p http://proxy.local:8080 https://:8080
Mar 07 2018 14:40:48.532 GMT+0100 WS connect error: Error: connect ETIMEDOUT :8080

U:\node_modules>node wstunnel/bin/wstt.js -c -t stdio:mxrun.de:8080 -p http://proxy.local:8080 https://:8080
Mar 07 2018 14:38:58.208 GMT+0100 WS connect error: Error: getaddrinfo ENOTFOUND :8080
Mar 07 2018 14:38:58.226 GMT+0100 HTTP connect error: Error: getaddrinfo ENOTFOUND :8080
{ Error: getaddrinfo ENOTFOUND :8080
at errnoException (dns.js:50:10)
at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:92:26)
code: 'ENOTFOUND',
errno: 'ENOTFOUND',
syscall: 'getaddrinfo',
hostname: '',
host: '',
port: '8080' }

Note about ws:// ports

I'd just like to note that as ws is based on http it can be used on port 80. Furthermore it's using upgrade request so it's actually possible to create hybrid http+ws server listening on single port, at least using node. Also it implies that ws is routable via nginx so realistically user can use path routing or subdomain routing in nginx for example to set up wstunnel "next to" actual http server without any significant trouble.

All of it creates quite interesting use case for wstunnel apart from punching through firewalls: one can use it for tunneling single service for multiple machines exposed under single public IP for example:

ssh.machine1.hostname.com
ssh.machine2.hostname.com

or if subdomains are not available option then even using path:

hostname.com/machine1/ssh
hostname.com/machine2/ssh

Surprisingly it seems to be the only option I found to actually perform ssh hostname/path based routing using single port and single public IP for multiple machines running the same service - as long as we don't want to create dedicated ssh gateway with accounts for absolutely all users or full blown VPN (which is obviously inconvenient as creating such gateway brings further accounts management overhead and security implications). Paired with stunnel TLS tunneling for high security encryption and certificate based authentication it's interesting options for VNC and other management protocols as well.

SSL over proxy

I tried use the SSL option with proxy , is it supported ?

Error running the tunnel

I get this when i run it on port 8080. But when I choose to run on a different port nothing starts. It's just blank.
Do we have to configure something else to make it run? need some help on this
Thanks in advance

root@localhost:~# wstunnel -s 8080
events.js:292
      throw er; // Unhandled 'error' event
      ^
Error: listen EADDRINUSE: address already in use 127.0.0.1:8080
    at Server.setupListenHandle [as _listen2] (net.js:1307:16)
    at listenInCluster (net.js:1355:12)
    at doListen (net.js:1492:7)
    at processTicksAndRejections (internal/process/task_queues.js:85:21)
Emitted 'error' event on Server instance at:
    at emitErrorNT (net.js:1334:8)
    at processTicksAndRejections (internal/process/task_queues.js:84:21) {
  code: 'EADDRINUSE',
  errno: 'EADDRINUSE',
  syscall: 'listen',
  address: '127.0.0.1',
  port: 8080
}

Remote port forwarding

Hi!
Kindly direct how to implement server to client port forwarding.
For example:
Remote client with ip x.x.x.x connect to server y.y.y.y:zzzz and this ports forwards to websoket client with u.u.u.u:ssss?

bad handshake error while connecting with wstunnel server

I have requirement to use https://github.com/mhzed/wstunnel server and connect chisel client with it. wstunnel server is running on localhost:8081, getting below error when trying to connect

chisel client 127.0.0.1:8081 127.0.0.1:8086:127.0.0.1:22

2022/02/05 15:29:32 client: Connecting to ws://127.0.0.1:8081
2022/02/05 15:29:32 client: tun: proxy#127.0.0.1:8086=>22: Listening
2022/02/05 15:29:32 client: Connection error: websocket: bad handshake
2022/02/05 15:29:32 client: Retrying in 100ms...
2022/02/05 15:29:32 client: Connection error: websocket: bad handshake (Attempt: 1)
2022/02/05 15:29:32 client: Retrying in 200ms...
2022/02/05 15:29:32 client: Connection error: websocket: bad handshake (Attempt: 2)
2022/02/05 15:29:32 client: Retrying in 400ms...
2022/02/05 15:29:32 client: Connection error: websocket: bad handshake (Attempt: 3)
2022/02/05 15:29:32 client: Retrying in 800ms...
2022/02/05 15:29:33 client: Connection error: websocket: bad handshake (Attempt: 4)
2022/02/05 15:29:33 client: Retrying in 1.6s...

Invalid tunnel option 3333

At the server, I'm running

wstunnel -s 0.0.0.0:8888 -t localhost:2222

At the client, I'm running

wstunnel -t 3333 ws://localhost:8888

Yet, I'm getting the error

Invalid tunnel option 3333

If I specify the host and port from the client, it works:

wstunnel -t 3333:localhost:2222 ws://localhost:8888

Backchannel support needed

Need to have a back tunnel: port is opened on the server side that tunnels any incoming connection to the some adderss:port on the client side.

Always listen on loop back IP

If we don't specify the IP in -t switch, it will always listen on loop back IP,
for example wstunnel -t 8080 will only available on 127.0.0.1:8080 but I guess it would be better to listen on 0.0.0.0 or at least reflect it on documentation that it will listen on loop back by default.

Please help!

Hello everyone,
Please I need help.
I've configured everything & wstunnel and SSH are working as intended on my Linux PC:

SSH client <---> wstunnel (client) <---> internet <---> wstunnel (server) <---> SSH server

and I'm using SSH tunneling (as VPN on my PC).
but, please I would like to connect to my ssh (as VPN) via wstunnel on my android device.

please any ideas.
and could I use android third-party websocket clients to connect to wstunnel server ?
Note: I'm an IT guy, so you could go deeper at the explanation.

Unable to bind server to specific IP

$ ./wstt.js -s 2222
Thu Aug 06 2015 14:41:27 GMT+0000 (UTC) Server is listening on port 2222

# lsof -ni|grep node
node      5857   wstunnel   10u  IPv4 25660001      0t0  TCP *:2222 (LISTEN)

[...]

$ ./wstt.js -s 127.0.0.1:2222 
Thu Aug 06 2015 14:40:43 GMT+0000 (UTC) Server is listening on port 127.0.0.1:2222

# lsof -ni|grep node
#

It also creates the -s target as a socket in .:

srwxrwxr-x 1 wstunnel wstunnel     0 Aug  6 14:40 127.0.0.1:2222

It doesn't seem to create the socket when just the port is specified.

If it's listening to external traffic then most of the purpose of putting it behind an HTTPS proxy is defeated.

Tunnel stdio (feature request)

Hi,
I am using this currently to tunnel SSH out of work and it works very well, thank you :)

One thing that I would like is if I could call it from ssh as a proxy command, eg..
ssh -o ProxyCommand="wstt -t stdio:%h:%p --proxy http://1.2.3.4 ws://5.6.7.8:1234" [email protected]

I did have a look at modifying myself but my NodeJS is minimal and CoffeeScript is non-existent :(

My approach was going to be to form a duplex stream from stdin/stdout, then replace @tcpserver with above stream (and skip the listen part).

client side command is not listening on public IP

I use the command below and it will not listen on any port,
wstunnel -t 0.0.0.0:8080 ws://1.2.3.4:8080
But it only answers to loop back request while I need it be available on all stations in my LAN

Proxy support

Currently each port must be tunneled separetely. Proxy like HTTPS (CONNECT method) or SOCKS5 allowes dynamic selection of the target address and port by the client application.
Would you provide the Socks5 or HTTPS proxy support?

Wrong Ports

As I understand the client establish a [ws] connection with a [host:port] server, so, you just acces the server and it will forward all traffic to the client.
But if I have an app running at port 3000 in my PC and try to run
wstunnel -t 3000 ws://publicdomain.com:9000 but it will try to open the already used port 3000, wth? that doesn't make any sense.

Nginx reverse proxy with TLS

Thanks for your websocket tunnel implementation!

I've wanted to run it behind NGINX reverse proxy with TLS.

nginx config part:

location /ws_proxy/ {
            proxy_pass http://127.0.0.1:8080;
            proxy_buffering off;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $connection_upgrade;
            proxy_set_header        Host            $host;
            proxy_set_header        X-Real-IP       $remote_addr;
            proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header        X-Forwarded-Proto $scheme;
#access_log off;
        }

TLS is enabled, and it's running on 443 standard HTTPS port.

wstunnel server is running like this: wstunnel server --restrict-http-upgrade-path-prefix ws_proxy ws://[::]:8080. Logs:

2023-11-12T11:34:18.437083Z  INFO wstunnel: WsServerConfig { socket_so_mark: None, bind: [::]:8080, restrict_to: None, websocket_ping_frequency: None, timeout_connect: 10s, websocket_mask_frame: false, tls: false }
2023-11-12T11:34:18.437139Z  INFO wstunnel::tunnel::server: Starting wstunnel server listening on [::]:8080

wstunnel client is running like this: wstunnel.exe client -L socks5://0.0.0.0:8888 --http-upgrade-path-prefix ws_proxy wss://myserver.com/ Logs:

2023-11-10T20:42:28.938420Z  INFO wstunnel::tls: Doing TLS handshake using sni DnsName("myserver.com") with the server myserver.com:443
2023-11-10T20:42:31.231458Z  INFO wstunnel::tcp: Opening TCP connection to myserver.com:443
2023-11-10T20:42:31.247044Z  INFO wstunnel::tcp: Opening TCP connection to myserver.com:443
2023-11-10T20:42:31.333049Z  INFO wstunnel::tls: Doing TLS handshake using sni DnsName("myserver.com") with the server myserver.com:443
2023-11-10T20:42:31.359116Z  INFO wstunnel::tls: Doing TLS handshake using sni DnsName("myserver.com") with the server myserver.com:443
2023-11-10T20:42:35.853700Z  INFO wstunnel::tcp: Opening TCP connection to myserver.com:443
2023-11-10T20:42:35.992473Z  INFO wstunnel::tls: Doing TLS handshake using sni DnsName("myserver.com") with the server myserver.com:443

There is nothing on Nginx access or error logs.
Long story short it is not working behind Nginx. Am I missing something?

listen EACCES error

Hi mhzed and bylevel, first thank for the great tool.

I found out this is the issue with environment, due to my environment do not able to bind to localhost, see next comment.

I facing some problem when running, can you figure out what I do wrong?
Normally I will run node wstt.js -s 8080, instead of wstunnel as I do not have root access to install in global.

./wstunnel -s 8080

Warning: Native modules not compiled. XOR performance will be degraded.
Warning: Native modules not compiled. UTF-8 validation disabled.

events.js:48
throw arguments[1]; // Unhandled 'error' event
^
Error: listen EACCES
at errnoException (net.js:670:11)
at Array.0 (net.js:756:28)
at EventEmitter._tickCallback (node.js:190:38)

wstunnel quits if invalid protocol passed

If anything other than "tunnel-protocol" is requested, the server prints an error to the console, and quits. This represents at best, an instability, and at worst a vector for a DOS attack.

Any possibility the server could reject the invalid connection, and then keep running, so existing users are not dropped?

Occasional client crash

I wasn't able to dig enough to find out the exact cause of the problem, but occasionally my client crashes with the following exception:

[Apr 17 2017 12:14:23.094 GMT+0430] WS connect error: Server responded with a non-101 status: 200
Response Headers Follow:
connection: keep-alive
date: Mon, 17 Apr 2017 07:44:23 GMT
transfer-encoding: chunked

[Apr 17 2017 12:14:23.103 GMT+0430] WS connect error: Server responded with a non-101 status: 200
Response Headers Follow:
connection: keep-alive
date: Mon, 17 Apr 2017 07:44:23 GMT
transfer-encoding: chunked

[Apr 17 2017 12:14:23.111 GMT+0430] Tunnel closed
_http_outgoing.js:354
    throw new Error('"value" required in setHeader("' + name + '", value)');
    ^

Error: "value" required in setHeader("x-htunsess", value)
    at ClientRequest.OutgoingMessage.setHeader (_http_outgoing.js:354:11)
    at new ClientRequest (_http_client.js:86:14)
    at Object.exports.request (http.js:31:10)
    at ClientConn.module.exports.ClientConn._recv (C:\Users\y\AppData\Roaming\npm\node_modules\wstunnel\lib\httptunnel\ClientConn.js:159:25)
    at ClientRequest.<anonymous> (C:\Users\y\AppData\Roaming\npm\node_modules\wstunnel\lib\httptunnel\ClientConn.js:110:19)
    at emitOne (events.js:96:13)
    at ClientRequest.emit (events.js:188:7)
    at HTTPParser.parserOnIncomingClient [as onIncoming] (_http_client.js:474:21)
    at HTTPParser.parserOnHeadersComplete (_http_common.js:99:23)
    at Socket.socketOnData (_http_client.js:363:20)

It might be due to a proxy server or firewall messing with request, and I am not expecting to fix that, but it would be very helpful if client doesn't crash in such a situation and maybe just log an error and drop that connection but continue to work.

Setting for proxy server

Please add a function so that this project would work when user need to open the connection through a proxy server first.
For example,make a new option

wstunnel -t 33 ws://server:8080 -proxy <IP Proxy Server>:<Port>

Why do you open new ws connection for each tcp conn?

Hi there! Thanks for your awesome work :)

I have a question on the architecture: why do you open a new ws connection for each TCP connection? Why not multiplex all messages in one and only one websocket channel? It'd be better for my case to have one ws connection, through which all the traffic goes. How do you think, would it work over one channel? Can I end up with a working multiplexor OR it'd be better to live with multiple connections?

Doesn't install

npm install wstunnel
npm WARN deprecated [email protected]: Use uuid module instead
/root
└── [email protected]

npm WARN enoent ENOENT: no such file or directory, open '/root/package.json'
npm WARN root No description
npm WARN root No repository field.
npm WARN root No README data
npm WARN root No license field.

Error: read ECONNRESET

My environment: HUAWEI MATE 9 Android, Termux, npm 3.10.10, node 6.11.3

Warning: Native modules not compiled.  XOR performance will be degraded.
Warning: Native modules not compiled.  UTF-8 validation disabled.
………

events.js:160
      throw er; // Unhandled 'error' event
      ^

Error: read ECONNRESET
    at exports._errnoException (util.js:1020:11)
    at TCP.onread (net.js:568:26)

Add license file

package.json indicates an MIT license but there is no license file in the repos.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.