Comprehensive Analysis of Load Testing Script and Project Management

Introduction

This article provides an in-depth analysis of a Bash script designed for load testing a website. The script sends HTTP GET requests with randomized attributes to a target URL and logs the response details. We will explore the script's components, functionality, and management using the Agile project management model. Additionally, we will analyze the script's behavior and performance in detail.

Script Overview

The provided script aims to simulate a load on a web server by sending multiple requests per second. Key features include the generation of random IP addresses (both IPv4 and IPv6), User-Agent strings, and Referer URLs. The script logs the response status and duration for each request.

Installation and Execution Requirements for the Script

1. Termux

To run the script on Termux, follow these steps:

  1. Update and Upgrade Termux Packages:
    pkg update && pkg upgrade
  2. Install Necessary Packages:
    pkg install curl coreutils util-linux tsu bash iproute2
  3. Root Access (Optional): If the script requires root access, use the following command:
    tsu
  4. Run the Script: To execute the script, use:
    bash script.sh

2. Linux (Ubuntu/Debian)

To run the script on a Linux-based system, follow these steps:

  1. Update and Upgrade the System:
    sudo apt update && sudo apt upgrade
  2. Install Required Packages:
    sudo apt install curl coreutils iproute2 bash tc
  3. Make the Script Executable (if needed):
    chmod +x script.sh
  4. Run the Script:
    ./script.sh

3. Additional Notes

QoS Configuration with `tc`: The script uses the `tc` tool to configure Quality of Service (QoS). Ensure you have the necessary permissions to execute these commands.

Process Management: The script uses background processes to send HTTP requests in parallel. At the end, it uses `pkill` to terminate all background processes.

Script Code

#!/bin/bash

# Define the target URL and IP address
url="https://www.miralishahidi.ir"  # Target domain
ip_address="185.55.227.184"  # Target public IP address

# Define requests per second (RPS)
pps=2  # Number of requests per second

# QoS settings - This example sets a simple QoS policy on the eth0 interface
tc qdisc add dev eth0 root handle 1: htb default 12
tc class add dev eth0 parent 1: classid 1:1 htb rate 1mbit
tc class add dev eth0 parent 1:1 classid 1:10 htb rate 512kbit ceil 1mbit
tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip dst $ip_address flowid 1:10

# Function to generate random IPv4 address
function generate_random_ipv4() {
  echo "$(shuf -i 1-255 -n 1).$(shuf -i 0-255 -n 1).$(shuf -i 0-255 -n 1).$(shuf -i 1-254 -n 1)"
}

# Function to generate random IPv6 address
function generate_random_ipv6() {
  # Generate a random 128-bit IPv6 address
  printf "%x:%x:%x:%x:%x:%x:%x:%x\n" \
    $((RANDOM % 0xFFFF)) $((RANDOM % 0xFFFF)) \
    $((RANDOM % 0xFFFF)) $((RANDOM % 0xFFFF)) \
    $((RANDOM % 0xFFFF)) $((RANDOM % 0xFFFF)) \
    $((RANDOM % 0xFFFF)) $((RANDOM % 0xFFFF))
}

# Function to generate random User-Agent
function generate_random_user_agent() {
  local user_agents=(
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:90.0) Gecko/20100101 Firefox/90.0"
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:90.0) Gecko/20100101 Firefox/90.0"
    "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:91.0) Gecko/20100101 Firefox/91.0"
    "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36"
    "Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1"
    "Mozilla/5.0 (Linux; Android 10; SM-A505F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Mobile Safari/537.36"
    "Mozilla/5.0 (Linux; Android 11; SM-G991B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Mobile Safari/537.36"
    "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:89.0) Gecko/20100101 Firefox/89.0"
  )
  echo "${user_agents[$RANDOM % ${#user_agents[@]}]}"
}

# Function to generate random Referer
function generate_random_referer() {
  local referers=(
    "https://www.google.com/"
    "https://www.bing.com/"
    "https://www.yahoo.com/"
    "https://www.duckduckgo.com/"
    "https://www.ask.com/"
    "https://search.yahoo.com/"
    "https://www.aol.com/"
    "https://www.baidu.com/"
    "https://www.yandex.com/"
  )
  echo "${referers[$RANDOM % ${#referers[@]}]}"
}

