fix(handler): move auth before request validation so probe resistance works (#875)
Probe resistance (probeResist=code:403) was always returning 400 Bad Request instead of the configured status code because the non-proxy-form request validation check (req.URL.Scheme != "http") ran before Authenticate(). Browser/scanner probes send GET / HTTP/1.1 which has an empty URL scheme, so they were rejected at the validation gate before probe resistance ever had a chance to respond. Swap the order: run Authenticate() first so probe resistance can intercept non-proxy-form probes with the configured decoy response. Legitimate clients with correct credentials proceed to request validation and routing as before.
This commit is contained in:
+17
-14
@@ -445,20 +445,9 @@ func (h *httpHandler) handleRequest(ctx context.Context, conn net.Conn, req *htt
|
||||
ro.HTTP.Response.Header = resp.Header
|
||||
}()
|
||||
|
||||
// HTTP/2 connection preface "PRI * HTTP/2.0" is rejected, as are
|
||||
// non-CONNECT requests without an http:// scheme.
|
||||
if req.Method == "PRI" ||
|
||||
(req.Method != http.MethodConnect && req.URL.Scheme != "http") {
|
||||
resp.StatusCode = http.StatusBadRequest
|
||||
|
||||
if log.IsLevelEnabled(logger.TraceLevel) {
|
||||
dump, _ := httputil.DumpResponse(resp, false)
|
||||
log.Trace(string(dump))
|
||||
}
|
||||
|
||||
return resp.Write(conn)
|
||||
}
|
||||
|
||||
// Authenticate before request validation so that probe resistance
|
||||
// can intercept non-proxy-form requests (e.g., browser/scanner probes
|
||||
// that send "GET / HTTP/1.1" instead of proxy-form URLs).
|
||||
result := h.auth.Authenticate(ctx, req)
|
||||
if !result.OK {
|
||||
if result.PipeTo != "" {
|
||||
@@ -477,6 +466,20 @@ func (h *httpHandler) handleRequest(ctx context.Context, conn net.Conn, req *htt
|
||||
return errors.New("authentication failed")
|
||||
}
|
||||
|
||||
// HTTP/2 connection preface "PRI * HTTP/2.0" is rejected, as are
|
||||
// non-CONNECT requests without an http:// scheme.
|
||||
if req.Method == "PRI" ||
|
||||
(req.Method != http.MethodConnect && req.URL.Scheme != "http") {
|
||||
resp.StatusCode = http.StatusBadRequest
|
||||
|
||||
if log.IsLevelEnabled(logger.TraceLevel) {
|
||||
dump, _ := httputil.DumpResponse(resp, false)
|
||||
log.Trace(string(dump))
|
||||
}
|
||||
|
||||
return resp.Write(conn)
|
||||
}
|
||||
|
||||
log = log.WithFields(map[string]any{"clientID": result.ClientID})
|
||||
ro.ClientID = result.ClientID
|
||||
|
||||
|
||||
Reference in New Issue
Block a user