fingerprint

package
v1.0.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 16, 2026 License: MIT Imports: 18 Imported by: 0

README

fingerprint — TLS, HTTP/2, HTTP/3 and HTTP/1 fingerprinting

fingerprint turns a raw TLS ClientHello (plus the first HTTP frames a client sends) into a set of well-known passive fingerprints — JA3, JA4, PeetPrint, the Akamai HTTP/2 fingerprint, an HTTP/3 settings fingerprint and an HTTP/1 header order fingerprint — together with a human-readable breakdown of the handshake.

It is the fingerprinting core of the server: every accepted connection is parsed once, and all fingerprint formats are derived from that single parse.

Pipeline overview

raw bytes (first TLS record)
        │  ParseClientHello()            ┌──────────────┐
        ▼                                │ TLSDetails   │
   ClientHello struct ──► CalculateJA3() │  JA3/JA3Hash │
        │  └► JA3Calculating (Parse +    │  JA4/JA4_r   │
        │     Calculate)                 │  PeetPrint…  │
        │  CalculatePeetPrint()          │  Ciphers,    │
        │  CalculateJa4() / QUIC         │  Extensions… │
        ▼                                └──────────────┘
   HTTP/2 frames  ──► GetAkamaiFingerprint()   (settings|window|priority|header order)
   HTTP/3 settings ─► GetHTTP3SettingsFingerprint() (+ hash, header order)
   HTTP/1 headers  ─► GetHTTP1HeaderOrderFingerprint() (+ hash)
   TCP/IP capture ──► SniffTCP()                (IP + TCP details, pcap)

All fingerprints are computed from one ClientHello parse, so they are mutually consistent (same cipher list, same extension list, …). The TCP/IP fingerprint is the exception: it is captured passively on the network interface (see TCP/IP fingerprinting) and attached to requests by the server.

1. ClientHello parsing (client_hello.go)

ParseClientHello(data []byte) (*ClientHello, error) parses the TLS record layer and the handshake message from raw bytes:

  • parsePacketType reads the record type (must be 0x16, handshake) and the handshake message type (must be 0x01, ClientHello). Any other packet type aborts parsing — the server only ever fingerprints TLS handshakes.
  • parseExtensions(raw []byte) ([]Extension, error) walks the extension block: each entry is a 2-byte type + 2-byte length + payload. Known extension types are further parsed; unknown ones are kept as raw data. A malformed/truncated extension aborts the walk (break) instead of panicking, so garbage input yields a partial but usable fingerprint.

The parsed ClientHello carries, among others:

Field Source
Version / RecordVersion record-layer version (e.g. 771 = TLS 1.2)
Random the 32-byte client random (hex)
SessionID legacy session id
CipherSuites raw suite IDs
CompressionMethods legacy compression list
SupportedProtos ALPN (application_layer_protocol_negotiation)
SupportedVersions supported_versions extension values
SupportedCurves supported_groups extension
SupportedPoints ec_point_formats extension
SignatureAlgorithms signature_algorithms extension
PSKKeyExchangeMode psk_key_exchange_modes extension
CertCompressionAlgorithms compress_certificate extension
AllExtensions numeric IDs of every extension seen, in wire order
Extensions full per-extension detail (length, payload, parsed fields)

Extension sub-parsers include ParseSNI, ParseSupportedGroups, ParseSignatureAlgorithms, ParseALPN, ParseKeyShare, ParseSupportedVersions, ParsePSKKeyExchangeModes and ParseCertCompressionAlgorithms. Lists that may arrive out of order are stored in wire order; fingerprint code that needs stability sorts explicitly (see PeetPrint extensions below).

Lookup tables (handshake.go)

