From 7bf4baa92134009050018c73efee8d34f8c436ce Mon Sep 17 00:00:00 2001 From: Tobias Berger Date: Sat, 8 Jan 2022 17:17:43 +0100 Subject: [PATCH] Several changes ~Use TLS properly +Generate author IDs from Salted IPs ~Change port +Add start script --- .gitignore | 3 +- package.json | 6 ++-- server.node.ts | 94 ++++++++++++++++++++++++++++++++++++++++---------- 3 files changed, 81 insertions(+), 22 deletions(-) diff --git a/.gitignore b/.gitignore index 7190e32..522e90d 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ !*.config.js .rollup.cache tsconfig.tsbuildinfo -node_modules \ No newline at end of file +node_modules +*.pem \ No newline at end of file diff --git a/package.json b/package.json index 09e2a47..7651a8b 100644 --- a/package.json +++ b/package.json @@ -2,11 +2,13 @@ "name": "web-drs-backend", "version": "1.0.0", "description": "", - "main": "server.js", + "main": "server.node.bundle.js", "directories": { "lib": "lib" }, "scripts": { + "dev": "yarn build && yarn start", + "start": "node server.node.bundle.js", "build": "rollup --config ./rollup.config.js" }, "repository": { @@ -28,4 +30,4 @@ "typescript": "^4.5.4", "ws": "^8.4.0" } -} +} \ No newline at end of file diff --git a/server.node.ts b/server.node.ts index b34fd6b..b3d494c 100644 --- a/server.node.ts +++ b/server.node.ts @@ -1,39 +1,87 @@ +import * as fs from "fs"; +import * as https from "https"; import { WebSocketServer } from "ws"; + +import * as crypto from "crypto"; + +import type { AckMessage, TextMessage } from "./lib/ServerMessage"; + import { isServerMessage, isTextMessage, MessageType, -} from "./lib/types/ServerMessage"; +} from "./lib/ServerMessage"; -const port = 8989; +const SALT = crypto + .randomBytes(Math.round(Math.random() * 1024)) + .toString("hex"); + +const port = 8085; const timeout = 15000; -const server = new WebSocketServer({port}); +const httpsServer = https.createServer({ + key: fs.readFileSync("./key.pem"), + cert: fs.readFileSync("./cert.pem"), +}); +const webSocketServer = new WebSocketServer({ server: httpsServer }); console.log("listening on port: " + port); -server.on("connection", function connection(socket) { - function close() { - socket.send("closing connection due to inactivity"); - socket.close(); +function hash(str: string) { + return crypto.createHash("SHAKE256").update(str, "utf-8").digest("hex"); +} + +async function handleTextMessage(message: TextMessage, from: string) { + for (const to of webSocketServer.clients) { + to.send( + JSON.stringify( + Object.assign({}, message, { + author: from, + }) + ) + ); + } +} + +webSocketServer.on("connection", function connection(socket, request) { + const close = (reason: string, code: number = 1000) => { + socket.send( + JSON.stringify({ + type: MessageType.ACK, + date: Date.now(), + __ctx: `closing connection. reason: ${reason}`, + } as AckMessage) + ); + socket.close(code, `closing connection. reason: ${reason}`); + }; + + let authorID: string; + { + let ip: string | undefined; + if (request.headers["x-forwarded-for"] !== undefined) { + const forwardedFor = request.headers["x-forwarded-for"]; + ip = + typeof forwardedFor === "string" + ? forwardedFor.split(",")[0]?.trim() + : forwardedFor[0]; + } else { + ip = request.socket.remoteAddress; + } + if (ip === undefined) { + close("could not generate author id", 1008); + console.error("connection without IP. closing."); + return; + } + authorID = hash(ip + SALT); } socket.on("message", function (rawMessage: string) { - console.log("message: " + rawMessage); - const message = JSON.parse(rawMessage); if (!isServerMessage(message)) { console.error(`Unexpected message received from client \`${message}\``); } if (isTextMessage(message)) { - socket.send( - JSON.stringify({ - type: MessageType.TEXT, - date: Date.now(), - author: "ECHO Service", - content: message.content, - }), - ); + handleTextMessage(message, authorID); } clearTimeout(closeTimeout); closeTimeout = setTimeout(close, timeout); @@ -42,7 +90,15 @@ server.on("connection", function connection(socket) { console.log("closed a connection"); }); - console.log("new client connected!"); - socket.send("connected"); + console.log("new client connected! ID:", authorID); + socket.send( + JSON.stringify({ + type: MessageType.ACK, + date: Date.now(), + __ctx: "connected successfully", + } as AckMessage) + ); let closeTimeout = setTimeout(close, timeout); }); + +httpsServer.listen(port);