1
0
Fork 0

Print access logs for rejected requests and warn about new behavior

This commit is contained in:
Romain 2025-12-16 16:20:05 +01:00 committed by GitHub
parent e0e49533ab
commit 60b19b7b81
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 371 additions and 147 deletions

View file

@ -606,10 +606,6 @@ func createHTTPServer(ctx context.Context, ln net.Listener, configuration *stati
handler = normalizePath(handler)
handler = denyFragment(handler)
handler = denyEncodedCharacters(configuration.HTTP.EncodedCharacters.Map(), handler)
serverHTTP := &http.Server{
Protocols: &protocols,
Handler: handler,
@ -709,54 +705,6 @@ func encodeQuerySemicolons(h http.Handler) http.Handler {
})
}
// denyEncodedCharacters reject the request if the escaped path contains encoded characters.
func denyEncodedCharacters(encodedCharacters map[string]struct{}, h http.Handler) http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
escapedPath := req.URL.EscapedPath()
for i := 0; i < len(escapedPath); i++ {
if escapedPath[i] != '%' {
continue
}
// This should never happen as the standard library will reject requests containing invalid percent-encodings.
// This discards URLs with a percent character at the end.
if i+2 >= len(escapedPath) {
rw.WriteHeader(http.StatusBadRequest)
return
}
// This rejects a request with a path containing the given encoded characters.
if _, exists := encodedCharacters[escapedPath[i:i+3]]; exists {
log.FromContext(req.Context()).Debugf("Rejecting request because it contains encoded character %s in the URL path: %s", escapedPath[i:i+3], escapedPath)
rw.WriteHeader(http.StatusBadRequest)
return
}
i += 2
}
h.ServeHTTP(rw, req)
})
}
// When go receives an HTTP request, it assumes the absence of fragment URL.
// However, it is still possible to send a fragment in the request.
// In this case, Traefik will encode the '#' character, altering the request's intended meaning.
// To avoid this behavior, the following function rejects requests that include a fragment in the URL.
func denyFragment(h http.Handler) http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
if strings.Contains(req.URL.RawPath, "#") {
log.WithoutContext().Debugf("Rejecting request because it contains a fragment in the URL path: %s", req.URL.RawPath)
rw.WriteHeader(http.StatusBadRequest)
return
}
h.ServeHTTP(rw, req)
})
}
// sanitizePath removes the "..", "." and duplicate slash segments from the URL according to https://datatracker.ietf.org/doc/html/rfc3986#section-6.2.2.3.
// It cleans the request URL Path and RawPath, and updates the request URI.
func sanitizePath(h http.Handler) http.Handler {