Started work on dynamic authentication for TURN servers

This commit is contained in:
rainbow napkin 2026-10-08 18:55:45 -04:00
parent b5bec9da50
commit a11fec6240
3 changed files with 74 additions and 11 deletions

View file

@ -34,11 +34,18 @@
"address": "toke@42069.weed", "address": "toke@42069.weed",
"pass": "CHANGE_ME" "pass": "CHANGE_ME"
}, },
"iceServers":[ "iceServers":{
{ "ttl":12,
"urls":["stun:stun.moonlight-stream.org:3478"] "stun":[
} ["stun:telstar.ourfore.st:3478"]
], ],
"turn":[
{
"urls": ["turns:telstar.ourfore.st:5349"],
"secret": "SHAREDSECRET"
}
]
},
"links":{ "links":{
"About": "/about", "About": "/about",
"Code": "https://git.ourfore.st/rainbownapkin/canopy", "Code": "https://git.ourfore.st/rainbownapkin/canopy",

View file

@ -66,11 +66,21 @@
"pass": "CHANGE_ME" "pass": "CHANGE_ME"
}, },
//Privdes STUN/TURN servers for WebRTC functionality //Privdes STUN/TURN servers for WebRTC functionality
"iceServers":[ "iceServers":{
{ //Time to live for TURN credentials (in hours)
"urls":["stun:stun.moonlight-stream.org:3478"] "ttl":12,
} //array of urls for each stun server
], "stun":[
["stun:telstar.ourfore.st:3478"]
],
//Array of objects containing urls and shared secret of a turn server
"turn":[
{
"urls": ["turns:telstar.ourfore.st:5349"],
"secret": "SHAREDSECRET"
}
]
},
//Provides customizable links for navbar //Provides customizable links for navbar
"links":{ "links":{
"About": "/about", "About": "/about",

View file

@ -14,6 +14,9 @@ GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.*/ along with this program. If not, see <https://www.gnu.org/licenses/>.*/
//Node imports
const crypto = require('crypto');
//NPM imports //NPM imports
const validator = require('validator'); const validator = require('validator');
const mongoose = require('mongoose'); const mongoose = require('mongoose');
@ -340,7 +343,7 @@ class queue{
let title = "Livestream"; let title = "Livestream";
let filename = '/'; let filename = '/';
let streamURL = '/'; let streamURL = '/';
let rawLink = {combo: [['default', config.iceServers]]}; let rawLink = {};
if(data != null && data.title != null){ if(data != null && data.title != null){
//If the title is too long //If the title is too long
@ -411,9 +414,13 @@ class queue{
filename = filename[1]; filename = filename[1];
} }
//Set rawlink to hls url
rawLink = {combo:[['default',streamURL]]}; rawLink = {combo:[['default',streamURL]]};
//Otherwise if we're starting a web RTC Stream //Otherwise if we're starting a web RTC Stream
}else if(chanDB.settings.streamType == "webrtc"){ }else if(chanDB.settings.streamType == "webrtc"){
//Set rawlink as iceServers
rawLink = {combo: [['default', this.prepIceConfig()]]};
//Let our webRTCHandler know //Let our webRTCHandler know
this.channel.webRTCHandler.startStream(socket); this.channel.webRTCHandler.startStream(socket);
} }
@ -443,6 +450,45 @@ class queue{
} }
} }
prepIceConfig(){
//Create array to hold ice servers
let iceServers = [];
//for each stun server listed in the config
for(let server of config.iceServers.stun){
//push the stun server into our array
iceServers.push({
urls: server
});
}
//Run thorugh TURN servers to dynamically generate temporary channel-specific credentials
for(let server of config.iceServers.turn){
//Get current time as JS epoch (millis) and convert to unix notation (seconds), then multiply config-specified ttl to convert hours to seconds, storing sum as the credential expiration epoch
const expiration = Math.floor(Date.now() / 1000) + (config.iceServers.ttl * 3600);
//Slap together username from ttl timestamp, and channel name (for session limiting purposes)
const user = `${expiration}:${this.channel.name}`
//sha1 seems like a silly/outdated choice but considering some of the other shit coturn devs have been up to mediocrity doesnt surprise me
//Seriously, to watch a deeply important puzzle piece of modern infrastructure get TURNed into LLM-Slop is just depressing
//At least I get to make puns about it
//Create token from server shared secret and username
const token = crypto.createHmac('sha1', `${server.secret}${user}`);
//Hash token string and save it in base64
const hash = token.digest('base64');
iceServers.push({
urls: server.urls,
username: user,
credential: hash
})
}
return iceServers;
}
/** /**
* Returns current channel stream type upon request * Returns current channel stream type upon request
* @param {Socket} socket - Socket we received the request from * @param {Socket} socket - Socket we received the request from