|
|
|
ts3init Linux netfilter module
|
|
|
|
==============================
|
|
|
|
A Linux netfilter module to help filter ts3init floods on TeamSpeak 3 servers
|
|
|
|
|
|
|
|
TeamSpeak 3 servers are a popular (D)Dos target. They are harder to protect than
|
|
|
|
other servers because the TeamSpeak 3 protocol is based on UDP. A popular
|
|
|
|
method, which is hard to mitigate by hosters is called *init floods*. This is
|
|
|
|
where the attacker sends many connection request to the server, usually spoofing
|
|
|
|
the source address, to make it harder to block them. The TeamSpeak 3 protocol
|
|
|
|
has an anti spoof check as the first stage of the connection, but the server
|
|
|
|
program can not keep up with the flood of packets.
|
|
|
|
|
|
|
|
This set of plugins is designed to let the Linux kernel, or rather netfilter,
|
|
|
|
handle the anti spoofing stages of a new TeamSpeak 3 connection. This could be
|
|
|
|
done on a different machine than the one the TeamSpeak 3 server is executing
|
|
|
|
on.
|
|
|
|
|
|
|
|
Current version
|
|
|
|
===============
|
|
|
|
The current release is version 0.1. This version is a beta and has by no means
|
|
|
|
been tested in a production environment. At this stage this software is merely
|
|
|
|
a proof of concept. We invite the TeamSpeak community and of course the Linux
|
|
|
|
community to test this tool and to contribute improvements and new ideas.
|
|
|
|
|
|
|
|
prerequisites
|
|
|
|
=============
|
|
|
|
In order to compile and install this software you need the following things:
|
|
|
|
* Linux kernel headers (version 2.6.35 or greater)
|
|
|
|
* Iptables development headers
|
|
|
|
* GCC (version 4.6.0 or greater)
|
|
|
|
|
|
|
|
Usually these can be installed using your package manager (yum/apt-get/etc).
|
|
|
|
Usually these packages resemble the names "Linux-header-<..>", "iptables-dev",
|
|
|
|
"GCC"
|
|
|
|
|
|
|
|
How to install
|
|
|
|
==============
|
|
|
|
|
|
|
|
```
|
|
|
|
make
|
|
|
|
sudo make install
|
|
|
|
sudo depmod -a
|
|
|
|
sudo modprobe xt_ts3init
|
|
|
|
```
|
|
|
|
|
|
|
|
Protocol background and module description
|
|
|
|
==========================================
|
|
|
|
When a TeamSpeak 3 client attempts to connect to a TeamSpeak 3 server, it sends
|
|
|
|
out a *get cookie* packet. The server then replies with a *set cookie* packet.
|
|
|
|
This packet has some secret information about the connection details. The client
|
|
|
|
then response with a *get puzzle* packet. This packet includes the cookie that
|
|
|
|
it got previously. The server now validates this cookie and if it is valid, the
|
|
|
|
server continues with the rest of the connection packets.
|
|
|
|
|
|
|
|
This software packages comes with two netfilter match extensions, and three
|
|
|
|
netfilter target extensions which we will discuss next. Combined these
|
|
|
|
extensions and some other netfilter modules, can handle the initial connection
|
|
|
|
phase for a TeamSpeak 3 server. This prevents any packet, with a spoofed source
|
|
|
|
ip address, to reach the TeamSpeak 3 server.
|
|
|
|
|
|
|
|
Match extensions
|
|
|
|
================
|
|
|
|
|
|
|
|
ts3init_get_cookie
|
|
|
|
------------------
|
|
|
|
Matches if the packet in question is a valid TeamSpeak 3 *get cookie* packet
|
|
|
|
from the client.
|
|
|
|
There are additional parameters that can be set:
|
|
|
|
```
|
|
|
|
$ iptables -m ts3init_get_cookie -h
|
|
|
|
<..>
|
|
|
|
ts3init_get_cookie match options:
|
|
|
|
--min-client n The client needs to be at least version n.
|
|
|
|
--check-time sec Check packet send time request.
|
|
|
|
May be off by sec seconds.
|
|
|
|
```
|
|
|
|
* `min-client` checks that the client version in the packet is at least the
|
|
|
|
version specified.
|
|
|
|
* `check-time` compares the unix-timestamp in the client packet to the unix-time
|
|
|
|
on the server. If they differ too much, the packet is not matched.
|
|
|
|
|
|
|
|
ts3init_get_puzzle
|
|
|
|
------------------
|
|
|
|
Matches if the packet in question is a valid TeamSpeak 3 *get puzzle* packet
|
|
|
|
from the client.
|
|
|
|
There are additional parameters that can be set:
|
|
|
|
```
|
|
|
|
$ iptables -m ts3init_get_puzzle -h
|
|
|
|
<..>
|
|
|
|
ts3init_get_puzzle match options:
|
|
|
|
--min-client n The client needs to be at least version n.
|
|
|
|
--check-cookie Check that the cookie was generated by same seed.
|
|
|
|
--random-seed <seed> Seed is a 60 byte hex number.
|
|
|
|
A source could be /dev/random.
|
|
|
|
--random-seed-file <file> Read the seed from a file.
|
|
|
|
```
|
|
|
|
* `min-client` checks that the client version in the packet is at least the
|
|
|
|
version specified.
|
|
|
|
* `check-cookie` matches if it matches the cookie that was generated in the
|
|
|
|
netfilter target extension `TS3INIT_SET_COOKIE`. To match the seed needs to be
|
|
|
|
exactly the same. It is possible to check cookies that were generated on a
|
|
|
|
different machine, provided that those machines have the same date and time,
|
|
|
|
and the same seed specified. In other words: The cookie is created in a
|
|
|
|
deterministic way, depending only on the current time and the seed. If
|
|
|
|
`check-cookie` is specified, either `random-seed` or `random-seed-file` needs
|
|
|
|
to be specified too.
|
|
|
|
|
|
|
|
ts3init
|
|
|
|
-------
|
|
|
|
Matches a ts3init packet, by checking if the packet starts with the *TS3INIT1*.
|
|
|
|
Additional header checks for client and server packets can be specified:
|
|
|
|
```
|
|
|
|
$ iptables -m ts3init -h
|
|
|
|
<..>
|
|
|
|
ts3init match options:
|
|
|
|
--client Match ts3init client packets.
|
|
|
|
--server Match ts3init server packets.
|
|
|
|
--command <command> Match packets with the specified command.
|
|
|
|
```
|
|
|
|
* `client` checks that the packet has a valid ts3init client header
|
|
|
|
* `server` checks that the packet has a valid ts3init server header
|
|
|
|
* `command` checks that the packet has the specified command in its header.
|
|
|
|
Requires either --client or --server.
|
|
|
|
|
|
|
|
Target extensions
|
|
|
|
=================
|
|
|
|
|
|
|
|
TS3INIT_GET_COOKIE
|
|
|
|
------------------
|
|
|
|
Rewrites the packet into a *get_cookie* packet and then accepts it.
|
|
|
|
It is assumed that the packet is a ts3init packet of any kind, any other packet
|
|
|
|
may or may not result in a valid *get_cookie* packet. Used for pre 3.1 clients,
|
|
|
|
as an alternative to `TS3INIT_RESET`. It takes no parameters.
|
|
|
|
|
|
|
|
TS3INIT_SET_COOKIE
|
|
|
|
------------------
|
|
|
|
Generates a *set_cookie* packet to the matched *get_cookie* packet. The orginal
|
|
|
|
*get_cookie* packet is dropped. It is assumed that the orginal packet is a
|
|
|
|
*get_cookie* packet, no attempt is made to check if that is true. It should
|
|
|
|
always be used with `ts3init_get_puzzle` match.
|
|
|
|
|
|
|
|
```
|
|
|
|
$ iptables -j TS3INIT_SET_COOKIE -h
|
|
|
|
<..>
|
|
|
|
TS3INIT_SET_COOKIE target options:
|
|
|
|
--zero-random-sequence Always return 0 as random sequence.
|
|
|
|
--random-seed <seed> Seed is a 60 byte hex number in.
|
|
|
|
A source could be /dev/random.
|
|
|
|
--random-seed-file <file> Read the seed from a file.
|
|
|
|
```
|
|
|
|
|
|
|
|
* `zero-random-sequence` forces the returned *random-sequence* to be always
|
|
|
|
zero. This allows the target to not look at the payload of the packet.
|
|
|
|
* `random-seed` is used to generate the cookie returned in the *set-cookie*
|
|
|
|
packet. *seed* must be a 120 character long hexstring.
|
|
|
|
* `random-seed-file` read the `random-seed` from a file. The file must contain
|
|
|
|
a 120 character long hexstring, without any newlines.
|
|
|
|
|
|
|
|
TS3INIT_RESET
|
|
|
|
-------------
|
|
|
|
Drops the packet and sends a *reset* packet back to the sender. The
|
|
|
|
sender should always be the TeamSpeak 3 client. Starting with the TeamSpeak 3.1
|
|
|
|
client, the client will react to the reset packet by resending the *get cookie*
|
|
|
|
to the server. Older clients do not handle this packet. It takes no parameters.
|
|
|
|
|
|
|
|
How to use
|
|
|
|
==========
|
|
|
|
The idea for which these extensions were developed was to create a few iptables
|
|
|
|
rules that do the anti spoofing phase for a TeamSpeak server. This can be done
|
|
|
|
as follows:
|
|
|
|
* [recommended] Disable connection tracking with the help of raw table
|
|
|
|
* Create ipset: ts3_authorized with a timeout of 30 seconds
|
|
|
|
* If a source ip address is in the ipset ts3_authorized, renew the entry in the
|
|
|
|
set to update the timeout then accept the packet.
|
|
|
|
* Use `ts3init_get_cookie` matches to get connection requests and reply with
|
|
|
|
`TS3INIT_SET_COOKIE`.
|
|
|
|
* Use `ts3init_get_puzzle` matches to get the cookie replies from the client.
|
|
|
|
If they match, add the source ip address to the ts3_authorizing ipset and then
|
|
|
|
reply with `TS3INIT_RESET`
|
|
|
|
* Drop all other packets
|
|
|
|
|
|
|
|
It is possible to make a more detailed firewall.
|
|
|
|
|
|
|
|
Example iptables setup
|
|
|
|
======================
|
|
|
|
There are two examples included: _simple_ and _complex_. Both use ipset to
|
|
|
|
create a set of whitelisted ip addresses that are allowed to send packets to the
|
|
|
|
TeamSpeak3 server. The simple example does the bare minimum to do the ip
|
|
|
|
addresss authentication on the firewall, and to protect the file transfer (tcp)
|
|
|
|
port from traffic from unverified ip addresses.
|
|
|
|
|
|
|
|
The complex example is a bit more advanced. It keeps three ipsets. Authorizing
|
|
|
|
authorized and authorized_ft.
|
|
|
|
|
|
|
|
The autorizing set stores ip addresses and ports for connections that have
|
|
|
|
verified ip addresses, but did not yet complete the puzzle phase on the ts3
|
|
|
|
server.
|
|
|
|
|
|
|
|
The authorized set keeps ip addresses and ports that have completed the puzzle
|
|
|
|
phase on the server and are assumed to be authorized. It is technically not
|
|
|
|
true that the server has accepted this connection. It could still reject it
|
|
|
|
because the password is wrong, or the server is full, or other reasons. But for
|
|
|
|
this example, it is good enough.
|
|
|
|
|
|
|
|
The authorized_ft set keeps a list of authorized ip addresses (not ports). Only
|
|
|
|
these ip addresses are allowed to send traffic to the file transfer
|
|
|
|
port. Since there is no way to know in advance what source port the TeamSpeak 3
|
|
|
|
client is going to use for file transfer, this is the best we can do.
|
|
|
|
|