用 Go 写个极简反向代理,把 CC 攻击挡在业务容器之外

最近容器化改造,所有业务都跑在 K8s 里。某天 3 点 15 分,Prometheus 疯狂告警:某个业务 Pod CPU 飙到 200%,原因是 /api/search 接口被刷。传统的 WAF 在集群外,流量已经压到 Ingress 上了,再往上加规则来不及。于是干脆在业务前面再插一层 Go 写的「微型网关」,在流量进容器之前就把它丢掉。

1. 项目结构

tiny-guard/
├── main.go
├── limiter.go
├── go.mod

2. 核心代码

main.go(不到 120 行,可直接 go run):

package main

import (
    "log"
    "net/http"
    "net/http/httputil"
    "net/url"
    "sync"
    "time"
)

// 滑动窗口计数器
type window struct {
    mu        sync.RWMutex
    counter   int
    resetTime int64
}

var store = make(map[string]*window)

func getIP(r *http.Request) string {
    // 简单取 X-Forwarded-For 第一个
    ip := r.Header.Get("X-Forwarded-For")
    if ip == "" {
        ip = r.RemoteAddr
    }
    return ip
}

func allow(ip string) bool {
    w, ok := store[ip]
    if !ok {
        w = &window{}
        store[ip] = w
    }
    w.mu.Lock()
    defer w.mu.Unlock()

    now := time.Now().Unix()
    if now-w.resetTime > 60 {
        w.counter, w.resetTime = 0, now
    }

    w.counter++
    return w.counter <= 100 // 每分钟 100 次
}

func main() {
    target, _ := url.Parse("http://127.0.0.1:8080 ")
    proxy := httputil.NewSingleHostReverseProxy(target)

    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        ip := getIP(r)
        if !allow(ip) {
            http.Error(w, "too fast", http.StatusTooManyRequests)
            return
        }
        proxy.ServeHTTP(w, r)
    })

    log.Println("listening :9000")
    log.Fatal(http.ListenAndServe(":9000", nil))
}

3. 运行测试

go run .
# 另开窗口
ab -n 1000 -c 50 http://localhost:9000/api/search

观察日志,大量 429 Too Many Requests,后端 Pod CPU 立刻降回正常水位。

4. 进阶玩法

  • store 换成 Redis + TTL,就能在多个网关实例间共享。
  • 需要更高并发量?把限流逻辑换成令牌桶即可,代码量不超过 20 行。
  • 如果你不想自己维护网关镜像,直接给集群前面挂一个 高防 IP,厂商已经帮你把滑动窗口、令牌桶、人机验证都封装好了,剩下的就是配几条规则、喝杯咖啡等告警解除。

5. 一行部署

docker build -t tiny-guard .
kubectl apply -f k8s/deployment.yaml
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值