├── .gitignore ├── package.json ├── COPYING ├── README.md └── ws-tcp-bridge /.gitignore: -------------------------------------------------------------------------------- 1 | lib-cov 2 | *.seed 3 | *.log 4 | *.csv 5 | *.dat 6 | *.out 7 | *.pid 8 | *.gz 9 | 10 | pids 11 | logs 12 | results 13 | 14 | npm-debug.log 15 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ws-tcp-bridge", 3 | "version": "1.0.0", 4 | "description": "Proxy between websocket and tcp servers", 5 | "bin" : { "ws-tcp-bridge" : "./ws-tcp-bridge" }, 6 | "dependencies": { 7 | "optimist": "~0.3.5", 8 | "ws": "~0.4.23" 9 | }, 10 | "devDependencies": {}, 11 | "scripts": { 12 | "test": "echo \"Error: no test specified\" && exit 1" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "https://github.com/andrewchambers/ws-tcp-bridge.git" 17 | }, 18 | "keywords": [ 19 | "websockets", 20 | "ws", 21 | "proxy", 22 | "tcp" 23 | ], 24 | "author": "andrewchamberss@gmail.com", 25 | "license": "BSD" 26 | } 27 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Andrew Chambers 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ws-tcp-bridge 2 | ============= 3 | 4 | Project status: 5 | currently not in use so i dont know if its up to date with its dependencies. Feel free to use the code as an example however 6 | the only licensing restriction is let me know if its been helpful! 7 | 8 | A websocket to tcp proxy server, using nodejs which bridges websockets and tcp servers in either direction. 9 | 10 | WIP - the actual code is extremely simple, but not tested well (YET), feel free to help. 11 | working examples will be provided with some real services when I get time. 12 | *NOTE* - currently I only support binary ws frames which isnt implemented in alot of browsers... 13 | A workaround is simple to implement. 14 | 15 | INSTALL - 16 | 17 | nodejs must be installed first before using this server. 18 | 19 | #install to current directory 20 | npm install ws-tcp-bridge 21 | ./node_modules/.bin/ws-tcp-bridge 22 | 23 | #or install globally 24 | npm install -g ws-tcp-bridge 25 | ws-tcp-bridge 26 | 27 | example - 28 | 29 | $ ws-tcp-bridge --method=ws2tcp --lport=8080 --rhost=127.0.0.1:8081 30 | 31 | proxy mode ws -> tcp 32 | forwarding port 8080 to 127.0.0.1:8081 33 | 34 | 35 | $ ws-tcp-bridge --method=tcp2ws --lport=8080 --rhost=ws://127.0.0.1:8081 36 | 37 | proxy mode tcp -> ws 38 | forwarding port 8080 to 127.0.0.1:8081 39 | 40 | 41 | If you want to have negotiation of the target address consider forwarding to a socks5 proxy 42 | -------------------------------------------------------------------------------- /ws-tcp-bridge: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var ws_module = require('ws'); 4 | var net = require('net'); 5 | 6 | var argv = require('optimist') 7 | .usage('Forward tcp connections to websocket servers, or websocket connections to tcp servers.') 8 | .demand('lport') 9 | .describe('lport','port to listen for connections on.') 10 | .demand('rhost') 11 | .describe('rhost','address to forward the connection to.') 12 | .demand('method') 13 | .describe('method','either tcp2ws or ws2tcp').argv; 14 | 15 | 16 | var wsMask = (argv.method == 'tcp2ws'); 17 | 18 | function initSocketCallbacks(state,ws,s) { 19 | 20 | function flushSocketBuffer() { 21 | if(state.sBuffer.length > 0) { 22 | s.write(Buffer.concat(state.sBuffer)); 23 | } 24 | state.sBuffer = null; 25 | }; 26 | 27 | function flushWebsocketBuffer() { 28 | if(state.wsBuffer.length > 0) { 29 | ws.send(Buffer.concat(state.wsBuffer),{binary: true,mask: wsMask}); 30 | } 31 | state.wsBuffer = null; 32 | }; 33 | 34 | s.on('close', function(had_error) { 35 | ws.removeAllListeners('close'); 36 | ws.close(); 37 | }); 38 | 39 | ws.on('close', function() { 40 | s.removeAllListeners('close'); 41 | s.end(); 42 | }); 43 | 44 | ws.on('error', function (e) { 45 | console.log('websocket error'); 46 | console.log(e); 47 | ws.removeAllListeners('close'); 48 | s.removeAllListeners('close'); 49 | ws.close(); 50 | s.end(); 51 | }); 52 | 53 | s.on('error', function (e) { 54 | console.log('socket error'); 55 | console.log(e); 56 | ws.removeAllListeners('close'); 57 | s.removeAllListeners('close'); 58 | ws.close(); 59 | s.end(); 60 | }); 61 | 62 | s.on('connect', function() { 63 | state.sReady = true; 64 | flushSocketBuffer(); 65 | }); 66 | 67 | ws.on('open', function () { 68 | state.wsReady = true; 69 | flushWebsocketBuffer(); 70 | }); 71 | 72 | s.on('data', function(data) { 73 | 74 | if(! state.wsReady) { 75 | state.wsBuffer.push(data); 76 | } else { 77 | ws.send(data,{binary: true,mask: wsMask}); 78 | } 79 | }); 80 | 81 | ws.on('message', function(m,flags) { 82 | if(!state.sReady) { 83 | state.sBuffer.push(m); 84 | } else { 85 | s.write(m); 86 | } 87 | }); 88 | } 89 | 90 | function tcp2ws() { 91 | console.log('proxy mode tcp -> ws'); 92 | console.log('forwarding port ' + argv.lport + ' to ' + argv.rhost); 93 | 94 | var server = net.createServer(function(s) { 95 | var ws = new ws_module(argv.rhost); 96 | 97 | var state = { 98 | sReady : true, 99 | wsReady : false, 100 | wsBuffer: [], 101 | sBuffer : [] 102 | }; 103 | initSocketCallbacks(state,ws,s); 104 | }); 105 | server.listen(argv.lport); 106 | } 107 | 108 | function ws2tcp() { 109 | 110 | console.log('proxy mode ws -> tcp'); 111 | console.log('forwarding port ' + argv.lport + ' to ' + argv.rhost); 112 | 113 | wss = new ws_module.Server({port: argv.lport}); 114 | wss.on('connection', function(ws) { 115 | var addr_port = argv.rhost.split(':'); 116 | var s = net.connect(addr_port[1],addr_port[0]); 117 | 118 | var state = { 119 | sReady : false, 120 | wsReady : true, // there is no callback so i assume its already connected 121 | wsBuffer: [], 122 | sBuffer : [] 123 | }; 124 | initSocketCallbacks(state,ws,s); 125 | }); 126 | 127 | } 128 | 129 | if(argv.method == 'tcp2ws') { 130 | tcp2ws(); 131 | } else if (argv.method == 'ws2tcp') { 132 | ws2tcp(); 133 | } else { 134 | console.error("Method must be either tcp2ws or ws2tcp!"); 135 | } 136 | --------------------------------------------------------------------------------