Skip to content

Commit

Permalink
updates
Browse files Browse the repository at this point in the history
  • Loading branch information
ao authored Feb 28, 2024
1 parent bd1a7a9 commit 05b30c4
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 82 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
goflood
.idea

27 changes: 27 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Use a lightweight base image
FROM golang:alpine AS builder

# Set the working directory
WORKDIR /app

# Copy the source code into the container
COPY ./src/ .

# Build the Go application
RUN go build -o app

# Use a minimal base image
FROM alpine:latest

# Set the working directory
WORKDIR /app

# Copy the built binary from the builder stage
COPY --from=builder /app/app /app/app

# Make the binary executable
RUN chmod +x /app/app

# Run the application
CMD ["/app/app"]

15 changes: 2 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,18 @@ A simple CLI tool that lets you make GET requests to a domain, and ignores the o

Packaged binaries for all platforms are available on the [GoFlood Github Release page](https://github.com/ao/goflood/releases/)


## Usage once Downloaded/Installed

### Option 1: Follow the wizard

You can simply run the CLI application and follow the prompts

```
./goflood
goflood
```

### Option 2: Specify the arguments

```
./goflood example.com 10 1
^ ^ ^
domain count batch
goflood -url=https://example.com -concurrency=500 -step=50 -duration=1m15s
```

#### Commandline Arguments

| argument | description | example value |
|----------|-------------|-------|
| domain | a domain name | example.com
| count | amount of concurrent reqs | 50 |
| batch | amount of times to repeat | 3 |
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module github.com/ao/goflood

go 1.17
go 1.19
16 changes: 0 additions & 16 deletions helper/helper.go

This file was deleted.

140 changes: 89 additions & 51 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,86 +1,124 @@
package main

import (
"flag"
"fmt"
"github.com/ao/goflood/helper"
"io/ioutil"
"log"
"net/http"
"os"
"strconv"
"os/signal"
"sync"
"sync/atomic"
"syscall"
"time"
)

func call(wg *sync.WaitGroup, domain string, userAgent string) {
func Banner() string {
return `
▄████ ▒█████ █████▒██▓ ▒█████ ▒█████ ▓█████▄
██▒ ▀█▒▒██▒ ██▒▓██ ▒▓██▒ ▒██▒ ██▒▒██▒ ██▒▒██▀ ██▌
▒██░▄▄▄░▒██░ ██▒▒████ ░▒██░ ▒██░ ██▒▒██░ ██▒░██ █▌
░▓█ ██▓▒██ ██░░▓█▒ ░▒██░ ▒██ ██░▒██ ██░░▓█▄ ▌
░▒▓███▀▒░ ████▓▒░░▒█░ ░██████▒░ ████▓▒░░ ████▓▒░░▒████▓
░▒ ▒ ░ ▒░▒░▒░ ▒ ░ ░ ▒░▓ ░░ ▒░▒░▒░ ░ ▒░▒░▒░ ▒▒▓ ▒
░ ░ ░ ▒ ▒░ ░ ░ ░ ▒ ░ ░ ▒ ▒░ ░ ▒ ▒░ ░ ▒ ▒
░ ░ ░ ░ ░ ░ ▒ ░ ░ ░ ░ ░ ░ ░ ▒ ░ ░ ░ ▒ ░ ░ ░
░ ░ ░ ░ ░ ░ ░ ░ ░ ░
`
}

func makeRequest(targetURL string, counter *int32, wg *sync.WaitGroup) {
defer atomic.AddInt32(counter, -1)
defer wg.Done()

client := &http.Client{}
start := time.Now()

req, err := http.NewRequest("GET", "http://"+domain, nil)
resp, err := http.Get(targetURL)
if err != nil {
log.Fatalln(err)
log.Printf("Error making request: %v\n", err)
return
}
defer resp.Body.Close()

req.Header.Set("User-Agent", userAgent)

resp, err := client.Do(req)
if err != nil {
log.Fatalln(err)
}
// Process response if needed

defer resp.Body.Close()
_, err = ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatalln(err)
if resp.StatusCode == http.StatusOK {
// Successful response handling
// You can add more metrics or processing here
}

fmt.Print(".")
// Print request duration
fmt.Printf("Request to %s took %s\n", targetURL, time.Since(start))
}

// main is the entry point for the load testing program. It parses command
// line flags, sets up interrupt handling for graceful shutdown, starts a
// specified number of goroutines to make requests to the target URL, and
// prints metrics after the specified duration.
func main() {
fmt.Println(helper.Banner())
var wg sync.WaitGroup
fmt.Println(Banner())

var targetURL string
var baseConcurrency, concurrencyStep int
var duration time.Duration
var showHelp bool

var domain string
var count int
var batch int
flag.StringVar(&targetURL, "url", "", "Target URL")
flag.IntVar(&baseConcurrency, "concurrency", 10, "Base Concurrency")
flag.IntVar(&concurrencyStep, "step", 1, "Concurrency Step")
flag.DurationVar(&duration, "duration", 10*time.Second, "Duration for which the program should run")
flag.BoolVar(&showHelp, "help", false, "Show help")

userAgents := map[string]string {
"0": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36",
"1": "Mozilla/5.0 (Macintosh; Intel Mac OS X 12_0_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36",
"2": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36",
"3": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/95.0.4638.50 Mobile/15E148 Safari/604.1",
"4": "Mozilla/5.0 (Linux; Android 10) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.50 Mobile Safari/537.36",
flag.Parse()

if targetURL == "" {
fmt.Println("Please specify a target URL")
flag.Usage()
os.Exit(0)
}

args := os.Args
if len(args)<4 {
if showHelp {
flag.Usage()
os.Exit(0)
}

fmt.Println("Enter a domain name (example.com): ")
fmt.Scanln(&domain)
var wg sync.WaitGroup
var counter int32

fmt.Println("Enter a count (10): ")
fmt.Scanln(&count)
// Interrupt handling for graceful shutdown
stop := make(chan os.Signal, 1)
signal.Notify(stop, syscall.SIGINT, syscall.SIGTERM)

fmt.Println("Enter a batch: (1): ")
fmt.Scanln(&batch)
} else {
domain = args[1]
count, _ = strconv.Atoi(args[2])
batch, _ = strconv.Atoi(args[3])
}
go func() {
<-stop
wg.Wait() // Wait for ongoing requests to finish
os.Exit(0)
}()

startTime := time.Now()

fmt.Println("Flooding "+domain+" "+strconv.Itoa(count)+" times, in "+strconv.Itoa(batch)+" batches")
timer := time.NewTimer(duration)

for i := 1; i <= batch; i++ {
fmt.Println("Batch #"+strconv.Itoa(i))
wg.Add(count)
for i := 0; i < count; i++ {
go call(&wg, domain, userAgents["0"])
for concurrency := baseConcurrency; concurrency <= baseConcurrency+concurrencyStep; concurrency += concurrencyStep {
for i := 0; i < concurrency; i++ {
wg.Add(1)
atomic.AddInt32(&counter, 1)
go makeRequest(targetURL, &counter, &wg)
}
wg.Wait()
fmt.Println("Done")
}

fmt.Println("Complete")
<-timer.C // Wait for the specified duration

// Wait until all requests are done
for atomic.LoadInt32(&counter) > 0 {
time.Sleep(100 * time.Millisecond)
}

elapsed := time.Since(startTime)

fmt.Printf("Target URL: %s\n", targetURL)
fmt.Printf("Base Concurrency: %d\n", baseConcurrency)
fmt.Printf("Concurrency Step: %d\n", concurrencyStep)
fmt.Printf("Duration: %s\n", elapsed)
}

0 comments on commit 05b30c4

Please sign in to comment.