The cookie is used to prevent address spoofing, without the firewall having to remember the ip-address of the clients. It does this by forcing the client to send a cookie, it can only get from the server. The cookie is generated from the current time, the source and destination address and port, and a secret that only the server has. It works on the same principle that authenticators do. This method forces the client to reply with the same ip/port to the same server ip/port in order to continue.
The cookie is the hashed ClientIp
, ServerIp
, ClientPort
and ServerPort
using siphash24
and a key that is one quarter of a cookie_seed
. Every second another quarter of the cookie_seed
is used as key.
The server generates a new cookie_seed
every 4 seconds, and always keeps 2 cookie_seeds
. That means a client has atleast 4 seconds, and atmost 8 seconds to reply before the cookie becomes invalid. ClientIp, ServerIp, ClientPort and ServerPort are in network order.
cookie_seed = sha512(random_seed << 32 | (unix_time & 0xffffffff))
cookie = siphash24(cookie_seed >> ((time & 3) * 128), Concat(ClientIp, ServerIp, ClientPort, ServerPort))
The server keeps a secret called random-seed
. Should a attacker ever get hold of the random-seed
a new random-seed
must be used. Otherwise any protection that the cookie offers would be compromised. Since a cookie is only valid for atmost eight seconds, changing the random-seed
would at the worst prevent users from logging into a Teamspeak-Server for atmost eight seconds, but the most common case would be no outage what so ever.
xxd -l 60 -c 60 -p /dev/urandom > random_seed
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 'T' | 'S' | '3' | 'I' |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 'N' | 'I' | 'T' | '1' |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| PacketId | ClientId |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type + Flags | Client Version ->
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Command | Timestamp ->
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Random Sequence ->
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| RESERVERD |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| RESERVED |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| RESERVERD |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- All fields are encoded in big endian, unless otherwise specified.
PacketId
is always101
.ClientId
is always0
.Type + Flags
is always0x88
.Client Version
is the build number of the client.Command
is always0
.Timestamp
is the unixtime of the client maschine, encoded in big endian.Random Sequence
is a random value generated by the client.- Every
RESERVED
field must be zero.