// turnserverauth.js // writted by Benoit LORAND // // webservice who deliver in JSON format turnserver ephemere credentials // Should be behind a reverse proxy (Apache, Nginx, haproxy) who do basic authentication // "use strict"; const http = require('http'); const hmacsha1 = require('hmacsha1'); const url = require('url'); const port = Number(process.env.NODE_PORT); const listenip = process.env.NODE_LISTEN_IP; const secret = process.env.SECRET; const auth_required = process.env.AUTH_REQUIRED; const ttl = Number(process.env.TTL); const turnserver = process.env.TURN_SERVER; //'turn.blorand.org'; const turn_ports = process.env.TURN_PORTS.split(' '); //['3478', '3479']; const turn_ports_tls = process.env.TURNS_PORTS.split(' '); //['5349', '5350']; function foundhttpusername() { } function onRequest(request, response) { if (request.headers['x-forwarded-for'] == undefined) { var IP = request.connection.remoteAddress; } else { var IP = request.headers['x-forwarded-for']; } if (((!request.headers['x-forwarded-user']) || request.headers['x-forwarded-user'].indexOf('Basic ') === -1) && !request.headers['x-remote-user'] && ((!request.headers['authorization']) || request.headers['authorization'].indexOf('Basic ') === -1)){ if ( auth_required == 'yes' ) { console.log('Missing Authenticated-user from : ' + IP + ' - REFUSED'); response.statusCode = 401; response.end(); return; } console.log('Missing Authenticated-user from : ' + IP); } Array.prototype.forEach.call(['x-forwarded-user', 'authorization'], authheader => { if (request.headers[authheader] || (!request.headers[authheader] == 'undefined' && !request.headers[authheader].indexOf('Basic ') === -1)){ const base64Credentials = request.headers[authheader].split(' ')[1]; const credentials = Buffer.from(base64Credentials, 'base64').toString('ascii'); var [username, password] = credentials.split(':'); } httpusername = username; }); if (request.headers['x-remote-user']) { var httpusername = request.headers['x-remote-user'] } const queryObject = JSON.stringify(url.parse(request.url,true).query); const getparameters = JSON.parse(queryObject); var timestamp = Date.now() / 1000 | 0; var expiry = (timestamp + ttl).toString(10); var turnusername = expiry + ':' + httpusername; var username_sha1 = hmacsha1(secret, turnusername); var turnpassword = username_sha1; var uris = []; if (!(getparameters.tls === "1")) { uris.push('turn:' + turnserver + ':' + turn_ports[0] + '?transport=udp'); uris.push('turn:' + turnserver + ':' + turn_ports[1] + '?transport=tcp'); } var transport = 'tcp'; Array.prototype.forEach.call(turn_ports_tls, turn_port_tls => { uris.push('turns:' + turnserver + ':' + turn_port_tls + '?transport=' + transport); }); const data = JSON.stringify( { username: turnusername, password: turnpassword, ttl: ttl, uris: uris } ) console.log('turnauthserver : Requête reçue de : ' + IP + ' by : ' + httpusername); response.statusCode = 200; response.setHeader('Content-Type', 'application/json'); response.write(data); response.end(); } http.createServer(onRequest).listen(port, listenip); console.log(`turnauthserver running at http://${listenip}:${port}/`);