[mirotalksfu] - improve host protection
هذا الالتزام موجود في:
15
app/src/Host.js
Normal file
15
app/src/Host.js
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const Logger = require('./Logger');
|
||||||
|
const log = new Logger('Host');
|
||||||
|
|
||||||
|
module.exports = class Host {
|
||||||
|
constructor(ip, authorized) {
|
||||||
|
this.auth = new Map();
|
||||||
|
this.auth.set(ip, authorized);
|
||||||
|
//log.debug('AUTH ---> ', this.auth.get(ip));
|
||||||
|
}
|
||||||
|
isAuthorized(ip) {
|
||||||
|
return this.auth.has(ip);
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -9,6 +9,7 @@ const config = require('./config');
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
const ngrok = require('ngrok');
|
const ngrok = require('ngrok');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
const Host = require('./Host');
|
||||||
const Room = require('./Room');
|
const Room = require('./Room');
|
||||||
const Peer = require('./Peer');
|
const Peer = require('./Peer');
|
||||||
const ServerApi = require('./ServerApi');
|
const ServerApi = require('./ServerApi');
|
||||||
@@ -42,6 +43,9 @@ const hostCfg = {
|
|||||||
const apiBasePath = '/api/v1'; // api endpoint path
|
const apiBasePath = '/api/v1'; // api endpoint path
|
||||||
const api_docs = host + apiBasePath + '/docs'; // api docs
|
const api_docs = host + apiBasePath + '/docs'; // api docs
|
||||||
|
|
||||||
|
// Authenticated IP by Login
|
||||||
|
let authHost;
|
||||||
|
|
||||||
// all mediasoup workers
|
// all mediasoup workers
|
||||||
let workers = [];
|
let workers = [];
|
||||||
let nextMediasoupWorkerIdx = 0;
|
let nextMediasoupWorkerIdx = 0;
|
||||||
@@ -49,9 +53,25 @@ let nextMediasoupWorkerIdx = 0;
|
|||||||
// all Room lists
|
// all Room lists
|
||||||
let roomList = new Map();
|
let roomList = new Map();
|
||||||
|
|
||||||
|
// directory
|
||||||
|
const dir = {
|
||||||
|
public: path.join(__dirname, '../../', 'public'),
|
||||||
|
};
|
||||||
|
|
||||||
|
// html views
|
||||||
|
const view = {
|
||||||
|
landing: path.join(__dirname, '../../', 'public/view/landing.html'),
|
||||||
|
login: path.join(__dirname, '../../', 'public/view/login.html'),
|
||||||
|
newRoom: path.join(__dirname, '../../', 'public/view/newroom.html'),
|
||||||
|
notFound: path.join(__dirname, '../../', 'public/view/404.html'),
|
||||||
|
permission: path.join(__dirname, '../../', 'public/view/permission.html'),
|
||||||
|
privacy: path.join(__dirname, '../../', 'public/view/privacy.html'),
|
||||||
|
room: path.join(__dirname, '../../', 'public/view/Room.html'),
|
||||||
|
};
|
||||||
|
|
||||||
app.use(cors());
|
app.use(cors());
|
||||||
app.use(compression());
|
app.use(compression());
|
||||||
app.use(express.static(path.join(__dirname, '../../', 'public')));
|
app.use(express.static(dir.public));
|
||||||
|
|
||||||
// Remove trailing slashes in url handle bad requests
|
// Remove trailing slashes in url handle bad requests
|
||||||
app.use((err, req, res, next) => {
|
app.use((err, req, res, next) => {
|
||||||
@@ -74,44 +94,45 @@ app.use((err, req, res, next) => {
|
|||||||
// all start from here
|
// all start from here
|
||||||
app.get(['/'], (req, res) => {
|
app.get(['/'], (req, res) => {
|
||||||
if (hostCfg.protected == true) {
|
if (hostCfg.protected == true) {
|
||||||
res.sendFile(path.join(__dirname, '../../', 'public/view/login.html'));
|
hostCfg.authenticated = false;
|
||||||
|
res.sendFile(view.login);
|
||||||
} else {
|
} else {
|
||||||
res.sendFile(path.join(__dirname, '../../', 'public/view/landing.html'));
|
res.sendFile(view.landing);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// handle login on host protected
|
// handle login on host protected
|
||||||
app.get(['/login'], (req, res) => {
|
app.get(['/login'], (req, res) => {
|
||||||
let ip = req.headers['x-forwarded-for'] || req.socket.remoteAddress;
|
let ip = getIP(req);
|
||||||
log.debug(`request login to host from: ${ip}`, req.query);
|
log.debug(`request login to host from: ${ip}`, req.query);
|
||||||
if (req.query.username == hostCfg.username && req.query.password == hostCfg.password) {
|
if (req.query.username == hostCfg.username && req.query.password == hostCfg.password) {
|
||||||
hostCfg.authenticated = true;
|
hostCfg.authenticated = true;
|
||||||
res.sendFile(path.join(__dirname, '../../', 'public/view/landing.html'));
|
authHost = new Host(ip, true);
|
||||||
|
log.debug('LOGIN OK', { ip: ip, authorized: authHost.isAuthorized(ip) });
|
||||||
|
res.sendFile(view.landing);
|
||||||
} else {
|
} else {
|
||||||
res.sendFile(path.join(__dirname, '../../', 'public/view/login.html'));
|
log.debug('LOGIN KO', { ip: ip, authorized: false });
|
||||||
|
hostCfg.authenticated = false;
|
||||||
|
res.sendFile(view.login);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// set new room name and join
|
// set new room name and join
|
||||||
app.get(['/newroom'], (req, res) => {
|
app.get(['/newroom'], (req, res) => {
|
||||||
|
let ip = getIP(req);
|
||||||
if (hostCfg.protected == true) {
|
if (hostCfg.protected == true) {
|
||||||
res.sendFile(path.join(__dirname, '../../', 'public/view/login.html'));
|
if (allowedIP(ip)) {
|
||||||
|
res.sendFile(view.newRoom);
|
||||||
|
} else {
|
||||||
|
hostCfg.authenticated = false;
|
||||||
|
res.sendFile(view.login);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
res.sendFile(path.join(__dirname, '../../', 'public/view/newroom.html'));
|
res.sendFile(view.newRoom);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// if not allow video/audio
|
// no room name specified to join || direct join
|
||||||
app.get(['/permission'], (req, res) => {
|
|
||||||
res.sendFile(path.join(__dirname, '../../', 'public/view/permission.html'));
|
|
||||||
});
|
|
||||||
|
|
||||||
// privacy policy
|
|
||||||
app.get(['/privacy'], (req, res) => {
|
|
||||||
res.sendFile(path.join(__dirname, '../../', 'public/view/privacy.html'));
|
|
||||||
});
|
|
||||||
|
|
||||||
// no room name specified to join
|
|
||||||
app.get('/join/', (req, res) => {
|
app.get('/join/', (req, res) => {
|
||||||
if (hostCfg.authenticated && Object.keys(req.query).length > 0) {
|
if (hostCfg.authenticated && Object.keys(req.query).length > 0) {
|
||||||
log.debug('Direct Join', req.query);
|
log.debug('Direct Join', req.query);
|
||||||
@@ -122,8 +143,7 @@ app.get('/join/', (req, res) => {
|
|||||||
let peerVideo = req.query.video;
|
let peerVideo = req.query.video;
|
||||||
let notify = req.query.notify;
|
let notify = req.query.notify;
|
||||||
if (roomName && peerName && peerAudio && peerVideo && notify) {
|
if (roomName && peerName && peerAudio && peerVideo && notify) {
|
||||||
res.sendFile(path.join(__dirname, '../../', 'public/view/Room.html'));
|
return res.sendFile(view.room);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
res.redirect('/');
|
res.redirect('/');
|
||||||
@@ -136,13 +156,28 @@ app.get('/join/*', (req, res) => {
|
|||||||
log.debug('redirect:' + req.url + ' to ' + url.parse(req.url).pathname);
|
log.debug('redirect:' + req.url + ' to ' + url.parse(req.url).pathname);
|
||||||
res.redirect(url.parse(req.url).pathname);
|
res.redirect(url.parse(req.url).pathname);
|
||||||
} else {
|
} else {
|
||||||
res.sendFile(path.join(__dirname, '../../', 'public/view/Room.html'));
|
res.sendFile(view.room);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
res.sendFile(path.join(__dirname, '../../', 'public/view/login.html'));
|
res.redirect('/');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// if not allow video/audio
|
||||||
|
app.get(['/permission'], (req, res) => {
|
||||||
|
res.sendFile(view.permission);
|
||||||
|
});
|
||||||
|
|
||||||
|
// privacy policy
|
||||||
|
app.get(['/privacy'], (req, res) => {
|
||||||
|
res.sendFile(view.privacy);
|
||||||
|
});
|
||||||
|
|
||||||
|
// not match any of page before, so 404 not found
|
||||||
|
app.get('*', function (req, res) {
|
||||||
|
res.sendFile(view.notFound);
|
||||||
|
});
|
||||||
|
|
||||||
// ####################################################
|
// ####################################################
|
||||||
// API
|
// API
|
||||||
// ####################################################
|
// ####################################################
|
||||||
@@ -203,11 +238,6 @@ app.post(['/api/v1/join'], (req, res) => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// not match any of page before, so 404 not found
|
|
||||||
app.get('*', function (req, res) {
|
|
||||||
res.sendFile(path.join(__dirname, '../../', 'public/view/404.html'));
|
|
||||||
});
|
|
||||||
|
|
||||||
// ####################################################
|
// ####################################################
|
||||||
// NGROK
|
// NGROK
|
||||||
// ####################################################
|
// ####################################################
|
||||||
@@ -624,3 +654,10 @@ io.on('connection', (socket) => {
|
|||||||
return Math.round(bytes / Math.pow(1024, i), 2) + ' ' + sizes[i];
|
return Math.round(bytes / Math.pow(1024, i), 2) + ' ' + sizes[i];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function getIP(req) {
|
||||||
|
return req.headers['x-forwarded-for'] || req.socket.remoteAddress;
|
||||||
|
}
|
||||||
|
function allowedIP(ip) {
|
||||||
|
return authHost != null && authHost.isAuthorized(ip);
|
||||||
|
}
|
||||||
|
|||||||
المرجع في مشكلة جديدة
حظر مستخدم