Go for Cyber Security

Build blazingly fast security tools with Go - concurrent port scanners, web crawlers, and network analysis tools with built-in concurrency.

Why Go for Security

Go (Golang) is the language of modern security tooling. Tools like Nuclei, Subfinder, httpx, Naabu, and Amass are all written in Go, making it essential for security professionals.

  • Blazing fast - Compiled to native binary, no interpreter overhead.
  • Built-in concurrency - Goroutines and channels make parallel scanning trivial.
  • Single binary - Compile to one executable, deploy anywhere.
  • Strong standard library - Networking, crypto, HTTP built-in.
  • Industry tools - Nuclei, Subfinder, httpx, Naabu, Amass are all Go.

Go Basics

go
package main

import (
    "fmt"
    "net"
    "time"
)

// Struct for scan results
type ScanResult struct {
    Port    int
    Open    bool
    Service string
    Banner  string
}

// Map for service lookup
var services = map[int]string{
    22: "SSH", 80: "HTTP", 443: "HTTPS",
    3306: "MySQL", 8080: "HTTP-Alt",
}

func checkPort(host string, port int) ScanResult {
    addr := fmt.Sprintf("%s:%d", host, port)
    conn, err := net.DialTimeout("tcp", addr, 1*time.Second)
    if err != nil {
        return ScanResult{Port: port, Open: false}
    }
    conn.Close()
    svc := services[port]
    if svc == "" { svc = "Unknown" }
    return ScanResult{Port: port, Open: true, Service: svc}
}

func main() {
    target := "192.168.1.1"
    for port := 1; port <= 1024; port++ {
        result := checkPort(target, port)
        if result.Open {
            fmt.Printf("[+] Port %d: %s\n", result.Port, result.Service)
        }
    }
}

Goroutines & Channels

go
package main

import (
    "fmt"
    "net"
    "sync"
    "time"
)

// Channel for collecting results
func concurrentScan(host string, start, end int, maxWorkers int) []ScanResult {
    results := []ScanResult{}
    var mu sync.Mutex
    var wg sync.WaitGroup

    // Worker pool pattern
    sem := make(chan struct{}, maxWorkers)

    for port := start; port <= end; port++ {
        wg.Add(1)
        go func(p int) {
            defer wg.Done()
            sem <- struct{}{}        // Acquire slot
            defer func() { <-sem }() // Release slot

            result := checkPort(host, p)
            if result.Open {
                mu.Lock()
                results = append(results, result)
                mu.Unlock()
                fmt.Printf("[+] Port %d: %s\n", result.Port, result.Service)
            }
        }(port)
    }

    wg.Wait()
    return results
}

func main() {
    start := time.Now()
    results := concurrentScan("192.168.1.1", 1, 65535, 1000)
    elapsed := time.Since(start)
    fmt.Printf("\nScanned 65535 ports in %v\n", elapsed)
    fmt.Printf("Found %d open ports\n", len(results))
}

Network Programming

go - banner_grab.go
package main

import (
    "bufio"
    "fmt"
    "net"
    "strings"
    "time"
)

func grabBanner(host string, port int) (string, error) {
    addr := fmt.Sprintf("%s:%d", host, port)
    conn, err := net.DialTimeout("tcp", addr, 5*time.Second)
    if err != nil {
        return "", err
    }
    defer conn.Close()
    conn.SetReadDeadline(time.Now().Add(3 * time.Second))

    // Send HTTP request to grab banner
    fmt.Fprintf(conn, "HEAD / HTTP/1.1\r\nHost: %s\r\n\r\n", host)
    reader := bufio.NewReader(conn)
    line, _ := reader.ReadString('\n')
    return strings.TrimSpace(line), nil
}

func main() {
    ports := []int{21, 22, 25, 80, 443}
    for _, port := range ports {
        banner, err := grabBanner("192.168.1.1", port)
        if err == nil && banner != "" {
            fmt.Printf("Port %d: %s\n", port, banner)
        }
    }
}

Fast Port Scanner

go - scanner/main.go
package main

import (
    "encoding/json"
    "flag"
    "fmt"
    "net"
    "os"
    "sync"
    "time"
)

type Result struct {
    Port    int    `json:"port"`
    State   string `json:"state"`
    Service string `json:"service"`
}

func scan(target string, port int, timeout time.Duration) Result {
    addr := fmt.Sprintf("%s:%d", target, port)
    conn, err := net.DialTimeout("tcp", addr, timeout)
    if err != nil {
        return Result{Port: port, State: "closed"}
    }
    conn.Close()
    return Result{Port: port, State: "open"}
}

func main() {
    target := flag.String("target", "127.0.0.1", "Target host")
    workers := flag.Int("workers", 1000, "Concurrent workers")
    flag.Parse()

    var results []Result
    var mu sync.Mutex
    var wg sync.WaitGroup
    sem := make(chan struct{}, *workers)

    start := time.Now()
    fmt.Printf("[*] Scanning %s with %d workers\n", *target, *workers)

    for port := 1; port <= 65535; port++ {
        wg.Add(1)
        go func(p int) {
            defer wg.Done()
            sem <- struct{}{}
            defer func() { <-sem }()

            r := scan(*target, p, 1*time.Second)
            if r.State == "open" {
                mu.Lock()
                results = append(results, r)
                mu.Unlock()
                fmt.Printf("[+] Port %d OPEN\n", p)
            }
        }(port)
    }

    wg.Wait()
    elapsed := time.Since(start)

    // Save JSON report
    data, _ := json.MarshalIndent(results, "", "  ")
    os.WriteFile("scan_results.json", data, 0644)

    fmt.Printf("\n[*] Complete: %d open ports in %v\n", len(results), elapsed)
}

Web Crawler

go - crawler.go
package main

import (
    "fmt"
    "io"
    "net/http"
    "regexp"
    "strings"
)

func crawl(url string) []string {
    resp, err := http.Get(url)
    if err != nil {
        return nil
    }
    defer resp.Body.Close()

    body, _ := io.ReadAll(resp.Body)
    content := string(body)

    // Extract links
    re := regexp.MustCompile(`href="([^"]*)"`)
    matches := re.FindAllStringSubmatch(content, -1)

    var links []string
    for _, m := range matches {
        link := m[1]
        if strings.HasPrefix(link, "http") || strings.HasPrefix(link, "/") {
            links = append(links, link)
        }
    }
    return links
}

func main() {
    links := crawl("http://example.com")
    fmt.Printf("Found %d links:\n", len(links))
    for _, l := range links {
        fmt.Println(l)
    }
}
Practice

Study the source code of popular Go security tools: Nuclei (projectdiscovery/nuclei), Subfinder, httpx, and Naabu on GitHub.

Resources

Type to start searching...