From a55912c7f28ffa8695568d656a87dbe467b33ff0 Mon Sep 17 00:00:00 2001 From: a-sync Date: Tue, 17 Sep 2024 11:44:40 +0200 Subject: [PATCH] skip address if IP is in private range --- README.md | 2 -- package-lock.json | 18 ++++++++++++++++++ package.json | 2 ++ src/discord-bot.ts | 5 ++++- src/game-server.ts | 4 ++-- src/lib/ipregex.ts | 21 --------------------- src/slack-bot.ts | 14 +++++++++----- src/telegram-bot.ts | 15 ++++++++++----- 8 files changed, 45 insertions(+), 36 deletions(-) delete mode 100644 src/lib/ipregex.ts diff --git a/README.md b/README.md index 32e7f82..e31f8e2 100644 --- a/README.md +++ b/README.md @@ -192,8 +192,6 @@ Check the list of [contributors](https://github.com/a-sync/game-server-watcher/c # Acknowledgments This project was inspired by (the sudden disappearance of) "_Game Status#5371_" bot and its creator [Ramzi Saheb](https://github.com/Ramzi-Sah) on discord. -IP regex stolen from the [ip-regex](https://github.com/sindresorhus/ip-regex) package source. - GSW icon stolen from _Marvel’s Voices: Indigenous Voices #1_ "_The Watcher_" by [Jeffrey Veregge](https://www.jeffreyveregge.com). Backgrounds stolen from [purple nebulas](https://opengameart.org/content/seamless-space-backgrounds) by [Screaming Brain Studios](https://screamingbrainstudios.com) and [imgur](https://imgur.com). diff --git a/package-lock.json b/package-lock.json index 001beec..366d9cc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,11 +15,13 @@ "dotenv": "^16.3.2", "gamedig": "^5.1.3", "grammy": "^1.20.3", + "ip": "^2.0.1", "lowdb": "^6.1.1", "mustache": "^4.2.0" }, "devDependencies": { "@types/gamedig": "^5.0.0", + "@types/ip": "^1.1.3", "@types/node": "^16.18.73", "eslint": "^8.56.0", "nodemon": "^3.0.3", @@ -586,6 +588,16 @@ "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==" }, + "node_modules/@types/ip": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@types/ip/-/ip-1.1.3.tgz", + "integrity": "sha512-64waoJgkXFTYnCYDUWgSATJ/dXEBanVkaP5d4Sbk7P6U7cTTMhxVyROTckc6JKdwCrgnAjZMn0k3177aQxtDEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@types/is-stream/-/is-stream-1.1.0.tgz", @@ -2643,6 +2655,12 @@ "node": ">= 0.4" } }, + "node_modules/ip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.1.tgz", + "integrity": "sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==", + "license": "MIT" + }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", diff --git a/package.json b/package.json index 50427f8..e5e368c 100644 --- a/package.json +++ b/package.json @@ -30,11 +30,13 @@ "dotenv": "^16.3.2", "gamedig": "^5.1.3", "grammy": "^1.20.3", + "ip": "^2.0.1", "lowdb": "^6.1.1", "mustache": "^4.2.0" }, "devDependencies": { "@types/gamedig": "^5.0.0", + "@types/ip": "^1.1.3", "@types/node": "^16.18.73", "eslint": "^8.56.0", "nodemon": "^3.0.3", diff --git a/src/discord-bot.ts b/src/discord-bot.ts index be13295..07a0adb 100644 --- a/src/discord-bot.ts +++ b/src/discord-bot.ts @@ -3,6 +3,7 @@ import { JSONPreset } from 'lowdb/node'; import { GameServer } from './game-server.js'; import hhmmss from './lib/hhmmss.js'; import { DiscordConfig } from './watcher.js'; +import ip from 'ip'; const DATA_PATH = process.env.DATA_PATH || './data/'; const DBG = Boolean(Number(process.env.DBG)); @@ -180,7 +181,9 @@ class ServerInfoMessage { if (gs.info.game) fields.push({ name: 'Game', value: String(gs.info.game), inline: true }); if (gs.info.map) fields.push({ name: 'Map', value: String(gs.info.map), inline: true }); fields.push({ name: 'Players', value: String(gs.info.playersNum + '/' + gs.info.playersMax), inline: true }); - fields.push({ name: 'Address', value: String(gs.info.connect) }); + + const connectIp = gs.info.connect.split(':')[0]; + if (ip.isPublic(connectIp)) fields.push({ name: 'Address', value: String(gs.info.connect) }); if (gs.config.infoText) fields.push({ name: 'Info', value: String(gs.config.infoText).slice(0, 1024) }); diff --git a/src/game-server.ts b/src/game-server.ts index 31c119c..7bb52e1 100644 --- a/src/game-server.ts +++ b/src/game-server.ts @@ -1,7 +1,7 @@ import axios from 'axios'; import { GameDig, Player, QueryOptions } from 'gamedig'; import { JSONPreset } from 'lowdb/node'; -import ipRegex from './lib/ipregex.js'; +import ip from 'ip'; import getIP from './lib/getip.js'; import { GameServerConfig } from './watcher.js'; @@ -205,7 +205,7 @@ export class GameServer { async getIp() { if (this.ip === '0.0.0.0') { - if (ipRegex.test(this.config.host)) { + if (ip.isV4Format(this.config.host) || ip.isV6Format(this.config.host)) { this.ip = this.config.host; } else { this.ip = await getIP(this.config.host) || '0.0.0.0'; diff --git a/src/lib/ipregex.ts b/src/lib/ipregex.ts deleted file mode 100644 index 0ee8277..0000000 --- a/src/lib/ipregex.ts +++ /dev/null @@ -1,21 +0,0 @@ -// source: https://github.com/sindresorhus/ip-regex -const v4 = '(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}'; - -const v6segment = '[a-fA-F\\d]{1,4}'; - -const v6 = ` -(?: -(?:${v6segment}:){7}(?:${v6segment}|:)| // 1:2:3:4:5:6:7:: 1:2:3:4:5:6:7:8 -(?:${v6segment}:){6}(?:${v4}|:${v6segment}|:)| // 1:2:3:4:5:6:: 1:2:3:4:5:6::8 1:2:3:4:5:6::8 1:2:3:4:5:6::1.2.3.4 -(?:${v6segment}:){5}(?::${v4}|(?::${v6segment}){1,2}|:)| // 1:2:3:4:5:: 1:2:3:4:5::7:8 1:2:3:4:5::8 1:2:3:4:5::7:1.2.3.4 -(?:${v6segment}:){4}(?:(?::${v6segment}){0,1}:${v4}|(?::${v6segment}){1,3}|:)| // 1:2:3:4:: 1:2:3:4::6:7:8 1:2:3:4::8 1:2:3:4::6:7:1.2.3.4 -(?:${v6segment}:){3}(?:(?::${v6segment}){0,2}:${v4}|(?::${v6segment}){1,4}|:)| // 1:2:3:: 1:2:3::5:6:7:8 1:2:3::8 1:2:3::5:6:7:1.2.3.4 -(?:${v6segment}:){2}(?:(?::${v6segment}){0,3}:${v4}|(?::${v6segment}){1,5}|:)| // 1:2:: 1:2::4:5:6:7:8 1:2::8 1:2::4:5:6:7:1.2.3.4 -(?:${v6segment}:){1}(?:(?::${v6segment}){0,4}:${v4}|(?::${v6segment}){1,6}|:)| // 1:: 1::3:4:5:6:7:8 1::8 1::3:4:5:6:7:1.2.3.4 -(?::(?:(?::${v6segment}){0,5}:${v4}|(?::${v6segment}){1,7}|:)) // ::2:3:4:5:6:7:8 ::2:3:4:5:6:7:8 ::8 ::1.2.3.4 -)(?:%[0-9a-zA-Z]{1,})? // %eth0 %1 -`.replace(/\s*\/\/.*$/gm, '').replace(/\n/g, '').trim(); - -const v46Exact = new RegExp(`(?:^${v4}$)|(?:^${v6}$)`); - -export default v46Exact; diff --git a/src/slack-bot.ts b/src/slack-bot.ts index 5bdd351..c7b0d20 100644 --- a/src/slack-bot.ts +++ b/src/slack-bot.ts @@ -4,6 +4,7 @@ import { JSONPreset } from 'lowdb/node'; import { GameServer } from './game-server.js'; import hhmmss from './lib/hhmmss.js'; import { SlackConfig } from './watcher.js'; +import ip from 'ip'; const DATA_PATH = process.env.DATA_PATH || './data/'; const DBG = Boolean(Number(process.env.DBG)); @@ -193,11 +194,14 @@ class ServerInfoMessage { text: '*Players* \r\n' + String(gs.info.playersNum + '/' + gs.info.playersMax) }); - text += '\r\nAddress: ' + String(gs.info.connect); - fields2.push({ - type: 'mrkdwn', - text: '*Address* \r\n' + String(gs.info.connect) - }); + const connectIp = gs.info.connect.split(':')[0]; + if (ip.isPublic(connectIp)) { + text += '\r\nAddress: ' + String(gs.info.connect); + fields2.push({ + type: 'mrkdwn', + text: '*Address* \r\n' + String(gs.info.connect) + }); + } if (fields2.length > 0) { blocks.push({ diff --git a/src/telegram-bot.ts b/src/telegram-bot.ts index 5095a8a..0919975 100644 --- a/src/telegram-bot.ts +++ b/src/telegram-bot.ts @@ -3,6 +3,7 @@ import { JSONPreset } from 'lowdb/node'; import { GameServer } from './game-server.js'; import hhmmss from './lib/hhmmss.js'; import { TelegramConfig } from './watcher.js'; +import ip from 'ip'; const DATA_PATH = process.env.DATA_PATH || './data/'; const DBG = Boolean(Number(process.env.DBG)); @@ -137,12 +138,16 @@ class ServerInfoMessage { let infoText = this.escapeMarkdown(gs.niceName) + ' offline...'; if (gs.info && gs.online) { - infoText = [ + const infoBlocks = [ this.escapeMarkdown(gs.niceName), - this.escapeMarkdown(gs.info.game) + ' / ' + this.escapeMarkdown(gs.info.map), - this.escapeMarkdown(gs.info.connect), - 'Players ' + gs.info.playersNum + '/' + gs.info.playersMax - ].join('\n'); + this.escapeMarkdown(gs.info.game) + ' / ' + this.escapeMarkdown(gs.info.map) + ]; + + const connectIp = gs.info.connect.split(':')[0]; + if (ip.isPublic(connectIp)) infoBlocks.push(this.escapeMarkdown(gs.info.connect)); + + infoBlocks.push('Players ' + gs.info.playersNum + '/' + gs.info.playersMax); + infoText = infoBlocks.join('\n'); if (gs.config.infoText) infoText += 'Info:\n' + String(gs.config.infoText).slice(0, 1024) + '\n';