Golang编写的HTTP服务器如何防御DDoS攻击?

Golang编写的HTTP服务器如何防御DDoS攻击? 能否请您列出一些您已经应用过的策略或方法,来预防/保护/减少针对RESTful Web服务的DDOS攻击?

提前感谢。

4 回复

将您的Go代码运行在类似NGINX的反向代理之后。这有助于防范DDOS攻击

更多关于Golang编写的HTTP服务器如何防御DDoS攻击?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


虽然不是严格与DoS相关(我也不确定如何实现你的需求),但《如何在互联网上暴露Go服务》这篇文章提供了一些很好的建议。不过这篇文章已经发布一年多了,内容可能不是完全最新。

速率限制似乎是一种有效的方法,并且可以在中间件中轻松实现。Alex Edwards 有一篇关于如何限制 HTTP 请求速率的文章,我觉得很有用。当然,OWASP 始终是获取安全信息的绝佳资源。

在Go语言中,防御针对HTTP服务器的DDoS攻击需要结合多种策略,包括限流、连接管理、超时设置和中间件防护。以下是我在实际项目中应用的有效方法,附带示例代码。

1. 实现速率限制(Rate Limiting)

使用令牌桶算法限制每个客户端的请求频率,防止资源耗尽。Go标准库的golang.org/x/time/rate包非常适合此场景。

package main

import (
    "net/http"
    "golang.org/x/time/rate"
    "sync"
)

// IPRateLimiter 结构存储每个IP的限流器
type IPRateLimiter struct {
    ips map[string]*rate.Limiter
    mu  *sync.RWMutex
    r   rate.Limit
    b   int
}

// NewIPRateLimiter 初始化一个IPRateLimiter实例
func NewIPRateLimiter(r rate.Limit, b int) *IPRateLimiter {
    return &IPRateLimiter{
        ips: make(map[string]*rate.Limiter),
        mu:  &sync.RWMutex{},
        r:   r,
        b:   b,
    }
}

// AddIP 为指定IP创建限流器
func (i *IPRateLimiter) AddIP(ip string) *rate.Limiter {
    i.mu.Lock()
    defer i.mu.Unlock()
    limiter := rate.NewLimiter(i.r, i.b)
    i.ips[ip] = limiter
    return limiter
}

// GetLimiter 获取IP对应的限流器,不存在则创建
func (i *IPRateLimiter) GetLimiter(ip string) *rate.Limiter {
    i.mu.RLock()
    limiter, exists := i.ips[ip]
    i.mu.RUnlock()
    if !exists {
        return i.AddIP(ip)
    }
    return limiter
}

// rateLimitMiddleware 限流中间件
func rateLimitMiddleware(next http.Handler) http.Handler {
    limiter := NewIPRateLimiter(1, 5) // 每秒1个令牌,桶大小5
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        ip := r.RemoteAddr
        lim := limiter.GetLimiter(ip)
        if !lim.Allow() {
            http.Error(w, "Rate limit exceeded", http.StatusTooManyRequests)
            return
        }
        next.ServeHTTP(w, r)
    })
}

func main() {
    mux := http.NewServeMux()
    mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        w.Write([]byte("Hello, World!"))
    })
    // 应用限流中间件
    http.ListenAndServe(":8080", rateLimitMiddleware(mux))
}

2. 设置连接超时和读写超时

在HTTP服务器配置中定义超时,防止慢速连接占用资源。

package main

import (
    "net/http"
    "time"
)

func main() {
    mux := http.NewServeMux()
    mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        time.Sleep(2 * time.Second) // 模拟处理延迟
        w.Write([]byte("Hello, World!"))
    })

    server := &http.Server{
        Addr:         ":8080",
        Handler:      mux,
        ReadTimeout:  5 * time.Second,  // 读取请求超时
        WriteTimeout: 10 * time.Second, // 写入响应超时
        IdleTimeout:  15 * time.Second, // 空闲连接超时
    }
    server.ListenAndServe()
}

3. 使用反向代理和负载均衡器

在生产环境中,结合Nginx或HAProxy作为反向代理,提供额外的DDoS防护层,例如限制连接数和请求大小。以下是一个Nginx配置示例(非Go代码,但常与Go服务配合使用):

http {
    limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s;

    server {
        listen 80;
        location / {
            limit_req zone=one burst=20 nodelay;
            proxy_pass http://localhost:8080;
        }
    }
}

4. 实施IP黑名单/白名单

通过中间件过滤恶意IP地址。

package main

import (
    "net/http"
    "strings"
)

var blacklist = map[string]bool{
    "192.168.1.100": true,
    "10.0.0.5":      true,
}

func ipFilterMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        ip := strings.Split(r.RemoteAddr, ":")[0] // 提取IP部分
        if blacklist[ip] {
            http.Error(w, "Forbidden", http.StatusForbidden)
            return
        }
        next.ServeHTTP(w, r)
    })
}

func main() {
    mux := http.NewServeMux()
    mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        w.Write([]byte("Hello, World!"))
    })
    http.ListenAndServe(":8080", ipFilterMiddleware(mux))
}

5. 限制请求体大小

防止大请求体消耗内存。

package main

import (
    "net/http"
)

func maxBodySizeMiddleware(next http.Handler, maxSize int64) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        r.Body = http.MaxBytesReader(w, r.Body, maxSize)
        next.ServeHTTP(w, r)
    })
}

func main() {
    mux := http.NewServeMux()
    mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        w.Write([]byte("Hello, World!"))
    })
    // 限制请求体最大为1MB
    http.ListenAndServe(":8080", maxBodySizeMiddleware(mux, 1<<20))
}

这些方法结合使用,可以有效减轻DDoS攻击的影响。在实际部署中,建议监控服务指标并根据流量模式调整参数。

回到顶部