Skip to content

Commit

Permalink
Added support for Crowdsec, an open-source and collaborative IPS (Int…
Browse files Browse the repository at this point in the history
…rusion Prevention System)
  • Loading branch information
Ylianst committed Jul 7, 2022
1 parent 79d32b6 commit 947d909
Show file tree
Hide file tree
Showing 7 changed files with 46 additions and 7 deletions.
12 changes: 11 additions & 1 deletion meshcentral-config-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@
"agentBlockedIP": { "type": [ "string", "array" ], "default": null, "description": "When set, agents from these denied IP address ranges will not be able to connect to the server. Example: \"192.168.2.100,192.168.1.0/24\"" },
"authLog": { "type": "string", "default": null, "description": "File path and name of the authentication log to be created. This log can be parsed by Fail2ban." },
"InterUserMessaging": { "type": "array", "uniqueItems": true, "items": { "type": "string" }, "description": "Users in this list are allowed to send and receive inter-user messages. This can be used to implement bots or other software where MeshCentral is used as data transport. See \"interuser\" websocket command in the code." },
"manageAllDeviceGroups": { "type": "array", "uniqueItems": true, "items": { "type": "string" }, "description": "Users in this list are allowed to see and manage all device groups within their domain." },
"manageAllDeviceGroups": { "type": "array", "uniqueItems": true, "items": { "type": " string" }, "description": "Users in this list are allowed to see and manage all device groups within their domain." },
"manageCrossDomain": { "type": "array", "uniqueItems": true, "items": { "type": "string" }, "description": "Users in this list are allowed to manage all users in all domains." },
"localDiscovery": {
"type": "object",
Expand Down Expand Up @@ -195,6 +195,16 @@
},
"required": [ "iceServers" ]
},
"crowdsec": {
"type": "object",
"additionalProperties": true,
"description": "Enabled the MeshCentral built-in Crowdsec bouncer. This section is passed directly to the bouncer, all of the settings are documented at https://www.npmjs.com/package/@crowdsec/express-bouncer",
"properties": {
"url": { "type": "string", "description": "The URL of your LAPI instance. Ex: http://localhost:8080" },
"apiKey": { "type": "string", "description": "The bouncer key (generated via cscli)" }
},
"required": [ "url", "apiKey" ]
},
"autoBackup": {
"type": "object",
"properties": {
Expand Down
15 changes: 11 additions & 4 deletions meshcentral.js
Original file line number Diff line number Diff line change
Expand Up @@ -698,7 +698,7 @@ function CreateMeshCentralServer(config, args) {
obj.args = args = config2.settings;

// Lower case all keys in the config file
obj.common.objKeysToLower(config2, ['ldapoptions', 'defaultuserwebstate', 'forceduserwebstate', 'httpheaders']);
obj.common.objKeysToLower(config2, ['ldapoptions', 'defaultuserwebstate', 'forceduserwebstate', 'httpheaders', 'crowdsec']);

// Grad some of the values from the original config.json file if present.
if ((config.settings.vault != null) && (config2.settings != null)) { config2.settings.vault = config.settings.vault; }
Expand Down Expand Up @@ -1196,7 +1196,7 @@ function CreateMeshCentralServer(config, args) {
for (i in args) { config2.settings[i] = args[i]; }

// Lower case all keys in the config file
common.objKeysToLower(config2, ['ldapoptions', 'defaultuserwebstate', 'forceduserwebstate', 'httpheaders']);
common.objKeysToLower(config2, ['ldapoptions', 'defaultuserwebstate', 'forceduserwebstate', 'httpheaders', 'crowdsec']);

// Grad some of the values from the original config.json file if present.
config2['mysql'] = config['mysql'];
Expand All @@ -1219,7 +1219,7 @@ function CreateMeshCentralServer(config, args) {
};

// Time to start the server of real.
obj.StartEx1b = function () {
obj.StartEx1b = async function () {
var i;

// Setup certificate operations
Expand All @@ -1232,6 +1232,12 @@ function CreateMeshCentralServer(config, args) {
})
}

// Start CrowdSec bouncer if needed: https://www.crowdsec.net/
if (typeof obj.args.crowdsec == 'object') {
const expressCrowdsecBouncer = require("@crowdsec/express-bouncer");
try { obj.crowdsecMiddleware = await expressCrowdsecBouncer(obj.args.crowdsec); } catch (ex) { delete obj.crowdsecMiddleware; }
}

// Check if self update is allowed. If running as a Windows service, self-update is not possible.
if (obj.fs.existsSync(obj.path.join(__dirname, 'daemon'))) { obj.serverSelfWriteAllowed = false; }

Expand Down Expand Up @@ -3515,7 +3521,7 @@ function getConfig(createSampleConfig) {

// Lower case all keys in the config file
try {
require('./common.js').objKeysToLower(config, ['ldapoptions', 'defaultuserwebstate', 'forceduserwebstate', 'httpheaders']);
require('./common.js').objKeysToLower(config, ['ldapoptions', 'defaultuserwebstate', 'forceduserwebstate', 'httpheaders', 'crowdsec']);
} catch (ex) {
console.log('CRITICAL ERROR: Unable to access the file \"./common.js\".\r\nCheck folder & file permissions.');
process.exit();
Expand Down Expand Up @@ -3713,6 +3719,7 @@ function mainStart() {
if (nodemailer || (config.smtp != null) || (config.sendmail != null)) { modules.push('nodemailer'); } // Add SMTP support
if (sendgrid || (config.sendgrid != null)) { modules.push('@sendgrid/mail'); } // Add SendGrid support
if (args.translate) { modules.push('jsdom'); modules.push('esprima'); modules.push('minify-js'); modules.push('html-minifier'); } // Translation support
if (typeof config.settings.crowdsec == 'object') { modules.push('@crowdsec/express-bouncer'); } // Add CrowdSec bounser module (https://www.npmjs.com/package/@crowdsec/express-bouncer)

// Setup encrypted zip support if needed
if (config.settings.autobackup && config.settings.autobackup.zippassword) {
Expand Down
14 changes: 12 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@
"sample-config-advanced.json"
],
"dependencies": {
"@crowdsec/express-bouncer": "^0.1.0",
"@yetzt/nedb": "^1.8.0",
"archiver": "^5.3.1",
"body-parser": "^1.19.0",
"cbor": "~5.2.0",
Expand All @@ -45,13 +47,21 @@
"express": "^4.17.0",
"express-handlebars": "^5.3.5",
"express-ws": "^4.0.0",
"image-size": "^1.0.1",
"ipcheck": "^0.1.0",
"loadavg-windows": "^1.1.1",
"minimist": "^1.2.5",
"multiparty": "^4.2.1",
"@yetzt/nedb": "^1.8.0",
"node-forge": "^1.0.0",
"node-windows": "^0.1.4",
"otplib": "^10.2.3",
"pg": "^8.7.1",
"pgtools": "^0.3.2",
"ssh2": "^1.11.0",
"web-push": "^3.5.0",
"ws": "^5.2.3",
"yauzl": "^2.10.0"
"yauzl": "^2.10.0",
"yubikeyotp": "^0.2.0"
},
"engines": {
"node": ">=10.0.0"
Expand Down
3 changes: 3 additions & 0 deletions redirserver.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ module.exports.CreateRedirServer = function (parent, db, args, func) {
res.redirect('https://' + host + ':' + httpsPort + req.url);
}

// Setup CrowdSec bouncer middleware if needed
if (parent.crowdsecMiddleware != null) { obj.app.use(parent.crowdsecMiddleware); }

/*
// Return the current domain of the request
function getDomain(req) {
Expand Down
4 changes: 4 additions & 0 deletions sample-config-advanced.json
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,10 @@
"trustedFqdn": "sample.com",
"ip": "192.168.1.1"
},
"_crowdsec": {
"url": "http://localhost:8080",
"apiKey": "BOUNCER_API_KEY"
},
"_plugins": { "enabled": true }
},
"_domaindefaults": {
Expand Down
3 changes: 3 additions & 0 deletions webrelayserver.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ module.exports.CreateWebRelayServer = function (parent, db, args, certificates,
var tlsSessionStoreCount = 0; // Number of cached TLS session information in store.

function serverStart() {
// Setup CrowdSec bouncer middleware if needed
if (parent.crowdsecMiddleware != null) { obj.app.use(parent.crowdsecMiddleware); }

if (args.trustedproxy) {
// Reverse proxy should add the "X-Forwarded-*" headers
try {
Expand Down
2 changes: 2 additions & 0 deletions webserver.js
Original file line number Diff line number Diff line change
Expand Up @@ -5706,9 +5706,11 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
obj.tlsAltServer.on('resumeSession', function (id, cb) { cb(null, tlsSessionStore[id.toString('hex')] || null); });
obj.expressWsAlt = require('express-ws')(obj.agentapp, obj.tlsAltServer, { wsOptions: { perMessageDeflate: (args.wscompression === true) } });
}
if (parent.crowdsecMiddleware != null) { obj.agentapp.use(parent.crowdsecMiddleware); } // Setup CrowdSec bouncer middleware if needed
}

// Setup middleware
if (parent.crowdsecMiddleware != null) { obj.app.use(parent.crowdsecMiddleware); } // Setup CrowdSec bouncer middleware if needed
obj.app.engine('handlebars', obj.exphbs({ defaultLayout: false }));
obj.app.set('view engine', 'handlebars');
if (obj.args.trustedproxy) {
Expand Down

1 comment on commit 947d909

@rallisf1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please make a video guide for the integration, cheers!

Please sign in to comment.