From 132b2ed85363a5074b15ced0923da6ff9b6b1f01 Mon Sep 17 00:00:00 2001 From: Xe Iaso Date: Mon, 14 Jul 2025 23:31:33 -0400 Subject: [PATCH] feat(cmd/anubis): capture ja4h fingerprints (#834) This is not used yet, but it will be part of a larger strategy around adding/removing weight based on JA4H (and other) fingerprint matches with Thoth. Signed-off-by: Xe Iaso --- .github/actions/spelling/allow.txt | 1 + cmd/anubis/main.go | 1 + docs/docs/CHANGELOG.md | 1 + go.mod | 1 + go.sum | 2 ++ internal/ja4h.go | 14 ++++++++++++++ 6 files changed, 20 insertions(+) create mode 100644 internal/ja4h.go diff --git a/.github/actions/spelling/allow.txt b/.github/actions/spelling/allow.txt index 6156761..64dd9a9 100644 --- a/.github/actions/spelling/allow.txt +++ b/.github/actions/spelling/allow.txt @@ -3,3 +3,4 @@ https ssh ubuntu workarounds +rjack \ No newline at end of file diff --git a/cmd/anubis/main.go b/cmd/anubis/main.go index ce77e7e..500b804 100644 --- a/cmd/anubis/main.go +++ b/cmd/anubis/main.go @@ -413,6 +413,7 @@ func main() { h = internal.RemoteXRealIP(*useRemoteAddress, *bindNetwork, h) h = internal.XForwardedForToXRealIP(h) h = internal.XForwardedForUpdate(*xffStripPrivate, h) + h = internal.JA4H(h) srv := http.Server{Handler: h, ErrorLog: internal.GetFilteredHTTPLogger()} listener, listenerUrl := setupListener(*bindNetwork, *bind) diff --git a/docs/docs/CHANGELOG.md b/docs/docs/CHANGELOG.md index 43e2196..7e0622e 100644 --- a/docs/docs/CHANGELOG.md +++ b/docs/docs/CHANGELOG.md @@ -102,6 +102,7 @@ There are a bunch of other assorted features and fixes too: - A race condition involving [opening two challenge pages at once in different tabs](https://github.com/TecharoHQ/anubis/issues/832) causing one of them to fail has been fixed. - The "Try again" button on the error page has been fixed. Previously it meant "try the solution again" instead of "try the challenge again". - In certain cases, a user could be stuck with a test cookie that is invalid, locking them out of the service for up to half an hour. This has been fixed with better validation of this case and clearing the cookie. +- Start exposing JA4H fingerprints for later use in CEL expressions. ### Potentially breaking changes diff --git a/go.mod b/go.mod index 50971f9..c5562db 100644 --- a/go.mod +++ b/go.mod @@ -14,6 +14,7 @@ require ( github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.1.0 github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2 github.com/joho/godotenv v1.5.1 + github.com/lum8rjack/go-ja4h v0.0.0-20250606032308-3a989c6635be github.com/nicksnyder/go-i18n/v2 v2.6.0 github.com/playwright-community/playwright-go v0.5200.0 github.com/prometheus/client_golang v1.22.0 diff --git a/go.sum b/go.sum index 3d2a32a..54da370 100644 --- a/go.sum +++ b/go.sum @@ -253,6 +253,8 @@ github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= +github.com/lum8rjack/go-ja4h v0.0.0-20250606032308-3a989c6635be h1:dVIND0nXGXPQnFZYrMXT6CxHhBYhTPMm0GFqcmfaIC4= +github.com/lum8rjack/go-ja4h v0.0.0-20250606032308-3a989c6635be/go.mod h1:q68TUR45WDa2r3yU4aO6WgxfCc0Vj1qtRaKaRE3yMLM= github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE= github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= diff --git a/internal/ja4h.go b/internal/ja4h.go new file mode 100644 index 0000000..d4c8c1d --- /dev/null +++ b/internal/ja4h.go @@ -0,0 +1,14 @@ +package internal + +import ( + "net/http" + + "github.com/lum8rjack/go-ja4h" +) + +func JA4H(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + r.Header.Add("X-Http-Fingerprint-JA4H", ja4h.JA4H(r)) + next.ServeHTTP(w, r) + }) +}