-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.js
124 lines (109 loc) · 3.19 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
const { spawn } = require('child_process');
const axios = require('axios');
const os = require('os');
const yaml = require('js-yaml');
const fs = require('fs');
let config = null;
// load from yaml
try {
const configContent = fs.readFileSync('./config.yaml', 'utf8');
config = yaml.load(configContent);
console.log(config.onReady);
} catch (e) {
console.log(e);
}
// check if webhook is set
if (config, config.webhook == null) {
console.error('Could not get discord webhook, exiting..');
process.exit(1);
}
const discordWebhookUrl = '${config.webhook}';
const tail = spawn('journalctl', ['-f', '-n', '0', '_COMM=sshd']);
// embed
tail.stdout.on('data', async (data) => {
const logData = data.toString();
if (logData.includes('Accepted password') || logData.includes('Accepted publickey')) {
const ipAddressRegex = /\b(?:\d{1,3}\.){3}\d{1,3}\b/;
const ipAddressMatch = logData.match(ipAddressRegex);
const ipAddress = ipAddressMatch ? ipAddressMatch[0] : config.ipAddressUnknown;
const userInfo = parseUserInfo(logData);
const geoLocation = await getGeoLocation(ipAddress);
const embed = {
title: config.webhookTitle,
description: config.webhookDescription,
color: config.webhookColor,
timestamp: new Date(),
fields: [
{
name: config.userInfo,
value: userInfo.user,
inline: true,
},
{
name: config.ipAddress,
value: ipAddress,
inline: true,
},
{
name: config.serverAffected,
value: os.hostname(),
inline: true,
},
{
name: config.affectedServerOS,
value: `${os.type()} ${os.release()}`,
inline: true,
},
{
name: config.clientGeolocation,
value: geoLocation,
inline: true,
},
],
};
sendDiscordEmbed(embed);
}
});
// error codes
tail.stderr.on('data', (data) => {
console.error(`${config.journalctl}: ${data}`);
});
// error codes
tail.on('exit', (code) => {
console.log(`${config.journalctlExit} ${code}`);
});
// parsing
function parseUserInfo(logData) {
const userRegex = /(?:for )?([^\s]+) from/;
const deviceRegex = /(?:via )?([^\s]+) port/;
const userMatch = logData.match(userRegex);
const deviceMatch = logData.match(deviceRegex);
const user = userMatch ? userMatch[1] : config.unknownUser;
const device = deviceMatch ? deviceMatch[1] : config.unknownDevice;
return {
user,
device,
};
}
// get geolocation for client
async function getGeoLocation(ipAddress) {
try {
const response = await axios.get(`https://ipinfo.io/${ipAddress}/json`);
const geoLocation = `${response.data.city}, ${response.data.region}, ${response.data.country}`;
return geoLocation;
} catch (error) {
console.error(config.geolocationFail, error.message);
return config.unknown;
}
}
// send json data to webhook
function sendDiscordEmbed(embed) {
const data = {
content: config.ping,
embeds: [embed],
};
// send post request
axios.post(discordWebhookUrl, data)
.then(() => console.log(config.embedSent))
.catch((error) => console.error(config.embedError, error.message));
}