Description
Engine.Handler() initialises http2.Server without setting ReadTimeout and WriteTimeout to adequate values, which leaves them to their default off values.
This expose the http server to slowloris DDoS attacks when dealing with untrusted clients.
You would be leaking connections and run out of descriptors..
How to reproduce
You start a new engine with any of the Run methods.
(...)
gin.SetMode(gin.ReleaseMode)
router = gin.New()
router.RunTLS("some ost url", "some ssl certificate", "some ssl key")
(...)
Expectations
The method Engine.Handler() should initialise the http server with proper timeout values so it doesn't expose it to the issue explained above.
i.e.
server := &http2.Server{
(...),
ReadTimeout: 5 * time.Second,
WriteTimeout: 10 * time.Second,
(...),
}
Actual result
func (engine *Engine) Handler() http.Handler {
if !engine.UseH2C {
return engine
}
h2s := &http2.Server{}
return h2c.NewHandler(engine, h2s)
}
Environment
- go version:
go1.19.1 - gin version (or commit ref):
github.com/gin-gonic/gin v1.8.1 - operating system:
Linux bach 4.9.0-16-amd64 #1 SMP Debian 4.9.272-2 (2021-07-19) x86_64 GNU/Linux
Comment From: Cookiery
I think you can create a timeout middleware. Reference: https://gist.github.com/montanaflynn/ef9e7b9cd21b355cfe8332b4f20163c1
Comment From: araujo88
http2.Server doesn't have a ReadTimeout or WriteTimeout fields, but it does have a IdleTimeout field. Should this field be set to a default value when calling Engine.Handler()?
func (engine *Engine) Handler() http.Handler {
if !engine.UseH2C {
return engine
}
h2s := &http2.Server{
IdleTimeout: 10 * time.Second, // sets IdleTimeout default value to 10 seconds
}
return h2c.NewHandler(engine, h2s)
}
Comment From: FirePing32
@appleboy shouldn't we provide a way to call the handler with user-defined params for such cases?