Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**
- * Конфигурация
- */
- var config = {
- local: {
- host: '0.0.0.0',
- port: 1973
- },
- remote: {
- host: '123.123.123.123',
- port: 1973
- },
- realip: false, // Добавлять реальный ip-адрес к mac-адресу (true) или нет (false)
- }
- /**
- * Подгрузка необходимых модулей
- */
- var net = require('net');
- var log4js = require('log4js');
- /**
- * Логгер
- */
- log4js.configure({
- appenders: [
- { type: 'console' },
- { type: 'dateFile', filename: 'log/proxy.log', pattern: '-yyyy-MM-dd', category: '[PROXY]' }
- ]
- });
- var logger = log4js.getLogger('[PROXY]');
- /**
- * Вывод ошибок в консоль
- */
- process.on('uncaughtException', function(e) {
- logger.error(e.toString());
- });
- /**
- * Запуск сервера
- */
- var server = net.createServer(function (socket) {
- /**
- * Инициализируем объект клиента
- */
- var client = {
- addr: socket.remoteAddress,
- port: socket.remotePort,
- packets: {
- amount: {},
- speed: {},
- actions: {}
- },
- badscounter: 0
- }
- /**
- * Инициализируем соединение с GateServer-ом
- */
- var remote = new net.Socket();
- remote.connect(config.remote.port, config.remote.host);
- /**
- * Обрабатываем входящие пакеты
- */
- socket.on('data', function(data) {
- /**
- * Регистрируем таймеры
- */
- var MSEC = new Date().getTime(); // UNIXTIME в миллисекундах
- var FSEC = Math.round(MSEC / 1000); // UNIXTIME в секундах
- /**
- * Разбираем входящий пакет
- */
- var buf = new Buffer(data);
- var hex = buf.toString('hex');
- var info = getPacketInfo(hex);
- /**
- * Проверяем общую частоту передачи пакетов в сек
- */
- if(client.packets.amount[FSEC]) {
- client.packets.amount[FSEC] += 1;
- } else {
- client.packets.amount = {};
- client.packets.amount[FSEC] = 1;
- }
- if(client.packets.amount[FSEC] > 256) {
- return sendMessage(client, 'MANY_PACKETS', 'WARN');
- }
- /**
- * Проверяем объем передаваемых данных в сек
- */
- var packet_size = data.length;
- if(client.packets.speed[FSEC]) {
- client.packets.speed[FSEC] += packet_size;
- } else {
- client.packets.speed = {};
- client.packets.speed[FSEC] = packet_size;
- }
- if(client.packets.speed[FSEC] > 5120) {
- logger.info('PACKET_DUMP', info.body);
- if(client.badscounter >= 5) {
- return closeConnection(socket, remote, client, 'BIG_SPEED', 'ERROR');
- } else {
- client.badscounter += 1;
- return sendMessage(client, 'BIG_SPEED', 'WARN');
- }
- }
- switch(info.code) {
- /**
- * Пакет авторизации
- * xxxx xxxx 0051 8000 0000 01af 0007 6e6f .@V..Q........no
- * 6269 6c6c 0000 0661 646d 696e 0000 182b bill...admin...+
- * 58e2 83be 8c88 0197 b4b7 9c98 3fb7 6739 X...........?.g9
- * a48c c18b cd16 bb00 1830 302d 3235 2d32 .........00-25-2
- * 322d 4446 2d41 432d 3739 2d30 302d 3030 2-DF-AC-79-00-00
- * 0003 8f00 88
- */
- case 431:
- // Разбор пакета
- var shift = 34;
- var pkt = {
- lsize: parseInt(hex.substring(shift, shift + 4), 16) * 2 };
- shift += 4;
- pkt.login = hex2str(hex.substring(shift, shift + pkt.lsize - 2));
- shift += pkt.lsize ;
- pkt.psize = parseInt(hex.substring(shift, shift + 4), 16) * 2;
- shift += 4;
- pkt.passw = hex.substring(shift, shift + pkt.psize);
- shift += pkt.psize;
- pkt.msize = parseInt(hex.substring(shift, shift + 4), 16) * 2;
- shift += 4;
- pkt.mac = hex2str(hex.substring(shift, shift + pkt.msize - 2));
- client.login = pkt.login;
- client.mac = pkt.mac;
- // Проверка заявленных длин реальным
- if (pkt.psize !== 48 || pkt.msize !== 48 ||
- pkt.passw.length !== 48 || pkt.mac.length !== 23 || pkt.login.length > 20 ||
- pkt.lsize/2-1 !== pkt.login.length) {
- return closeConnection(socket, remote, client, 'INVALID_LOGIN_SIZES', 'ERROR');
- }
- // Проверка формата мак-адреса
- var re = /^([0-9A-Z]{2}-){7}[0-9A-Z]{2}$/; // 00-25-22-DF-AC-79-00-00
- if (!re.test(client.mac)) {
- return closeConnection(socket, remote, client, 'INVALID_MAC_FORMAT', 'ERROR');
- }
- // Проверка формата логина
- var re = /^[0-9a-zA-Z]{5,20}$/;
- if (!re.test(client.login)) {
- return closeConnection(socket, remote, client, 'INVALID_LOGIN_FORMAT', 'ERROR');
- }
- sendMessage(client, 'LOGIN');
- // Модифицируем пакет, добавляя к мак-адресу ip клиента
- if(config.realip) {
- var find = int2hex(pkt.msize / 2) + str2hex(client.mac);
- var replace = str2hex(';' + client.addr);
- var new_pkt = '8000000001af' +
- info.body.replace(new RegExp(find), int2hex((pkt.msize + replace.length) / 2) + find.substring(4) + replace);
- new_pkt = int2hex(new_pkt.length / 2 + 2) + new_pkt;
- data = new Buffer(new_pkt, 'hex');
- }
- remote.write(data);
- break;
- default:
- remote.write(data);
- break;
- }
- });
- socket.on('error', function (e) {
- remote.end();
- });
- remote.on('error', function (e) {
- logger.error(e.toString());
- socket.end();
- });
- remote.on('data', function(data) {
- socket.write(data);
- });
- socket.on('close', function(had_error) {
- remote.end();
- });
- remote.on('close', function(had_error) {
- socket.end();
- });
- }).listen(config.local.port, config.local.host, function(){
- logger.info('ProxyServer accepting connection on %s:%d', config.local.host, config.local.port);
- });
- /**
- * Возвращает базовую информацию о hex-пакете
- */
- /*function getPacketInfo(hex) {
- return {
- size: parseInt(hex.substring(0, 4), 16),
- signature: hex.substring(4, 12),
- code: parseInt(hex.substring(12, 16), 16),
- realsize: hex.length/2,
- body: hex.substring(16)
- }
- }*/
- /**
- * Возвращает базовую информацию о hex-пакете
- * Если содержится несколько логических пакетов, берем только первый
- */
- function getPacketInfo(hex) {
- var packet = {
- size: parseInt(hex.substring(0, 4), 16),
- signature: hex.substring(4, 12),
- code: parseInt(hex.substring(12, 16), 16)
- }
- packet.body = hex.substring(16,packet.size * 2);
- packet.realsize = packet.body.length / 2 + 8;
- return packet;
- }
- /**
- * Закрывает все соединения с сообщением в консоль
- */
- function closeConnection(socket, remote, client, message, level) {
- remote.end();
- socket.end();
- return sendMessage(client, message, level ? level : 'WARN');
- }
- /**
- * Логирует сообщения
- */
- function sendMessage(client, message, level) {
- switch (level) {
- case 'WARN':
- logger.warn(message, client.login, client.addr, client.port, client.mac);
- break;
- case 'ERROR':
- logger.error(message, client.login, client.addr, client.port, client.mac);
- break;
- default:
- logger.info(message, client.login, client.addr, client.port, client.mac);
- break;
- }
- return true;
- }
- /**
- * Конвертирует число в int32 hex
- */
- function int2hex(int) {
- return String('0000' + (int).toString(16)).slice(-4);
- }
- /**
- * Конвертирует hex-строку в utf
- */
- function hex2str(hex) {
- return new Buffer(hex, 'hex').toString();
- }
- /**
- * Конвертирует utf в hex-строку
- */
- function str2hex(str) {
- return new Buffer(str).toString('hex');
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement