Serverquery login protection

Najsr

Moderator
TeamSpeak Developer
Apr 23, 2016
483
249
167
Hello,
is there any way to protect serveradmin login? I mean by allowing only certain IPs to be able to use it (localhost etc...) It would be very useful to protect everyone's server :)
 

techgolem

Member
Jan 12, 2016
38
12
50
Why would it be useful? Simply use a secure password and everything should be fine.

AFAIK it's not possible.
 

Najsr

Moderator
TeamSpeak Developer
Apr 23, 2016
483
249
167
Maybe somehow via ip tables? I think it would be possible.
 

Derp

Retired Staff
Contributor
Apr 30, 2015
933
1,017
217
There's this great thing people always fucking ignore, for some reason.....

It's called... (teamspeak server directory)/doc/serverquery/serverquery.html
(in your case serveruqery.html#how_to_use_the_blacklist)

....*MAGIC*
 

Kleberstoff

Knowledge Seeker
VIP
Dec 29, 2015
308
214
158
Why would it be useful? Simply use a secure password and everything should be fine.

AFAIK it's not possible.
Do some research before you say it's impossible. That said..

Do:
Code:
iptables -A INPUT -p tcp --dport 10011 -j DROP
iptables -A INPUT -p tcp --dport 10011 -s 127.0.0.1 -j ACCEPT
And it'll drop all connection that are not from localhost. You can also set a subnet or any other IP.

or use that what derp mentioned, also works and is way easier.
 
Last edited:

Najsr

Moderator
TeamSpeak Developer
Apr 23, 2016
483
249
167
I explained it wrong, I am sorry... I just wanted to protect serverquery login since it's the only one who can manage everything.
 

Kleberstoff

Knowledge Seeker
VIP
Dec 29, 2015
308
214
158
I explained it wrong, I am sorry... I just wanted to protect serverquery login since it's the only one who can manage everything.

You still didn't make yourself every Clear. Try to explain yourself a bit more. What kinda of Protection, and against What?
 

Najsr

Moderator
TeamSpeak Developer
Apr 23, 2016
483
249
167
Restrict "serveradmin" (server query account) to some IPs only.
 

Najsr

Moderator
TeamSpeak Developer
Apr 23, 2016
483
249
167
Ok ok
For multiple ips it would be like this?
Code:
iptables -A INPUT -p tcp --dport 10011 -s 127.0.0.1,1.2.3.4,1.3.4.0/24 -j ACCEPT
 

Kleberstoff

Knowledge Seeker
VIP
Dec 29, 2015
308
214
158
Ok ok
For multiple ips it would be like this?
Code:
iptables -A INPUT -p tcp --dport 10011 -s 127.0.0.1,1.2.3.4,1.3.4.0/24 -j ACCEPT

I'm not sure, i never really used IPtables, might try around or just google it.
 

Vivorma

New Member
Dec 24, 2016
4
2
15
Ok ok
For multiple ips it would be like this?
Code:
iptables -A INPUT -p tcp --dport 10011 -s 127.0.0.1,1.2.3.4,1.3.4.0/24 -j ACCEPT

[*]

Code:
iptables -A INPUT -p tcp --dport 10011 -j DROP
iptables -I INPUT -s 127.0.0.1 -p tcp --dport 10011 -j ACCEPT
iptables -I INPUT -s yourip -p tcp --dport 10011 -j ACCEPT
iptables -I INPUT -s CIRD -p tcp --dport 10011 -j ACCEPT
 

DifferentUser

Member
Feb 19, 2016
53
23
58
Here a little NodeJS Script which acts like a man in the middle tool for your Query, it is capable of logging every command and whitelisting the login system
So instead of creating a connection to the TeamSpeak Query, you connect to this ts3query Application which basically redirects all traffic to the TeamSpeak Server with some validation and logging in between

You will need to install NodeJS on your System
This Script has been tested on NodeJS v7.2.0 probably runs on v6 too
Copy the content save it to a file (for example /root/ts3query.js) and execute it with "node /root/ts3query.js"

HTML:
/*     Original Creator multivitamin.WTF
 *    Designed as "Man in the Middle" TeamSpeak Query Protection
 *  You maybe want to add the IP of the Server which executes this Script to the query_whitelist.txt
*/

const OPTIONS = {
  "teamspeak": ["10.10.12.106", 10011],                      //TeamSpeak IP + Query Port
  "listenPort": 10011,                                       //Listen Port for this App -> the Port which the Application listens to for new connections
  "logging": {
    "logfile": "/var/log/ts3_query.log",               //false for no file logging
    "censor_passwords": true                           //Password will be replaced to ___CENSORED___ in log
  },
  "login": [                                                 //Here you can define multiple States for "login" catches
    {
      "user": "serveradmin",                     //Login User Name
      "filter": "IP",                            //Filter Allowed Methods (DENY, IP)
      "ips": ["127.0.0.1", "localhost", "::1"]   //List with allowed IP Addresses
    },
    {
      "user": "*",                               //Appends on !!ALL!! Users
      "filter": "DENY"                           //Denies Login to all Users
    }
  ],
}


//At this Point no need to edit stuff
const net = require("net")
const fs = require("fs")


class Logger {
  constructor(logfile = false, censorpasswords = true) {
    this.out = logfile
    this.censorpasswords = censorpasswords
  }
  log(prefix, str) {
    if (!str.match(/[\w]/)) return
    if (this.censorpasswords) {
      let login = str.match(/login[ ]{1,}(client_login_name=([\w]{1,})|([\w]{1,})) (client_login_password=([\w]{1,})|([\w]{1,}))/)
      if (login) str = str.replace((login[5]) ? login[5] : login[6], "___CENSORED___")
    }
    var msg = "["+new Date().toISOString()+"]["+prefix+"] "+str.replace("\n","")
    console.log(msg)
    if (this.out === false) return
    fs.appendFile(this.out, msg+"\n", (err) => {
      if (err) throw err
    })
  }
}


const LOGGER = new Logger(OPTIONS.logging.logfile, OPTIONS.logging.censorpasswords)

function allowLogin (ip, username) {
  var verify = (obj) => {
    if (obj.filter.toUpperCase() === "DENY") return false
    return (obj.filter.toUpperCase() === "IP" && obj.ips.indexOf(ip) >= 0)
  }
  for (var k in OPTIONS.login) {
    let object = OPTIONS.login[k]
    if (object.user === "*") star = object
    if (object.user !== "*" && object.user == username) return verify(object)
  }
  if (typeof star === "object") return verify(star)
  return true
}

net.createServer((socket) => {
  let prefix = socket.remoteFamily+" "+socket.remoteAddress+":"+socket.remotePort
  LOGGER.log(prefix, "Query Connected!")
  let remote = net.connect(OPTIONS.teamspeak[1], OPTIONS.teamspeak[0])
  socket.on('data', (stream) => {
    LOGGER.log(prefix, String(stream))
    let match = String(stream).match(/^login[ ]{1,}(client_login_name=([\w]{1,})|([\w]{1,}))/)
    if (match) {
      if (!allowLogin(socket.remoteAddress, match[2] || match[3])) return socket.end("error id=1337 msg=Query\\sProtection:\\snot\\sallowed\\sto\\slogin\\sas\\s"+(match[2] || match[3]))
    }
    remote.write(stream)
  })
  remote.on('data', (stream) => {
    socket.write(stream)
  })
  socket.on('end', () => {
    remote.end()
    LOGGER.log(prefix, "Query Disconnected!")
  })
  remote.on('end', socket.end)
  remote.on('error', () => {})
  socket.on('error', () => {})
}).listen(OPTIONS.listenPort)
 

Najsr

Moderator
TeamSpeak Developer
Apr 23, 2016
483
249
167
Here a little NodeJS Script which acts like a man in the middle tool for your Query, it is capable of logging every command and whitelisting the login system
So instead of creating a connection to the TeamSpeak Query, you connect to this ts3query Application which basically redirects all traffic to the TeamSpeak Server with some validation and logging in between

You will need to install NodeJS on your System
This Script has been tested on NodeJS v7.2.0 probably runs on v6 too
Copy the content save it to a file (for example /root/ts3query.js) and execute it with "node /root/ts3query.js"

HTML:
/*     Original Creator multivitamin.WTF
 *    Designed as "Man in the Middle" TeamSpeak Query Protection
 *  You maybe want to add the IP of the Server which executes this Script to the query_whitelist.txt
*/

const OPTIONS = {
  "teamspeak": ["10.10.12.106", 10011],                      //TeamSpeak IP + Query Port
  "listenPort": 10011,                                       //Listen Port for this App -> the Port which the Application listens to for new connections
  "logging": {
    "logfile": "/var/log/ts3_query.log",               //false for no file logging
    "censor_passwords": true                           //Password will be replaced to ___CENSORED___ in log
  },
  "login": [                                                 //Here you can define multiple States for "login" catches
    {
      "user": "serveradmin",                     //Login User Name
      "filter": "IP",                            //Filter Allowed Methods (DENY, IP)
      "ips": ["127.0.0.1", "localhost", "::1"]   //List with allowed IP Addresses
    },
    {
      "user": "*",                               //Appends on !!ALL!! Users
      "filter": "DENY"                           //Denies Login to all Users
    }
  ],
}


//At this Point no need to edit stuff
const net = require("net")
const fs = require("fs")


class Logger {
  constructor(logfile = false, censorpasswords = true) {
    this.out = logfile
    this.censorpasswords = censorpasswords
  }
  log(prefix, str) {
    if (!str.match(/[\w]/)) return
    if (this.censorpasswords) {
      let login = str.match(/login[ ]{1,}(client_login_name=([\w]{1,})|([\w]{1,})) (client_login_password=([\w]{1,})|([\w]{1,}))/)
      if (login) str = str.replace((login[5]) ? login[5] : login[6], "___CENSORED___")
    }
    var msg = "["+new Date().toISOString()+"]["+prefix+"] "+str.replace("\n","")
    console.log(msg)
    if (this.out === false) return
    fs.appendFile(this.out, msg+"\n", (err) => {
      if (err) throw err
    })
  }
}


const LOGGER = new Logger(OPTIONS.logging.logfile, OPTIONS.logging.censorpasswords)

function allowLogin (ip, username) {
  var verify = (obj) => {
    if (obj.filter.toUpperCase() === "DENY") return false
    return (obj.filter.toUpperCase() === "IP" && obj.ips.indexOf(ip) >= 0)
  }
  for (var k in OPTIONS.login) {
    let object = OPTIONS.login[k]
    if (object.user === "*") star = object
    if (object.user !== "*" && object.user == username) return verify(object)
  }
  if (typeof star === "object") return verify(star)
  return true
}

net.createServer((socket) => {
  let prefix = socket.remoteFamily+" "+socket.remoteAddress+":"+socket.remotePort
  LOGGER.log(prefix, "Query Connected!")
  let remote = net.connect(OPTIONS.teamspeak[1], OPTIONS.teamspeak[0])
  socket.on('data', (stream) => {
    LOGGER.log(prefix, String(stream))
    let match = String(stream).match(/^login[ ]{1,}(client_login_name=([\w]{1,})|([\w]{1,}))/)
    if (match) {
      if (!allowLogin(socket.remoteAddress, match[2] || match[3])) return socket.end("error id=1337 msg=Query\\sProtection:\\snot\\sallowed\\sto\\slogin\\sas\\s"+(match[2] || match[3]))
    }
    remote.write(stream)
  })
  remote.on('data', (stream) => {
    socket.write(stream)
  })
  socket.on('end', () => {
    remote.end()
    LOGGER.log(prefix, "Query Disconnected!")
  })
  remote.on('end', socket.end)
  remote.on('error', () => {})
  socket.on('error', () => {})
}).listen(OPTIONS.listenPort)
Looks awesome, but does it support cidr notations?
 

Najsr

Moderator
TeamSpeak Developer
Apr 23, 2016
483
249
167
When trying to launch, it returns an error -->
Code:
events.js:160
      throw er; // Unhandled 'error' event
      ^

Error: listen EADDRINUSE :::10011
    at Object.exports._errnoException (util.js:1022:11)
    at exports._exceptionWithHostPort (util.js:1045:20)
    at Server._listen2 (net.js:1262:14)
    at listen (net.js:1298:10)
    at Server.listen (net.js:1376:9)
    at Object.<anonymous> (/root/ts3query.js:91:4)
    at Module._compile (module.js:571:32)
    at Object.Module._extensions..js (module.js:580:10)
    at Module.load (module.js:488:32)
    at tryModuleLoad (module.js:447:12)
EDIT: It's something with the listen port. I can't run it when teamspeak server is running, coz that port is already in use :( Is there any way to launch it on the same server where is ts server running?
 
Last edited:

Najsr

Moderator
TeamSpeak Developer
Apr 23, 2016
483
249
167
It doesn't work :(

Code:
login client_login_name=serveradmin client_login_password=MYSECRETPW
error id=0 msg=ok
 
Top