q3rcon-bridge
Version:
Proxies rcon commands to servers with optional user:pass auth
75 lines (72 loc) • 2.6 kB
JavaScript
var udpnat = require('./udp-nat');
var util = require('util');
var events = require('events');
var trim = new RegExp("\"", 'g');
function arr_compare(arr1, arr2) {
if(arr1.length != arr2.length) {
return false;
}
for(i in arr1) {
if(arr1[i] != arr2[i]) {
return false;
}
}
return true;
}
var rconheader = [0xFF, 0xFF, 0xFF, 0xFF, "r".charCodeAt(0), "c".charCodeAt(0), "o".charCodeAt(0), "n".charCodeAt(0)];
var needsOptions = ["bindHost", "servers", "authLib"];
function rconproxy(options) {
for(i in needsOptions) {
if(!(needsOptions[i] in options)) {
throw new Error("Missing arguments for rconproxy: " + needsOptions[i]);
return;
}
}
var $proxy = this;
this.options = options;
this.authlib = options.authLib;
this.nat = udpnat.createServer(options, function(msg, sender, callback) {
if(arr_compare(rconheader, msg.slice(0, 8))) {
var str = msg.toString('utf8').substr(4).trim().replace(trim,"");
var parts = str.split(" ");
rawcmd = parts.shift();
password = parts.shift();
command = parts.join(" ").trim();
if(command.toLowerCase().indexOf("rcon_password") > -1) {
return callback(false);
}
if(rawcmd != "rcon") {
return callback(false);
}
var userServer = password.indexOf("/") > -1 ? password.split("/") : ["",""];
if(!(userServer[1] in $proxy.options.servers)) {
$proxy.emit("badserver", {ip: sender.address, port: sender.port}, userServer[1], command);
return callback(false);
}
var authuser = userServer[0].indexOf(":") > -1 ? userServer[0].split(":") : [userServer[0],""];
$proxy.authlib.auth(authuser[0], authuser[1], userServer[1], function(loggedIn) {
if(loggedIn) {
$proxy.emit("command", {user: authuser[0], ip: sender.address, port: sender.port}, userServer[1], command);
rcon_msg = [rawcmd, $proxy.options.servers[userServer[1]].password, command].join(" ");
var buf = new Buffer(4 + rcon_msg.length);
msg.copy(buf, 0, 0, 4);
buf.write(rcon_msg, 4, rcon_msg.length);
return callback(buf, $proxy.options.servers[userServer[1]]);
} else {
$proxy.emit("badauth", {user: authuser[0], ip: sender.address, port: sender.port}, userServer[1], command);
return callback(false);
}
});
} else {
return callback(false);
}
});
}
util.inherits(rconproxy, events.EventEmitter);
rconproxy.prototype.listen = function(port, host) {
this.nat.listen(port, host);
this.emit("listening");
}
exports.createServer = function(options) {
return new rconproxy(options);
}