Documentation
¶
Overview ¶
Package signals tells people from bots and recognizes devices, from what the server sees of each request: its TLS ClientHello (JA4), its HTTP/2 settings and the order of its headers, how its headers fit the browser its User-Agent claims, and, optionally, a client check in the browser with a proof of work. It is for an app's own security: blocking abuse, limiting rates per client, noticing a sign-in from a new device. It doesn't follow people across sites, and it keeps nothing.
sig := signals.New(signals.Options{Check: true})
ternApp(kit.WithPlugins(sig))
func Actions… {
if s := signals.Of(c); s.Verdict == signals.Bot { … }
}
The TLS and HTTP/2 fingerprints need the App to terminate TLS itself (kit.WithAutoTLS, kit.WithTLS). Behind a proxy that terminates it, the proxy can pass its JA4 on in a header (Options.JA4Header); the rest of the signals work anywhere.
Index ¶
Constants ¶
const ( Human = "human" Suspicious = "suspicious" Bot = "bot" )
Verdicts.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Client ¶
type Client struct {
// Browser is Chrome, Edge, Opera, Samsung Internet, Firefox or Safari,
// or "" for anything else.
Browser string `json:"browser,omitempty"`
// Version is the browser's major version.
Version int `json:"version,omitempty"`
// OS is Windows, macOS, iOS, Android, Linux or ChromeOS, or "".
OS string `json:"os,omitempty"`
Mobile bool `json:"mobile,omitempty"`
// Crawler names a search engine or other crawler that says it is one,
// such as Googlebot. It says nothing of whether it's true.
Crawler string `json:"crawler,omitempty"`
// Tool names an HTTP library or automation tool, such as curl,
// python-requests or HeadlessChrome.
Tool string `json:"tool,omitempty"`
}
Client is what a request's User-Agent says it is.
type Options ¶
type Options struct {
// Check adds the client check to every page: a script that solves a
// small proof of work and looks for signs of automation, once a day
// per browser. Signals.Checked tells who passed.
Check bool
// Difficulty is the check's proof of work, in leading zero bits of a
// SHA-256. Each bit doubles the work; the default, 16, takes a phone
// a fraction of a second.
Difficulty int
// Secret signs the check's challenges and results. The default is
// TERN_SECRET's; without either, a random one is made at start, and
// browsers check again after a restart.
Secret string
// Block answers requests that change things (POST, PUT, PATCH,
// DELETE) with 403 when their score is Block or more. 0 blocks
// nothing; the app decides with Of.
Block int
// JA4Header names a header with the client's JA4 fingerprint, set by
// a proxy that terminates TLS in front of the App, such as
// Cloudflare's. It is read only from proxies the App trusts
// (kit.WithTrustedProxies).
JA4Header string
// DeviceCookie names the cookie that identifies a device. The default
// is "tern_device".
DeviceCookie string
}
Options configures the plugin.
type Plugin ¶
type Plugin struct {
// contains filtered or unexported fields
}
Plugin computes the signals. Make it with New.
type Signals ¶
type Signals struct {
// Score is 0 for a request that looks like a person's browser, up to
// 100 for one that is plainly automated.
Score int `json:"score"`
// Verdict is Human (score under 30), Suspicious (under 70) or Bot.
Verdict string `json:"verdict"`
// Reasons are codes for what raised or lowered the score, such as
// "tool:curl" or "tls-no-grease"; docs/signals.md lists them.
Reasons []string `json:"reasons,omitempty"`
// Client is what the User-Agent claims.
Client Client `json:"client"`
// JA4 is the TLS client fingerprint, when known.
JA4 string `json:"ja4,omitempty"`
// HTTP2 is the HTTP/2 fingerprint (SETTINGS, WINDOW_UPDATE, PRIORITY
// and pseudo-header order), for HTTP/2 requests to the App's own TLS.
HTTP2 string `json:"http2,omitempty"`
// Headers fingerprints the request's headers: JA4H's first two parts,
// from the method, version, header count, language and the header
// names in the order sent.
Headers string `json:"headers,omitempty"`
// Proto is the HTTP version.
Proto string `json:"proto"`
// Checked reports that this browser passed the client check
// (Options.Check) within the day.
Checked bool `json:"checked"`
// Device identifies the browser, from a cookie, with Of; NewDevice
// reports that the cookie was set by this request.
Device string `json:"device,omitempty"`
NewDevice bool `json:"newDevice,omitempty"`
}
Signals are what the plugin found of a request.