# Function to send an HTTP GET request and log details
function send_request() {
  local ip_version="$1"
  local ip_address="$2"
  local user_agent=$(generate_random_user_agent)
  local referer=$(generate_random_referer)

  local headers=(
    "-H" "User-Agent: $user_agent"
    "-H" "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8"
    "-H" "Accept-Language: en-US,en;q=0.5"
    "-H" "Connection: keep-alive"
    "-H" "Upgrade-Insecure-Requests: 1"
    "-H" "Referer: $referer"
    "-H" "X-Forwarded-For: $ip_address"
  )

  # Capture the start time
  local start_time=$(date +%s%3N)

  # Send the request and capture the response status and duration
  local response=$(curl -s -o /dev/null -w "%{http_code}" "${headers[@]}" "$url")
  local end_time=$(date +%s%3N)
  local duration=$((end_time - start_time))

  # Log the request details
  echo "Request: IP: $ip_address, User-Agent: $user_agent, Status Code: $response, Duration: ${duration}ms"
}

# Start the load test
echo "[!] Starting infinite load distribution test for $url and IP $ip_address with maximum 2 requests per second..."

# Initialize request count
request_count=0

# Infinite loop to send requests in parallel
while true; do
  for ((i=1; i<=$pps; i++)); do
    if [ $((i % 2)) -eq 0 ]; then
      ip=$(generate_random_ipv4)
      send_request "ipv4" "$ip" &
    else
      ip=$(generate_random_ipv6)
      send_request "ipv6" "$ip" &
    fi
    # Increment the request count
    ((request_count++))
  done

  # Log the total number of requests sent
  echo "Total Requests Sent: $request_count"

  # Wait for one second to match the rate of requests per second
  sleep 1
done

# Wait for all background processes to complete
wait

# Terminate all background processes
pkill -P $$
                

Project Management Analysis Using Agile

The Agile project management model is well-suited for this script due to its iterative development and flexibility. Here’s how Agile principles can be applied to this project:

1. Planning

  • Requirements Gathering: Identify the key objectives of the script, such as testing the load capacity of the target URL and monitoring response times.
  • Scope Definition: Define the core features of the script, including the generation of random IPs and User-Agents, and iterative improvements based on testing results.

2. Design

  • Components: The script includes various components such as functions for generating IP addresses, User-Agents, and sending HTTP requests.
  • Execution Flow: The script operates in a continuous loop to send requests at a defined rate, with mechanisms to handle both IPv4 and IPv6 addresses.

3. Development

  • Implementation: Develop the script according to the outlined design, ensuring all functions are correctly implemented and tested.
  • Testing: Perform rigorous testing to ensure the script works as intended, logging accurate data and handling various network conditions.

4. Deployment

  • Environment Setup: Prepare the execution environment, ensuring necessary permissions and tools are available for running the script.
  • Execution: Deploy the script in a controlled environment to test its performance and ensure it meets the defined requirements.

5. Monitoring and Maintenance

  • Monitoring: Regularly monitor the script’s performance and log outputs to detect any issues or performance bottlenecks.
  • Updates: Incorporate feedback, add new features, and make necessary updates to improve functionality and performance.
  • Documentation: Maintain detailed documentation of the script’s features, usage instructions, and any changes made over time.

Behavior and Performance Analysis

The script’s behavior and performance can be analyzed based on the following aspects:

1. Request Rate

The script is designed to send a maximum of 2 requests per second. This rate can be adjusted by modifying the pps variable. Monitoring the actual request rate and adjusting the script accordingly is crucial for accurate load testing.

2. Response Time

The duration of each request is logged, providing insights into the response time of the server under load. This helps in identifying performance issues and optimizing server configurations.

3. Resource Usage

Running the script generates a significant load on the system. Monitoring CPU and memory usage during the script execution is essential to ensure that it does not adversely affect the system’s performance.

4. Error Handling

The script logs the HTTP status code for each request. Analyzing these logs helps in identifying any errors or issues with the target URL and ensures that the server is handling requests as expected.