ts3server ping utility [Linux only]

shockli

Contributor
Jan 29, 2016
243
194
111
Cant install the dependencies :
Code:
[2015-06-10 01:49.28]  /home/root/Downloads
[root.roots-PC_Win8-1] ➤ apt-get install libqt5core5:i386
Trying to download file setup.bz2
Updated setup.ini
Package libqt5core5:i386 not found in cygwin mirror, trying cygwinports mirror
Trying to download file setup.bz2
Updated setup.ini

Package libqt5core5:i386 not found, exiting...

                                                                                                                         ✔
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
[2015-06-10 01:50.04]  /home/root/Downloads
[root.roots-PC_Win8-1] ➤ apt-get install libqt5core5
Package libqt5core5 not found in cygwin mirror, trying cygwinports mirror

Package libqt5core5 not found, exiting...

                                                                                                                         ✔
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
[2015-06-10 01:50.12]  /home/root/Downloads
[root.roots-PC_Win8-1] ➤ apt-get install libqt5network5:i386
Package libqt5network5:i386 not found in cygwin mirror, trying cygwinports mirror

Package libqt5network5:i386 not found, exiting...

                                                                                                                         ✔
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
[2015-06-10 01:50.28]  /home/root/Downloads
[root.roots-PC_Win8-1] ➤ apt-get install libqt5network5
Package libqt5network5 not found in cygwin mirror, trying cygwinports mirror

Package libqt5network5 not found, exiting...
Also cant open the file:
Code:
[2015-06-10 01:49.10]  /home/root/Downloads
[root.roots-PC_Win8-1] ➤ ./sender_32_final
bash: ./sender_32_final: cannot execute binary file

The package belongs to libQt5Core-devel on cygwin. Don't run it as root (maybe a part of the issue? Sending a packet doesn't require root). Why are you running 32 bit if cygwin supports 64 bit, and your pc is 99.9% running 64 bit.

---- Automatically Merged Double Post ----

NO LONGER SUPPORTED. But should still work.

Releasing the first version of my tool :D

You will need the following packages for it to work : libqt5network5 (and libqt5core5)

This tool sends a special crafted UDP packet that appears to be a ping packet in the ts3 protocol. It then monitors the connection and wait for a reply until timeout is reached.

THIS DOES NOT SEND AN ICMP PING. IT SENDS A SPECIAL CRAFTED UDP PACKET. IT CAN DETECT IF YOUR TS SERVER CRASHED WHEREAS A SIMPLE PING CAN'T !

Options :
  1. ip : ip of th server to check (no dns support).
  2. port : port of the server to check (default to 9987).
  3. timeout : time to wait before failing.
  4. response validation : Whether to fail or not if reply is weird.
  5. server type : Normal or SDK
  6. ping type : short is a short ping with no special infos. Realistic sends versions info, and the server replies with more infos (unknown).
  7. new! repeat : Number of pings to send, -1 for infinite
  8. new! pause : Pause between pings, default to 1500ms

5P7G2ceS

Example with voice.teamspeak.com (server is custom as you can see) :
VgN4OZMb


ver 0.4 : x64
i386
VirusTotal 0.4 : https://www.virustotal.com/en/file/...20000e66a3b2a5fce2670abae4c8439fd92/analysis/ 0/57

Very interesting you used qt's network library. May we see the source (or if you could pm it even?)? I'm quite curious.
 
Last edited:

ehthe

