Я хочу написать небольшую часть промежуточного программного обеспечения для ограничения скорости, которое:
- Позволяет установить разумную скорость (например, 10 req/s) на один удаленный IP
- Возможно (но это не обязательно) допускать всплески
- Удаляет (закрывает?) соединения, которые превышают скорость и возвращает HTTP 429
Затем я могу обернуть это вокруг маршрутов аутентификации или других маршрутов, которые могут быть уязвимы для атак с грубой силой (т.е. пароля reset с использованием токена, который истекает и т.д.). Шансы на то, что кто-то грубо забивает маркер 16 или 24 байта, действительно низки, но это не помешает сделать этот дополнительный шаг.
Я посмотрел https://code.google.com/p/go-wiki/wiki/RateLimiting, но не уверен, как смириться с http.Request(s). Кроме того, я не уверен, как мы будем "отслеживать" запросы от определенного IP-адреса в течение любого периода времени.
В идеале я получаю что-то вроде этого, отмечая, что я за обратным прокси (nginx), поэтому мы проверяем HTTP-заголовок REMOTE_ADDR
вместо использования r.RemoteAddr
:
// Rate-limiting middleware
func rateLimit(h http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
remoteIP := r.Header.Get("REMOTE_ADDR")
for req := range (what here?) {
// what here?
// w.WriteHeader(429) and close the request if it exceeds the limit
// else pass to the next handler in the chain
h.ServeHTTP(w, r)
}
}
// Example routes
r.HandleFunc("/login", use(loginForm, rateLimit, csrf)
r.HandleFunc("/form", use(editHandler, rateLimit, csrf)
// Middleware wrapper, for context
func use(h http.HandlerFunc, middleware ...func(http.HandlerFunc) http.HandlerFunc) http.HandlerFunc {
for _, m := range middleware {
h = m(h)
}
return h
}
Я был бы признателен за некоторые рекомендации здесь.