handshake.go contains the reference tables used to make fingerprints readable:

  • GetCipherSuiteName(id uint16) — TLS cipher suite ID → IANA-style name (49199TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256). Unknown values fall back to TLS_UNKNOWN.
  • GetExtensionNameByID, GetCurveNameByID, GetSignatureNameByID — the same for extensions (server_name…), curves (secp256r1…), signature algorithms (ecdsa_secp256r1_sha256…).
  • GreaseValues + IsGrease(value string) — the 16 GREASE values (0x0A0A0xFAFA). GREASE (Generate Random Extensions And Sustain Extensibility, RFC 8701) lets clients probe server extensibility with reserved values; because clients randomize them, GREASE values must not appear as literal numbers in a stable fingerprint — they are replaced by the token GREASE.

2. JA3 (tls.go)

JA3 is the de-facto standard TLS fingerprint (Salesforce, 2017):

SSLVersion,Ciphers-Extensions-Curves,Points        (dash-joined, comma-separated fields)

The JA3Calculating type is the pipeline:

  1. CalculateJA3(parsed ClientHello) JA3Calculating copies the raw numeric lists (AllCiphers, AllCurves, AllPoints, AllExtensions), the record version, and the non-GREASE supported_versions list into a new JA3Calculating, then runs Parse() and Calculate().
  2. Parse() walks the raw lists once and splits them into three parallel views:
    • JA3Ciphers / JA3Extensions / JA3Curves / JA3Points — decimal strings used for the JA3 string itself;
    • ReadableCiphers — the IANA names (via GetCipherSuiteName), for the human-readable JSON output;
    • PeetPrintCiphers / PeetPrintExtensions / PeetPrintCurves — used by PeetPrint, where GREASE values are replaced by the literal token GREASE (detected via the zero-padded hex form, e.g. 0x0A0A). GREASE filtering happens here: GREASE ciphers/extensions/curves are excluded from the JA3 string (JA3 has no GREASE token) but kept as GREASE in the PeetPrint lists. Curve 6969 (0x1B39) is additionally treated as GREASE — a compatibility quirk of this implementation, since some clients send it as a reserved value.
  3. Calculate() joins the parts into Version,Ciphers-Extensions-Curves,Points and sets JA3Hash to the MD5 of that string — the hash is what most tools (e.g. ja3er.com) actually compare.

Note that JA3's extension list is the raw wire order (JA3 predates extension randomization awareness), while PeetPrint sorts it.

3. JA4 (ja4.go)

JA4 (FoxIO, 2023) fixes JA3's weaknesses: it uses sorted lists, replaces random values with counts, and hashes with SHA-256 truncated to 12 hex chars. Format: ja4a_ja4b_ja4c.

  • ja4a — the “human-readable” part, built as a single token: proto + tlsVersion + sniMode + suiteCount + extCount + firstALPN
    • proto: t (TCP) or q (QUIC, CalculateJa4QUIC);
    • tlsVersion: the negotiated version mapped to JA4 codes (77112, 77213), falling back to the raw value via getOrReturnOG;
    • sniMode: d (domain) or i (IP — note: always d in this implementation, the SNI type is not distinguished);
    • suiteCount / extCount: number of cipher suites / extensions as two lowercase hex digits;
    • firstALPN: first ALPN protocol mapped (h2h2, http/1.1h1, h3h3).
  • ja4b — cipher suites: every suite converted to lowercase 4-digit hex, sorted ascending, joined with , (ja4b_r = the raw sorted string); ja4b is SHA256trunc(raw).
  • ja4c — extensions plus signature algorithms: extensions converted to lowercase hex, GREASE/padding values (0010 padding, 0000, 0015 padding) filtered out, sorted, joined with ,; then _; then the signature algorithms as lowercase hex (GREASE token skipped), unsorted. ja4c is SHA256trunc(raw).

CalculateJa4 / CalculateJa4_r return a_b_c / a_b_r_c_r; the QUIC variants reuse the same b/c parts with q as the proto.

4. PeetPrint (tls.go)

PeetPrint (a.k.a. the “TCP fingerprint” from tls.peet.ws) is a pipe-joined 8-field string that keeps readable values instead of hashes:

tls_versions|protos|groups|sig_algs|key_mode|comp_algs|suites|extensions
  1. tls_versions — dash-joined supported_versions values; GREASE versions (parsed as -1) become the token GREASE.
  2. protos — ALPN protocols normalized: h22, http/1.11.1, http/1.01.0 (other values are dropped).
  3. groups — the PeetPrintCurves list from Parse() (GREASE-aware).
  4. sig_algs — dash-joined signature algorithms via joinSignatureAlgorithms, which flags GREASE values as GREASE instead of emitting the (randomized) number.
  5. key_mode — the PSK key exchange mode, as sent.
  6. comp_algs — dash-joined certificate compression algorithms.
  7. suites — the PeetPrintCiphers list (GREASE-aware, wire order).
  8. extensionsPeetPrintExtensions sorted alphabetically, because modern clients randomize extension order (this is the key difference to JA3, which keeps wire order).

The second return value is GetMD5Hash(fp) — the PeetPrint hash used by tls.peet.ws style databases.

5. Akamai HTTP/2 fingerprint (h2.go)

Based on the Black Hat EU 2017 paper Passive Fingerprinting of HTTP/2 Clients (Shuster). Computed from the first HTTP/2 frames the client sends, after the connection preface (see parseHTTP2 in the server):

settings|window_update|priorities|pseudo_header_order
  • settings — the client's SETTINGS frame as id:value;id:value;… using the names (HEADER_TABLE_SIZE:4096;MAX_CONCURRENT_STREAMS:100;…), mapped through a small table (settings 16, 9). Malformed entries are skipped rather than polluting the fingerprint. Only the first SETTINGS frame is considered.
  • window_update — the WINDOW_UPDATE increment value; 0 if none was sent (only the first frame is used).
  • priorities — every PRIORITY frame as stream:exclusive:depends_on:weight, comma-joined; 0 if none.
  • pseudo_header_order — the initials of the pseudo-headers of the first HEADERS frame in the order sent (:methodm, :authoritya, :schemes, :pathp), comma-joined.

Http2Details in the response JSON carries the fingerprint plus AkamaiFingerprintHash (MD5) and the raw parsed frames (sent_frames).

6. HTTP/3 fingerprint (h3.go)

HTTP/3 (QUIC) has no HPACK settings — its SETTINGS frame is a separate QUIC frame type. The fingerprint is:

id:value;id:value;…|header_order
  • settings — raw id:value pairs in wire order (1:16384;6:16384;…); GetHTTP3SettingName resolves known IDs (SETTINGS_QPACK_MAX_TABLE_CAPACITY, SETTINGS_MAX_FIELD_SECTION_SIZE, SETTINGS_QPACK_BLOCKED_STREAMS, SETTINGS_ENABLE_CONNECT_PROTOCOL, SETTINGS_H3_DATAGRAM), flags GREASE settings ((id-0x21) % 0x1f == 0), and falls back to UNKNOWN_<id>.
  • header_order — the first letters of the pseudo-headers of the first request headers, comma-joined (m,a,s,p), via GetHTTP3HeaderOrder.

GetHTTP3FingerprintHash is the MD5 of the whole string. The QUIC layer also produces Http3Details (0-RTT usage, datagram support, QUIC version, GSO) and a JA4 with the q proto.

7. HTTP/1 header order (h1.go)

The simplest fingerprint in the package:

host|user-agent|accept|accept-language|…

GetHTTP1HeaderOrderFingerprint lowercases every header name of the request and joins them in the exact order sent, pipe-separated. Header order is a strong HTTP/1 client discriminator because browsers and bots emit headers in fixed but different orders. The server stores it (plus its MD5 hash) in Http1Details.HeaderOrderFingerprint(Hash).

8. TCP/IP fingerprinting (tcp.go)

Passive TCP/IP fingerprinting captures packets on the network interface (the TLS port) and records the client's IP and TCP header details — TTL, TOS, window size, MSS, TCP option order and timestamps are all strong signals for identifying the client's TCP/IP stack (e.g. a browser on Windows vs a custom bot).