Retired Staff
Contributor
Apr 26, 2015
1,029
896
216
So since I wasn't VIP anymore I couldn't see the messages here :p
I used Qt because it had some simple array stuff don't quite remember, I could have used boost or the standard std.
I deleted/modified the code long ago and it wasn't working that is why there is no update. All it did was try and reproduce part of the handshake a client does when connecting to the server.
I beleive anyone who has extended knowledge of this (I don't) can achieve the same thing.

---- Automatically Merged Double Post ----

Here's a horrible code snippet :p
C++:
bool sendPing(QUdpSocket &udpSocket) {
    QByteArray clientPing(PING_FROM_CLIENT_SIZE, '\0'); //Must be 34 otherwise is ignored
    clientPing[0] = 'T';
    clientPing[1] = 'S';
    clientPing[2] = '3';
    clientPing[3] = 'I';
    clientPing[4] = 'N';

    clientPing[5] = 'I';
    clientPing[6] = 'T';
    clientPing[7] = '1';

    //clientPing[8] = 0x00;    //can be anything
    clientPing[9] = 0x65;    //can be anything
    //clientPing[10] = 0x00;    //can be anything
    //clientPing[11] = 0x00;    //can be anything

    clientPing[12] = 0x88; //can be 0xc8

    //no changes between arch or os, just versions
    //3.0.16    3.0.11    3.0.11.1    3.0.12    3.0.13    3.0.13.1    3.0.14    3.0.15    3.0.15.1
    clientPing[13] = 0x02;    //0x01    0x01    0x01    0x01    0x01    0x02    0x02    0x02    INCREMENTING
    clientPing[14] = 0xFD;    //0x13    0x1e    0x4b    0x63    0x85    0x3e    0xc1    0xe1
    clientPing[15] = 0x66;    //0xf5    0x7b    0x5f    0x4e    0x95    0x22    0xbe    0xa6
    clientPing[16] = 0xD3;    //0x3d    0x66    0x29    0x05    0xa3    0xaf    0xaa    0xa4
    //If all 0 (short query) then server responds 0xc8. No real connection possible ? TODO investigate

    return udpSocket.write(clientPing.data(), PING_FROM_CLIENT_SIZE) == PING_FROM_CLIENT_SIZE;
}
 
Last edited:

BIOS

Knowledge Seeker
VIP
Oct 10, 2015
447
848
208
Use the Net_Ping module

The first thing you can try to do is use the PHP PEAR Net_Ping module to get around this problem. In short, you install it like this:

Code:
pear install Net_Ping


Then use it like this:

Code:
<?php
require_once "Net/Ping.php";
$ping = Net_Ping::factory();
if (PEAR::isError($ping)) {
  echo $ping->getMessage();
} else {
  $ping->setArgs(array('count' => 2));
  var_dump($ping->ping('example.com'));
}
?>

This is shown at the documentation page for this module.


This didn't work for me, as they also disabled access to the PHP pear command.



Use the PHP Curl module

The next thing I tried (and what worked for me) is to use a PHP Curl script I found that emulates a little bit of what the ping command does. It's important to note that this isn't technically true: The ping command uses a totally different protocol than the approach shown here, but for my purposes I just needed to see if a remote web server was alive, so it didn't really matter to me whether I used ping or a curl command like this.


Here's a modified version of the original source code:

Code:
<?php

$url = 'www.google.com';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$data = curl_exec($ch);
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if($httpcode>=200 && $httpcode<300){
  echo 'worked';
} else {
  echo "didn't work";
}

?>

You can find the original source code at this "Lost in Code" URL.

Issue a ping command from a PHP script

As a final option, if you can run the ping command from your command line, you can also just execute it with a PHP ping script, like this:


Code:
<?php
$str = exec("ping -c 1 www.google.com");
if ($result == 0){
  echo "ping succeeded";
}else{
  echo "ping failed";
}
?>

In my case this didn't work because I wasn't given access to the ping command, but if you do have access to the ping command at the command line, this "PHP exec" example shows how this can work.

no one have need to run an separate pingtool anyone can handle php or phyton​
 

kalle

high minded
Contributor
Oct 28, 2015
411
253
178
Use the Net_Ping module

The first thing you can try to do is use the PHP PEAR Net_Ping module to get around this problem. In short, you install it like this:

Code:
pear install Net_Ping


Then use it like this:

Code:
<?php
require_once "Net/Ping.php";
$ping = Net_Ping::factory();
if (PEAR::isError($ping)) {
  echo $ping->getMessage();
} else {
  $ping->setArgs(array('count' => 2));
  var_dump($ping->ping('example.com'));
}
?>

This is shown at the documentation page for this module.


This didn't work for me, as they also disabled access to the PHP pear command.



Use the PHP Curl module

The next thing I tried (and what worked for me) is to use a PHP Curl script I found that emulates a little bit of what the ping command does. It's important to note that this isn't technically true: The ping command uses a totally different protocol than the approach shown here, but for my purposes I just needed to see if a remote web server was alive, so it didn't really matter to me whether I used ping or a curl command like this.


Here's a modified version of the original source code:

Code:
<?php

$url = 'www.google.com';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$data = curl_exec($ch);
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if($httpcode>=200 && $httpcode<300){
  echo 'worked';
} else {
  echo "didn't work";
}

?>

You can find the original source code at this "Lost in Code" URL.

Issue a ping command from a PHP script

As a final option, if you can run the ping command from your command line, you can also just execute it with a PHP ping script, like this:


Code:
<?php
$str = exec("ping -c 1 www.google.com");
if ($result == 0){
  echo "ping succeeded";
}else{
  echo "ping failed";
}
?>

In my case this didn't work because I wasn't given access to the ping command, but if you do have access to the ping command at the command line, this "PHP exec" example shows how this can work.

no one have need to run an separate pingtool anyone can handle php or phyton​

I think that there is diffrence between your and ehthe code snippet.
His code makes UDP packet and sends it to the TS3 server, but your code only pings server. Also he mentions diffrence between his code and normal ping. :)
 

NNE

C++ priest
VIP
Jul 20, 2016
21
15
78
Modified python echo client example:
Python:
#!/usr/bin/python3

import asyncio
import argparse

parser = argparse.ArgumentParser()
parser.add_argument('-H', '--host', nargs='?', default='localhost', help="Host")
parser.add_argument('-p', '--port', nargs='?', type=int, default=9987, help="Port")
args = parser.parse_args()

class EchoClientProtocol:
    def __init__(self, message, loop):
        self.message = message
        self.loop = loop
        self.transport = None
        self.on_con_lost = loop.create_future()

    def connection_made(self, transport):
        self.transport = transport
        print('Send:', self.message)
        self.transport.sendto(self.message)

    def datagram_received(self, data, addr):
        print("Received:", data)

        print("Close the socket")
        self.transport.close()

    def error_received(self, exc):
        print('Error received:', exc)

    def connection_lost(self, exc):
        print("Connection closed")
        self.on_con_lost.set_result(True)


async def main(host,port):
    # Get a reference to the event loop as we plan to use
    # low-level APIs.
    loop = asyncio.get_running_loop()

    message = b'TS3INIT1\x00\x65\x00\x00\x88\x02\xFD\x66\xD3' + bytearray(17)
    transport, protocol = await loop.create_datagram_endpoint(
        lambda: EchoClientProtocol(message, loop),
        remote_addr=(host, port))

    try:
        await protocol.on_con_lost
    finally:
        transport.close()


asyncio.run(main(args.host,args.port))

Output:
Code:
Send: b'TS3INIT1\x00e\x00\x00\x88\x02\xfdf\xd3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
Received: b'TS3INIT1\x00e\xc8\x01\x00\x00\x02\n'
Close the socket
Connection closed
 
Last edited:

NNE

C++ priest
VIP
Jul 20, 2016
21
15
78
Added timeout. Now can be used from bash script for batch checks)
Python:
#!/usr/bin/python3

import asyncio
import argparse

parser = argparse.ArgumentParser()
parser.add_argument('-H', '--host', nargs='?', default='localhost', help="Host")
parser.add_argument('-p', '--port', nargs='?', type=int, default=9987, help="Port")
parser.add_argument('-t', '--timeout', nargs='?', type=float, default=5.0, help="Timeout in seconds")
args = parser.parse_args()

class EchoClientProtocol:
    def __init__(self, message, loop):
        self.message = message
        self.loop = loop
        self.transport = None
        self.on_con_lost = loop.create_future()

    def connection_made(self, transport):
        self.transport = transport
        #print('Send:', self.message)
        self.transport.sendto(self.message)

    def datagram_received(self, data, addr):
        #print("Received:", data)

        #print("Close the socket")
        self.transport.close()

    def error_received(self, exc):
        print('Error received:', exc)

    def connection_lost(self, exc):
        #print("Connection closed")
        if not self.on_con_lost.done():
            self.on_con_lost.set_result(True)

async def main(host,port,timeout):
    # Get a reference to the event loop as we plan to use
    # low-level APIs.
    loop = asyncio.get_running_loop()

    message = b'TS3INIT1\x00\x65\x00\x00\x88\x02\xFD\x66\xD3' + bytearray(17)
    transport, protocol = await loop.create_datagram_endpoint(
        lambda: EchoClientProtocol(message, loop),
        remote_addr=(host, port))

    try:
        await asyncio.wait_for(protocol.on_con_lost, timeout=timeout)
        print(f"{host}:{port} - Ok")
    except asyncio.TimeoutError:
        print(f"{host}:{port} - Timeout")
    finally:
        transport.close()


asyncio.run(main(args.host,args.port,args.timeout))
 
Top