netplaySniff – Diff between revs 1 and 2
?pathlinks?
Rev 1 | Rev 2 | |||
---|---|---|---|---|
Line 1... | Line 1... | |||
1 | #!/usr/bin/env node |
1 | #!/usr/bin/env node |
|
2 | /////////////////////////////////////////////////////////////////////////// |
2 | /////////////////////////////////////////////////////////////////////////// |
|
3 | // Copyright (C) 2023 Wizardry and Steamworks - License: MIT // |
3 | // Copyright (C) 2024 Wizardry and Steamworks - License: MIT // |
|
4 | /////////////////////////////////////////////////////////////////////////// |
4 | /////////////////////////////////////////////////////////////////////////// |
|
Line 5... | Line 5... | |||
5 | |
5 | |
|
6 | const fs = require('fs') |
6 | const fs = require('fs') |
|
7 | const path = require('path') |
7 | const path = require('path') |
|
Line 13... | Line 13... | |||
13 | const PROTOCOL = decoders.PROTOCOL |
13 | const PROTOCOL = decoders.PROTOCOL |
|
14 | const shortHash = require('short-hash') |
14 | const shortHash = require('short-hash') |
|
15 | const { exec } = require("child_process") |
15 | const { exec } = require("child_process") |
|
16 | const Inotify = require('inotify-remastered').Inotify |
16 | const Inotify = require('inotify-remastered').Inotify |
|
17 | const inotify = new Inotify() |
17 | const inotify = new Inotify() |
|
- | 18 | const sqlite = require('sqlite') |
||
Line 18... | Line 19... | |||
18 | |
19 | |
|
19 | // load configuration file. |
20 | // load configuration file. |
|
Line 20... | Line 21... | |||
20 | let config = YAML.load('config.yml') |
21 | let config = YAML.load('config.yml') |
|
21 | |
22 | |
|
22 | // set up logger. |
23 | // set up logger. |
|
23 | const logger = createLogger({ |
24 | const logger = createLogger({ |
|
- | 25 | format: format.combine( |
||
- | 26 | format.timestamp({ |
||
24 | format: format.combine( |
27 | format: 'YYYYMMDDHHmmss' |
|
- | 28 | }), |
||
- | 29 | format.printf(info => |
||
25 | format.splat(), |
30 | `${info.timestamp} ${info.level}: ${info.message}`+(info.splat !== undefined?`${info.splat}`:" ") |
|
26 | format.simple() |
31 | ) |
|
27 | ), |
32 | ), |
|
28 | transports: [ |
33 | transports: [ |
|
29 | new transports.Console({ |
34 | new transports.Console({ |
|
Line 63... | Line 68... | |||
63 | }) |
68 | }) |
|
Line 64... | Line 69... | |||
64 | |
69 | |
|
Line 65... | Line 70... | |||
65 | const mqttClient = mqtt.connect(config.mqtt.connect) |
70 | const mqttClient = mqtt.connect(config.mqtt.connect) |
|
66 | |
71 | |
|
67 | mqttClient.on('reconnect', () => { |
72 | mqttClient.on('reconnect', () => { |
|
Line 68... | Line 73... | |||
68 | logger.info('Reconnecting to Corrade MQTT server...') |
73 | logger.info('Reconnecting to MQTT server...') |
|
69 | }) |
74 | }) |
|
70 | |
75 | |
|
71 | mqttClient.on('connect', () => { |
76 | mqttClient.on('connect', () => { |
|
72 | logger.info('Connected to Corrade MQTT server.') |
77 | logger.info('Connected to MQTT server.') |
|
73 | // Subscribe to group message notifications with group name and password. |
78 | // Subscribe to group message notifications with group name and password. |
|
74 | mqttClient.subscribe(`${config.mqtt.topic}`, (error) => { |
79 | mqttClient.subscribe(`${config.mqtt.topic}`, (error) => { |
|
75 | if (error) { |
80 | if (error) { |
|
Line 76... | Line 81... | |||
76 | logger.info('Error subscribing to Corrade MQTT group messages.') |
81 | logger.info('Error subscribing to MQTT server.') |
|
77 | return |
82 | return |
|
78 | } |
83 | } |
|
Line 79... | Line 84... | |||
79 | |
84 | |
|
80 | logger.info('Subscribed to Corrade MQTT group messages.') |
85 | logger.info('Subscribed to MQTT server.') |
|
81 | }) |
86 | }) |
|
Line 82... | Line 87... | |||
82 | }) |
87 | }) |
|
83 | |
88 | |
|
84 | mqttClient.on('close', () => { |
89 | mqttClient.on('close', () => { |
|
Line 85... | Line 90... | |||
85 | logger.error('Disconnected from Corrade MQTT server...') |
90 | logger.error('Disconnected from MQTT server.') |
|
86 | }) |
91 | }) |
|
Line 124... | Line 129... | |||
124 | // remove NULL and NETPLAY_CMD_NICK |
129 | // remove NULL and NETPLAY_CMD_NICK |
|
125 | netplay.nick = payload.toString().replace(/[\u0000\u0020]+/gi, '') |
130 | netplay.nick = payload.toString().replace(/[\u0000\u0020]+/gi, '') |
|
126 | netplay.hash = shortHash(`${netplay.nick}${netplay.ip}`) |
131 | netplay.hash = shortHash(`${netplay.nick}${netplay.ip}`) |
|
127 | netplay.time = new Date().toISOString() |
132 | netplay.time = new Date().toISOString() |
|
Line -... | Line 133... | |||
- | 133 | |
||
- | 134 | logger.info(`Player ${netplay.nick} joined via IP ${netplay.ip}`); |
||
- | 135 | |
||
- | 136 | const db = new sqlite.Database({ filename: config.db.file }, sqlite.OPEN_CREATE | sqlite.OPEN_READWRITE | sqlite.OPEN_FULLMUTEX, (error) => { |
||
- | 137 | if(error) { |
||
- | 138 | logger.error(`failed to open database ${config.db.file}`) |
||
- | 139 | return |
||
- | 140 | } |
||
- | 141 | |
||
- | 142 | db.run(`CREATE TABLE IF NOT EXISTS "players" ("nick" TEXT(15) NOT NULL, "ip" TEXT NOT NULL)`, (error, result) => { |
||
- | 143 | if(error) { |
||
- | 144 | logger.error(`could not create database table`); |
||
- | 145 | return |
||
- | 146 | } |
||
- | 147 | db.run(`INSERT INTO "players" ("nick", "ip") VALUES (:nick, :ip)`, { nick: netplay.nick, $ip: netplay.ip }, (error) => { |
||
- | 148 | if(error) { |
||
- | 149 | logger.error(`could not insert player and IP into database`) |
||
- | 150 | return |
||
- | 151 | } |
||
- | 152 | |
||
- | 153 | logger.info(`player added to database`) |
||
- | 154 | }) |
||
- | 155 | }) |
||
- | 156 | }) |
||
- | 157 | |
||
- | 158 | // send data to MQTT server |
||
- | 159 | const data = JSON.stringify(netplay, null, 4) |
||
- | 160 | mqttClient.publish(`${config.mqtt.topic}`, data) |
||
128 | |
161 | |
|
129 | // ban by nick. |
162 | // ban by nick. |
|
130 | if(nickBanSet.has(netplay.nick)) { |
163 | if(nickBanSet.has(netplay.nick)) { |
|
131 | logger.info(`nick found to be banned: ${netplay.nick}`) |
164 | logger.info(`nick found to be banned: ${netplay.nick}`) |
|
132 | exec(`/usr/sbin/iptables -t mangle -A PREROUTING -p tcp --src ${netplay.ip} --dport ${config.netplay.port} -j DROP`, (error, stdout, stderr) => { |
165 | exec(`iptables -t mangle -A PREROUTING -p tcp --src ${netplay.ip} --dport ${config.netplay.port} -j DROP`, (error, stdout, stderr) => { |
|
133 | if (error) { |
166 | if (error) { |
|
134 | logger.error(`Error returned while banning connecting client ${error.message}`) |
167 | logger.error(`Error returned while banning connecting client ${error.message}`) |
|
135 | return |
168 | return |
|
136 | } |
169 | } |
|
137 | if (stderr) { |
170 | if (stderr) { |
|
138 | logger.error(`Standard error returned ${stderr}`) |
171 | logger.error(`Standard error returned ${stderr}`) |
|
139 | return |
172 | return |
|
140 | } |
173 | } |
|
141 | if(stdout) { |
174 | if (stdout) { |
|
142 | logger.info(`Standard error reported while banning ${typeof stdout}`) |
175 | logger.info(`Standard error reported while banning ${typeof stdout}`) |
|
143 | return |
176 | return |
|
144 | } |
- | ||
145 | |
- | ||
146 | // only send notification if the connecting nick isn't banned |
- | ||
147 | const data = JSON.stringify(netplay, null, 4) |
- | ||
148 | mqttClient.publish(`${config.mqtt.topic}`, data) |
177 | } |
|
149 | }) |
178 | }) |
|
Line 150... | Line 179... | |||
150 | } |
179 | } |