-
Notifications
You must be signed in to change notification settings - Fork 869
Expand file tree
/
Copy pathREADME
More file actions
144 lines (107 loc) · 5.9 KB
/
Copy pathREADME
File metadata and controls
144 lines (107 loc) · 5.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
ATS (Apache Traffic Server) JAx Fingerprint Plugin
User-facing documentation lives in
`doc/admin-guide/plugins/jax_fingerprint.en.rst`. This README covers the
developer side: how the plugin is organised, and what it takes to add a new
fingerprinting method.
Plugin layout
-------------
```
jax_fingerprint/
plugin.cc / plugin.h Plugin entry points, hook handlers, method dispatch.
context.cc / .h JAxContext: per-connection (or per-txn) fingerprint state.
context_map.h Inline fixed-size table that multiplexes JAxContexts
by method name on a single user-arg slot.
userarg.cc / userarg.h Shared user-arg slot reservation and accessors.
header.cc / .h Set/append/remove the fingerprint and via headers.
log.cc / .h Optional log file output for fingerprints.
method.h Abstract Method struct (name, type, callbacks).
Unaware of any concrete method.
config.h PluginConfig, parsing helpers.
common/ Shared utilities (hash stringification, etc.).
ja3/ ja4/ ja4h/ One subdirectory per fingerprinting method.
```
Each method subdirectory follows the conventions described below.
Adding a new method
-------------------
Suppose you want to add a method called `mymethod`. The steps are:
1. Create a directory `mymethod/` under this plugin.
2. Drop in the source files (see *File naming* below for what each name
means to the build):
mymethod/method.h Declares `extern struct Method method;` in
your namespace (e.g. `namespace mymethod`).
mymethod/method.cc Defines `Method method = { "MYMETHOD", ... }`
and the on_client_hello / on_request callback.
This is the file allowed to use TS APIs
(TSVConn, TSClientHello, ...).
mymethod/mymethod.cc/.h Pure algorithm. No TS API.
mymethod/datasource.cc/.h Abstract data source the algorithm consumes
(mirror ja4/datasource.h).
mymethod/test.cc Catch2 unit tests for the algorithm.
3. Register the method in plugin.cc. The dispatcher is a `constexpr` table
gated by `ENABLE_JAX_METHOD_*` macros. Add two entries:
#ifdef ENABLE_JAX_METHOD_MYMETHOD
#include "mymethod/method.h"
#endif
...
constexpr Method const *METHODS[] = {
...
#ifdef ENABLE_JAX_METHOD_MYMETHOD
&mymethod::method,
#endif
};
4. Enable the method at build time:
cmake -B build -DENABLE_JAX_METHODS="ja3;ja4;ja4h;mymethod"
CMake automatically picks up `mymethod/*.cc`, defines
`ENABLE_JAX_METHOD_MYMETHOD`, and bumps `JAX_FINGERPRINT_MAX_METHODS` to
match the list length.
5. Use the method:
jax_fingerprint.so --method MYMETHOD --header x-my-fingerprint
File naming
-----------
The top-level CMakeLists.txt globs `*.cc` from each enabled method directory
and applies these filters:
test.cc Built only into the test_jax binary (Catch2 unit tests).
method.cc Built only into jax_fingerprint.so. This is the one file
in each method directory that is allowed to call TS APIs
(TSVConn, TSClientHello, ...). Keep all TS glue here.
every other Built into BOTH jax_fingerprint.so and test_jax. Keep these
.cc files free of TS API calls so the unit-test binary, which
does not link the TS plugin SDK, still builds.
If you genuinely need to spread TS-API code across more than `method.cc` in
a method directory, you have to extend the exclusion regex in
CMakeLists.txt. There is one such historical exception today --
`ja4/tls_client_hello_summary.cc` -- and the regex carves it out by name.
Prefer not to add new files in that category: split the algorithm so the
TS-facing piece stays in `method.cc` and the pure-data piece is its own
file. If a future case really does justify extending the regex, name the
file something that documents the constraint (for instance `*_ts.cc`) and
update the regex accordingly.
The method directory name (lower case) maps to the macro
`ENABLE_JAX_METHOD_<UPPER>` (so `mymethod` -> `ENABLE_JAX_METHOD_MYMETHOD`).
`Method::name` should be the user-visible spelling (e.g. "MYMETHOD"),
matched against `--method` on the command line.
`Method::name` must reference a string with static storage duration (a
string literal is the natural fit). ContextMap stores `std::string_view`
slot keys that alias `Method::name`; if `name` ever pointed at temporary
storage, the keys would dangle.
Build-time configuration
------------------------
ENABLE_JAX_METHODS Semicolon-separated list of methods to
compile in. Default: "ja3;ja4;ja4h".
Empty list or unknown directory name causes
a FATAL_ERROR at configure time.
JAX_FINGERPRINT_MAX_METHODS Auto-derived from the length of
ENABLE_JAX_METHODS, passed to the plugin as
a compile definition. Bounds the inline
ContextMap slot array. The header has a
fallback `#define JAX_FINGERPRINT_MAX_METHODS 8`
so it is also valid standalone (e.g. for
IDE indexing).
Unit tests vs. AuTest
---------------------
* Catch2 unit tests (`test_jax`) live in each `*/test.cc` and cover pure
algorithm logic. Built when BUILD_TESTING is on; run via ctest or the
test_jax binary directly.
* End-to-end AuTests live under `tests/gold_tests/pluginTest/jax_fingerprint/`
and exercise the plugin via Proxy Verifier replay yamls. They require a
full install (traffic_server, traffic_layout, the plugin .so).