feat(handler/http,http2): support comma-separated hostnames in probeResistance knock

Knock previously accepted a single hostname. Now it accepts multiple
comma-separated hostnames; probe resistance is bypassed if the request
hostname matches any entry in the list. Matching is case-insensitive
and whitespace around entries is trimmed.
This commit is contained in:
ginuerzh
2026-05-28 23:20:27 +08:00
parent 3246b39c93
commit c246a1d4fa
6 changed files with 163 additions and 7 deletions
+16 -1
View File
@@ -391,7 +391,7 @@ func (h *http2Handler) authenticate(ctx context.Context, w http.ResponseWriter,
pr := h.md.probeResistance
// probing resistance is enabled, and knocking host is mismatch.
if pr != nil && (pr.Knock == "" || !strings.EqualFold(r.URL.Hostname(), pr.Knock)) {
if pr != nil && (pr.Knock == "" || !knockMatch(r.URL.Hostname(), pr.Knock)) {
resp.StatusCode = http.StatusServiceUnavailable // default status code
switch pr.Type {
case "code":
@@ -536,3 +536,18 @@ func (h *http2Handler) observeStats(ctx context.Context) {
}
}
}
// knockMatch reports whether hostname matches any entry in the
// comma-separated knock list. Matching is case-insensitive. An empty
// knock string returns false (no match).
func knockMatch(hostname, knock string) bool {
if knock == "" {
return false
}
for _, h := range strings.Split(knock, ",") {
if strings.EqualFold(hostname, strings.TrimSpace(h)) {
return true
}
}
return false
}
+1 -1
View File
@@ -64,5 +64,5 @@ func (h *http2Handler) parseMetadata(md mdata.Metadata) error {
type probeResistance struct {
Type string
Value string
Knock string
Knock string // optional comma-separated hostnames; probe resistance only fires when the request hostname matches none of them
}