SniffTCP(device, tlsPort, fingerprints, stop) opens the device with pcap.OpenLive (via github.com/malivvan/gopacket, a CGO-free fork of gopacket that loads libpcap with purego), iterates the captured packets and, for every TCP SYN packet destined for tlsPort (the client's initial handshake packet, which carries the fingerprint signals), stores a TCPIPDetails value keyed by "sourceIP:sourcePort" in the provided *sync.Map. Closing stop closes the pcap handle and ends the capture loop.

  • IPDetails — IPv4 (ID, TOS, TTL, …) or IPv6 (hop limit) header fields.
  • TCPDetails — ACK/checksum/flags, sequence, window, urgent pointer, header length, plus the TCP options: Options (comma-joined option names such as MSS,Nop,WindowScale,SACKPermitted,Timestamps), OptionsOrder (the option kind numbers in wire order, e.g. 2,1,3,4,8,0), MSS, Timestamp and TimestampEchoReply extracted from the option payloads.
  • TCPIPDetails — the combination of both, with capture length and ports.

The server attaches the captured fingerprint to matching requests as Request.Fingerprint.TCPIP (the Server.SniffDevice field enables the capture; see the server package).

9. Utilities (utils.go)

  • GetMD5Hash(text) — hex MD5 (used for JA3/PeetPrint/Akamai/H1 hashes).
  • SHA256trunc(in) — hex SHA-256 truncated to 12 characters (JA4's b/c).
  • ToHexAll(in, filterOut, shouldSort) — converts decimal strings to lowercase hex, optionally filtering GREASE and optionally sorting (JA4 internals).
  • GetAllFlags(frame) — the HTTP/2 frame's flag names in numeric order (used by the server's HTTP/2 frame parser); getKeysInOrder is its internal numeric sort of flag map keys.
  • SplitBytesIntoChunks(buf, lim) — chunk a byte slice; used for frame reassembly.
  • SortByVal(m, x) — sort a map[string]int by value (top-x), used by extension/flag reporting.
  • ReadFile / WriteToFile — small file helpers shared with the server package.

Notes on determinism

  • JA3: ciphers/extensions/curves in wire order (client-dependent).
  • PeetPrint: extensions sorted, everything else in wire order; GREASE values always rendered as GREASE so randomized values never leak into the fingerprint.
  • JA4: b sorted ascending, c extensions sorted (sig-algs unsorted per spec), both hashed with truncated SHA-256; _r variants expose the raw strings for debugging and exact matching.
  • All GREASE detection goes through IsGrease on zero-padded uppercase hex (0x0A0A), so reserved values are recognized regardless of case or width.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var GreaseValues = []string{
	"0x0A0A",
	"0x1A1A",
	"0x2A2A",
	"0x3A3A",
	"0x4A4A",
	"0x5A5A",
	"0x6A6A",
	"0x7A7A",
	"0x8A8A",
	"0x9A9A",
	"0xAAAA",
	"0xBABA",
	"0xCACA",
	"0xDADA",
	"0xEAEA",
	"0xFAFA",
}

Functions

func CalculateJa4

func CalculateJa4(tls *TLSDetails) string

func CalculateJa4QUIC

func CalculateJa4QUIC(tls *TLSDetails) string

CalculateJa4QUIC calculates JA4 fingerprint for Quic/HTTP3 connections

func CalculateJa4QUIC_r

func CalculateJa4QUIC_r(tls *TLSDetails) string

CalculateJa4QUIC_r calculates JA4_r fingerprint for Quic/HTTP3 connections

func CalculateJa4_r

func CalculateJa4_r(tls *TLSDetails) string

func CalculatePeetPrint

func CalculatePeetPrint(parsed ClientHello, j JA3Calculating) (string, string)

func GetAkamaiFingerprint

func GetAkamaiFingerprint(frames []ParsedFrame) string

func GetAllFlags

func GetAllFlags(frame http2.Frame) []string

func GetCipherSuiteName

func GetCipherSuiteName(cipher uint16) string

func GetCurveNameByID

func GetCurveNameByID(id uint16) string

func GetExtensionNameByID

func GetExtensionNameByID(id uint16) string

func GetHTTP1HeaderOrderFingerprint

func GetHTTP1HeaderOrderFingerprint(headers []string) string

GetHTTP1HeaderOrderFingerprint returns a pipe-separated, lowercased list of header names in the exact order they were sent by the client, e.g. "host|user-agent|accept|accept-language|accept-encoding|connection". Header names are a strong signal for HTTP/1 client fingerprinting because different clients emit them in different orders.

func GetHTTP3FingerprintHash

func GetHTTP3FingerprintHash(fingerprint string) string

GetHTTP3FingerprintHash returns MD5 hash of the fingerprint

func GetHTTP3HeaderOrder

func GetHTTP3HeaderOrder(headers []string) string

GetHTTP3HeaderOrder extracts pseudo-header order from headers Headers are in format "key: value" Returns format like "m,a,s,p" for :method, :authority, :scheme, :path

func GetHTTP3SettingName

func GetHTTP3SettingName(id uint64) string

GetHTTP3SettingName returns the name for a known HTTP/3 setting ID

func GetHTTP3SettingsFingerprint

func GetHTTP3SettingsFingerprint(settings []Http3SettingPair, headerOrder string) string

GetHTTP3SettingsFingerprint generates a fingerprint string from HTTP/3 settings Format: "id:value;id:value;...|header_order"

func GetMD5Hash

func GetMD5Hash(text string) string

func GetSignatureNameByID

func GetSignatureNameByID(id uint16) string

func IsGrease

func IsGrease(cipher string) bool

func PrettyPrintClientHello

func PrettyPrintClientHello(ch ClientHello)

DEBUG

func ReadFile

func ReadFile(filename string) ([]byte, error)

func SHA256trunc

func SHA256trunc(in string) string

func SniffTCP

func SniffTCP(device string, tlsPort int, fingerprints *sync.Map, stop <-chan struct{}) error

SniffTCP passively captures TCP packets destined for tlsPort on the given network device and stores their IP/TCP fingerprints in fingerprints, keyed by "sourceIP:sourcePort".

The capture loop runs until the device handle fails or stop is closed (the handle is then closed, unblocking the read loop). OpenLive errors are returned to the caller.

func SortByVal

func SortByVal(m map[string]int, x int) map[string]int

func SplitBytesIntoChunks

func SplitBytesIntoChunks(buf []byte, lim int) [][]byte

func ToHexAll

func ToHexAll(in []string, filterOut bool, shouldSort bool) []string

func WriteToFile

func WriteToFile(filename string, data []byte) error

Types

type ClientHello

type ClientHello struct {
	Length             int
	Version            int // TLS version, always 1.2 because of middleboxes
	ClientRandom       string
	SessionID          string
	CipherSuites       []uint16
	CompressionMethods string
	AllExtensions      []int
	Extensions         []interface{}

	SupportedProtos   []string
	SupportedPoints   []uint8
	SupportedVersions []uint8
	SupportedCurves   []uint16

	// For the PeetPrint
	SupportedTLSVersions      []int
	SupportedProtocols        []string
	SignatureAlgorithms       []int
	PSKKeyExchangeMode        int
	CertCompressionAlgorithms []int
}

func ParseClientHello

func ParseClientHello(ch string) ClientHello

Gets the ClientHello as hex bytes

type Extension

type Extension struct {
	Type   string
	Length int
	Data   string
}

type GoAway

type GoAway struct {
	LastStreamID uint32
	ErrCode      uint32
	DebugData    []byte
}

type Http1Details

type Http1Details struct {
	Headers                    []string `json:"headers"`
	HeaderOrderFingerprint     string   `json:"header_order_fingerprint,omitempty"`
	HeaderOrderFingerprintHash string   `json:"header_order_fingerprint_hash,omitempty"`
}

func (*Http1Details) GetHeader

func (h1 *Http1Details) GetHeader(key string, toLower bool) string

type Http2Details

type Http2Details struct {
	AkamaiFingerprint     string        `json:"akamai_fingerprint"`
	AkamaiFingerprintHash string        `json:"akamai_fingerprint_hash"`
	Settings              []string      `json:"settings,omitempty"`
	SendFrames            []ParsedFrame `json:"sent_frames"`
}

type Http3Details

type Http3Details struct {
	Used0RTT                           bool               `json:"used_0rtt"`
	SupportsDatagrams                  bool               `json:"supports_datagrams"`
	SupportsStreamResetPartialDelivery bool               `json:"supports_stream_reset_partial_delivery"`
	Version                            uint32             `json:"version"`
	GSO                                bool               `json:"gso"`
	Settings                           []Http3SettingPair `json:"settings"`
	AkamaiFingerprint                  string             `json:"akamai_fingerprint"`
	AkamaiFingerprintHash              string             `json:"akamai_fingerprint_hash"`
	Headers                            []string           `json:"headers,omitempty"`
}

type Http3SettingPair

type Http3SettingPair struct {
	ID    uint64 `json:"id"`
	Name  string `json:"name"`
	Value uint64 `json:"value"`
}

Http3SettingPair represents a single HTTP/3 setting for fingerprinting

type Http3Settings

type Http3Settings struct {
	EnableDatagrams       bool               `json:"enable_datagrams"`
	EnableExtendedConnect bool               `json:"enable_extended_connect"`
	Other                 map[uint64]uint64  `json:"other,omitempty"`
	RawSettings           []Http3SettingPair `json:"settings,omitempty"`
}

type IPDetails

type IPDetails struct {
	DF          int    `json:"df,omitempty"`
	HDRLength   int    `json:"hdr_length,omitempty"`
	ID          int    `json:"id,omitempty"`
	MF          int    `json:"mf,omitempty"`
	NXT         int    `json:"nxt,omitempty"`
	OFF         int    `json:"off,omitempty"`
	PLEN        int    `json:"plen,omitempty"`
	Protocol    int    `json:"protocol,omitempty"`
	RF          int    `json:"rf,omitempty"`
	TOS         int    `json:"tos,omitempty"`
	TotalLength int    `json:"total_length,omitempty"`
	TTL         int    `json:"ttl,omitempty"`
	IPVersion   int    `json:"ip_version,omitempty"`
	DstIp       string `json:"dst_ip,omitempty"`
	SrcIP       string `json:"src_ip,omitempty"`
}

IPDetails holds IPv4/IPv6 header fields extracted from captured TCP packets.

type JA3Calculating

type JA3Calculating struct {
	AllCiphers      []uint16 `json:"-"`
	JA3Ciphers      []string `json:"-"`
	ReadableCiphers []string `json:"ciphers"`

	AllCurves []uint16 `json:"-"`
	JA3Curves []string `json:"-"`

	AllExtensions []int    `json:"-"`
	JA3Extensions []string `json:"-"`

	AllPoints []uint8  `json:"-"`
	JA3Points []string `json:"-"`

	Version           string
	ReadableProtocols []string
	ReadableVersions  []string

	JA3     string
	JA3Hash string

	// PeetPrint
	PeetPrintCiphers    []string
	PeetPrintExtensions []string
	PeetPrintCurves     []string
}

func CalculateJA3

func CalculateJA3(parsed ClientHello) JA3Calculating

func (*JA3Calculating) Calculate

func (j *JA3Calculating) Calculate()

func (*JA3Calculating) Parse

func (j *JA3Calculating) Parse()

type ParsedFrame

type ParsedFrame struct {
	Type      string    `json:"frame_type,omitempty"`
	Stream    uint32    `json:"stream_id,omitempty"`
	Length    uint32    `json:"length,omitempty"`
	Payload   []byte    `json:"payload,omitempty"`
	Headers   []string  `json:"headers,omitempty"`
	Settings  []string  `json:"settings,omitempty"`
	Increment uint32    `json:"increment,omitempty"`
	Flags     []string  `json:"flags,omitempty"`
	Priority  *Priority `json:"priority,omitempty"`
	GoAway    *GoAway   `json:"goaway,omitempty"`
}

type Priority

type Priority struct {
	Weight    int `json:"weight"`
	DependsOn int `json:"depends_on"`
	Exclusive int `json:"exclusive"`
}

type Request

type Request struct {
	Conn        net.Conn      `json:"-"`
	ObservedAt  time.Time     `json:"observed_at"`
	Donate      string        `json:"donate"`
	IP          string        `json:"ip"`
	HTTPVersion string        `json:"http_version"`
	Path        string        `json:"path"`
	Method      string        `json:"method"`
	UserAgent   string        `json:"user_agent,omitempty"`
	TLS         *TLSDetails   `json:"tls"`
	TCPIP       *TCPIPDetails `json:"tcpip,omitempty"`
	Http1       *Http1Details `json:"http1,omitempty"`
	Http2       *Http2Details `json:"http2,omitempty"`
	Http3       *Http3Details `json:"http3,omitempty"`
}

func (Request) CalcJa4

func (req Request) CalcJa4() Request

func (Request) ToJson

func (req Request) ToJson() string

type SmallResponse

type SmallResponse struct {
	JA3           string `json:"ja3"`
	JA3Hash       string `json:"ja3_hash"`
	JA4           string `json:"ja4"`
	JA4_r         string `json:"ja4_r"`
	Akamai        string `json:"akamai"`
	AkamaiHash    string `json:"akamai_hash"`
	PeetPrint     string `json:"peetprint"`
	PeetPrintHash string `json:"peetprint_hash"`
	HTTPVersion   string `json:"http_version"`
}

func (SmallResponse) ToJson

func (res SmallResponse) ToJson() string

type TCPDetails

type TCPDetails struct {
	Ack                int    `json:"ack,omitempty"`
	Checksum           int    `json:"checksum,omitempty"`
	Flags              int    `json:"flags,omitempty"`
	HeaderLength       int    `json:"header_length,omitempty"`
	MSS                int    `json:"mss,omitempty"`
	OFF                int    `json:"off,omitempty"`
	Options            string `json:"options,omitempty"`
	OptionsOrder       string `json:"options_order,omitempty"`
	Seq                int    `json:"seq,omitempty"`
	Timestamp          int    `json:"timestamp,omitempty"`
	TimestampEchoReply int    `json:"timestamp_echo_reply,omitempty"`
	URP                int    `json:"urp,omitempty"`
	Window             int    `json:"window,omitempty"`
}

TCPDetails holds TCP header fields extracted from captured TCP packets.

type TCPIPDetails

type TCPIPDetails struct {
	CapLen    int        `json:"cap_length,omitempty"`
	DstPort   int        `json:"dst_port,omitempty"`
	SrcPort   int        `json:"src_port,omitempty"`
	HeaderLen int        `json:"header_length,omitempty"`
	TS        []int      `json:"ts,omitempty"`
	IP        IPDetails  `json:"ip,omitempty"`
	TCP       TCPDetails `json:"tcp,omitempty"`
}

TCPIPDetails bundles the IP and TCP fingerprints of a captured packet.

type TLSDetails

type TLSDetails struct {
	Ciphers           []string      `json:"ciphers"`
	Extensions        []interface{} `json:"extensions"`
	RecordVersion     string        `json:"tls_version_record"`
	NegotiatedVersion string        `json:"tls_version_negotiated"`
	ServerName        string        `json:"server_name,omitempty"`
	NegotiatedCipher  string        `json:"negotiated_cipher,omitempty"`

	JA3     string `json:"ja3"`
	JA3Hash string `json:"ja3_hash"`

	JA4   string `json:"ja4"`
	JA4_r string `json:"ja4_r"`

	PeetPrint     string `json:"peetprint"`
	PeetPrintHash string `json:"peetprint_hash"`

	ClientRandom string `json:"client_random"`
	SessionID    string `json:"session_id"`
	RawBytes     string `json:"-"`
	RawB64       string `json:"-"`
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL