3 Commits

Author SHA1 Message Date
lamp 409ab09790 rewrite attempt 12/13/21(?) not work 2022-01-17 17:43:38 -08:00
Lamp 61ca9d54d2 Update README.md 2020-04-19 10:29:42 -07:00
Lamp fa028e4af0 Update README.md 2020-04-19 10:27:52 -07:00
5 changed files with 112 additions and 64 deletions
+3 -1
View File
@@ -69,4 +69,6 @@ ws://localhost:8080/?target=ws://www.multiplayerpiano.com:443&origin=http://www.
Query parameters may or may not be encoded, but querystring chars (`&` and `=`) must be encoded to escape them.
**Note:** If the `target` is missing or invalid, or if an error occurs when connecting to the remote host (such as if it responded with a 403), your connection is simply closed. Ideally, the proxy server would wait for the connection to the target to finish, before responding to the client with the same response of the target; however, I found this much too complicated to set up, so I just kept it simple.
## Issues
If the `target` is missing or invalid, or if an error occurs when connecting to the remote host (such as if it responded with a 403), your connection is simply closed. Ideally, the proxy server would wait for the connection to the target to finish, before responding to the client with the same response of the target; however, I found this much too complicated to set up, so I just kept it simple.
+38 -48
View File
@@ -1,54 +1,44 @@
var WebSocket = require('ws');
var {parse:parseQueryString} = require('query-string');
var wss = new WebSocket.Server({
port: process.env.OPENSHIFT_NODEJS_PORT || process.env.PORT || 8080
var http = require("http");
var https = require("https");
var server = http.createServer();
server.listen(process.env.OPENSHIFT_NODEJS_PORT || process.env.PORT || 8080);
server.on("request", function (req, res) {
res.writeHead(400);
res.end("Websockets only!");
});
var conncount = 0;
wss.on('connection', function (cws, req){
var number = conncount++;
console.log(`New connection #${number} from ${req.connection.remoteAddress} with ${req.url}`);
cws.on('close', function(){
console.log(`Closing connection #${number} from ${req.connection.remoteAddress}`);
});
var querystring = req.url.substr(1);
if (!querystring) return cws.close();
var params = parseQueryString(querystring);
var target = params.target;
if (!target) return cws.close();
var headers = {};
for (let key in params) if (key != "target") headers[key] = params[key];
try {
var tws = new WebSocket(target, {headers});
} catch(e) {
console.error(e);
cws.close();
return;
server.on("upgrade", function (req, socket) {
if (req.headers["upgrade"] != "websocket") return socket.end("HTTP/1.1 400 Websocket upgrade only");
var xof = req.url.indexOf('?');
if (xof < 0) return socket.end("HTTP/1.1 400 Missing querystring");
var params = new URLSearchParams(req.url.substring(xof));
var targetURL = decodeURIComponent(params.get("target"));
if (!targetURL) return socket.end("HTTP/1.1 400 Target parameter is required");
targetURL = new URL(targetURL);
if (["https:","wss:"].includes(targetURL.protocol))
var secure = true;
else if (!["http:","ws:"].includes(targetURL.protocol))
return socket.end("HTTP/1.1 400 Unsupported target protocol");
targetURL.protocol = targetURL.protocol.replace("ws", "http");
var targetReq = (secure ? https : http).get(targetURL, {
headers: {
"Connection": "Upgrade",
"Upgrade": "websocket",
"Sec-WebSocket-Version": 13,
"Sec-WebSocket-Key": require('crypto').randomBytes(16).toString('base64')
}
// client to target
var messageBuffer = [];
tws.on('open', function(){
for (let message of messageBuffer) tws.send(message);
messageBuffer = undefined;
});
cws.on('message', function(message){
if (tws.readyState == WebSocket.OPEN) tws.send(message);
else if (messageBuffer) messageBuffer.push(message);
console.debug("sdfsdfjig");
targetReq.on("response", function(targetRes) {
console.log(req.socket.remoteAddress, targetURL.href, targetRes.statusCode);
if (targetRes.statusCode == 101) {
targetRes.pipe(socket);
socket.pipe(targetRes);
} else {
socket.end(`HTTP/1.1 502 Unexpected status code from target server: ${targetRes.statusCode}`);
}
});
cws.on('close', function(){
tws.close();
messageBuffer = undefined;
targetReq.on("error", function(error) {
console.log(req.socket.remoteAddress, targetURL.href, error.message);
socket.end();
});
cws.on('error', console.error);
// target to client
tws.on('message', function(message){
if (cws.readyState == WebSocket.OPEN) cws.send(message);
});
tws.on('close', function(){
cws.close();
});
tws.on('error', console.error);
});
+61 -11
View File
@@ -1,12 +1,64 @@
{
"name": "websocket-proxy",
"lockfileVersion": 2,
"requires": true,
"lockfileVersion": 1,
"packages": {
"": {
"dependencies": {
"async-limiter": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz",
"integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg=="
"query-string": "^6.2.0",
"ws": "^8.3.0"
}
},
"node_modules/decode-uri-component": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
"integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=",
"engines": {
"node": ">=0.10"
}
},
"node_modules/query-string": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/query-string/-/query-string-6.2.0.tgz",
"integrity": "sha512-5wupExkIt8RYL4h/FE+WTg3JHk62e6fFPWtAZA9J5IWK1PfTfKkMS93HBUHcFpeYi9KsY5pFbh+ldvEyaz5MyA==",
"dependencies": {
"decode-uri-component": "^0.2.0",
"strict-uri-encode": "^2.0.0"
},
"engines": {
"node": ">=6"
}
},
"node_modules/strict-uri-encode": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz",
"integrity": "sha1-ucczDHBChi9rFC3CdLvMWGbONUY=",
"engines": {
"node": ">=4"
}
},
"node_modules/ws": {
"version": "8.3.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.3.0.tgz",
"integrity": "sha512-Gs5EZtpqZzLvmIM59w4igITU57lrtYVFneaa434VROv4thzJyV6UjIL3D42lslWlI+D4KzLYnxSwtfuiO79sNw==",
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": "^5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
"optional": true
},
"utf-8-validate": {
"optional": true
}
}
}
},
"dependencies": {
"decode-uri-component": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
@@ -27,12 +79,10 @@
"integrity": "sha1-ucczDHBChi9rFC3CdLvMWGbONUY="
},
"ws": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-6.0.0.tgz",
"integrity": "sha512-c2UlYcAZp1VS8AORtpq6y4RJIkJ9dQz18W32SpR/qXGfLDZ2jU4y4wKvvZwqbi7U6gxFQTeE+urMbXU/tsDy4w==",
"requires": {
"async-limiter": "~1.0.0"
}
"version": "8.3.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.3.0.tgz",
"integrity": "sha512-Gs5EZtpqZzLvmIM59w4igITU57lrtYVFneaa434VROv4thzJyV6UjIL3D42lslWlI+D4KzLYnxSwtfuiO79sNw==",
"requires": {}
}
}
}
+1 -1
View File
@@ -4,6 +4,6 @@
},
"dependencies": {
"query-string": "^6.2.0",
"ws": "^6.0.0"
"ws": "^8.3.0"
}
}
+6
View File
@@ -0,0 +1,6 @@
var {WebSocketServer} = require("ws");
var wss = new WebSocketServer({port:4444});
wss.on("connection", ws => {
ws.send("ohayo");
ws.on("message", console.log);
});