Skip to content

Commit f6a08ee

Browse files
committed
[fooinha#11] - saves ec values to nginx connection
1 parent 6a4ab26 commit f6a08ee

File tree

4 files changed

+215
-62
lines changed

4 files changed

+215
-62
lines changed
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
diff -r -u ./src/event/ngx_event_openssl.c ../../nginx/src/event/ngx_event_openssl.c
2+
--- ./src/event/ngx_event_openssl.c 2019-03-31 22:24:03.317031000 +0000
3+
+++ ../../nginx/src/event/ngx_event_openssl.c 2019-03-31 22:29:05.000000000 +0000
4+
@@ -1599,6 +1599,117 @@
5+
return NGX_OK;
6+
}
7+
8+
+/* ----- JA3 HACK START -----------------------------------------------------*/
9+
+#if OPENSSL_VERSION_NUMBER >= 0x10101000L
10+
+
11+
+void
12+
+ngx_SSL_client_features(ngx_connection_t *c) {
13+
+
14+
+ unsigned short *ciphers_out = NULL;
15+
+ int *curves_out = NULL;
16+
+ int *point_formats_out = NULL;
17+
+ size_t len = 0;
18+
+ SSL *s = NULL;
19+
+
20+
+ if (c == NULL) {
21+
+ return;
22+
+ }
23+
+ s = c->ssl->connection;
24+
+
25+
+ /* Cipher suites */
26+
+ c->ssl->ciphers = NULL;
27+
+ c->ssl->ciphers_sz = SSL_get0_raw_cipherlist(s, &ciphers_out);
28+
+ c->ssl->ciphers_sz /= 2;
29+
+
30+
+ if (c->ssl->ciphers_sz && ciphers_out) {
31+
+ len = c->ssl->ciphers_sz * sizeof(unsigned short);
32+
+ c->ssl->ciphers = ngx_pnalloc(c->pool, len);
33+
+ ngx_memcpy(c->ssl->ciphers, ciphers_out, len);
34+
+ OPENSSL_free(ciphers_out);
35+
+ }
36+
+
37+
+ /* Elliptic curve points */
38+
+ c->ssl->curves_sz = SSL_get1_curves(s, NULL);
39+
+ if (c->ssl->curves_sz) {
40+
+ curves_out = OPENSSL_malloc(c->ssl->curves_sz * sizeof(int));
41+
+ if (curves_out != NULL) {
42+
+ SSL_get1_curves(s, curves_out);
43+
+ len = c->ssl->curves_sz * sizeof(unsigned short);
44+
+ c->ssl->curves = ngx_pnalloc(c->pool, len);
45+
+ if (c->ssl->curves != NULL) {
46+
+ for (size_t i = 0; i < c->ssl->curves_sz; i++) {
47+
+ c->ssl->curves[i] = curves_out[i];
48+
+ }
49+
+ }
50+
+ OPENSSL_free(curves_out);
51+
+ }
52+
+ }
53+
+
54+
+ /* Elliptic curve point formats */
55+
+ c->ssl->point_formats_sz = SSL_get0_ec_point_formats(s, &point_formats_out);
56+
+ if (c->ssl->point_formats_sz && point_formats_out != NULL) {
57+
+ len = c->ssl->point_formats_sz * sizeof(unsigned char);
58+
+ c->ssl->point_formats = ngx_pnalloc(c->pool, len);
59+
+ if (c->ssl->point_formats != NULL) {
60+
+ ngx_memcpy(c->ssl->point_formats, point_formats_out, len);
61+
+ }
62+
+ OPENSSL_free(point_formats_out);
63+
+ }
64+
+}
65+
+
66+
+
67+
+/* should *ALWAYS return 1
68+
+ * # define SSL_CLIENT_HELLO_SUCCESS 1
69+
+ *
70+
+ * otherwise
71+
+ * A failure in the ClientHello callback terminates the connection.
72+
+ */
73+
+int
74+
+ngx_SSL_early_cb_fn(SSL *s, int *al, void *arg) {
75+
+
76+
+ int got_extensions;
77+
+ int *ext_out;
78+
+ size_t ext_len;
79+
+ ngx_connection_t *c;
80+
+
81+
+ c = arg;
82+
+
83+
+ if (c == NULL) {
84+
+ return 1;
85+
+ }
86+
+
87+
+ if (c->ssl == NULL) {
88+
+ return 1;
89+
+ }
90+
+
91+
+ c->ssl->version = SSL_version(s);
92+
+
93+
+
94+
+ c->ssl->extensions_size = 0;
95+
+ c->ssl->extensions = NULL;
96+
+
97+
+ got_extensions = SSL_client_hello_get1_extensions_present(s,
98+
+ &ext_out,
99+
+ &ext_len);
100+
+ if (got_extensions) {
101+
+ if (ext_out && ext_len) {
102+
+ c->ssl->extensions =
103+
+ ngx_palloc(c->pool, sizeof(int) * ext_len);
104+
+ if (c->ssl->extensions != NULL) {
105+
+ c->ssl->extensions_size = ext_len;
106+
+ ngx_memcpy(c->ssl->extensions, ext_out, sizeof(int) * ext_len);
107+
+ OPENSSL_free(ext_out);
108+
+ }
109+
+ }
110+
+ }
111+
+
112+
+
113+
+ return 1;
114+
+}
115+
+#endif
116+
+/* ----- JA3 HACK END -------------------------------------------------------*/
117+
+
118+
+
119+
120+
ngx_int_t
121+
ngx_ssl_handshake(ngx_connection_t *c)
122+
@@ -1614,6 +1725,10 @@
123+
124+
ngx_ssl_clear_error(c->log);
125+
126+
+#if OPENSSL_VERSION_NUMBER >= 0x10101000L
127+
+ SSL_CTX_set_client_hello_cb(c->ssl->session_ctx, ngx_SSL_early_cb_fn, c);
128+
+#endif
129+
+
130+
n = SSL_do_handshake(c->ssl->connection);
131+
132+
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_do_handshake: %d", n);
133+
@@ -1634,6 +1749,12 @@
134+
135+
c->ssl->handshaked = 1;
136+
137+
+/* ----- JA3 HACK START -----------------------------------------------------*/
138+
+#if OPENSSL_VERSION_NUMBER >= 0x10101000L
139+
+ ngx_SSL_client_features(c);
140+
+#endif
141+
+/* ----- JA3 HACK END -------------------------------------------------------*/
142+
+
143+
c->recv = ngx_ssl_recv;
144+
c->send = ngx_ssl_write;
145+
c->recv_chain = ngx_ssl_recv_chain;
146+
diff -r -u ./src/event/ngx_event_openssl.h ../../nginx/src/event/ngx_event_openssl.h
147+
--- ./src/event/ngx_event_openssl.h 2019-03-31 22:24:03.297031000 +0000
148+
+++ ../../nginx/src/event/ngx_event_openssl.h 2019-03-31 22:28:22.000000000 +0000
149+
@@ -99,6 +99,23 @@
150+
unsigned in_early:1;
151+
unsigned early_preread:1;
152+
unsigned write_blocked:1;
153+
+
154+
+/* ----- JA3 HACK START -----------------------------------------------------*/
155+
+#if OPENSSL_VERSION_NUMBER >= 0x10101000L
156+
+
157+
+ size_t ciphers_sz;
158+
+ unsigned short *ciphers;
159+
+
160+
+ size_t extensions_size;
161+
+ unsigned short *extensions;
162+
+
163+
+ size_t curves_sz;
164+
+ unsigned short *curves;
165+
+
166+
+ size_t point_formats_sz;
167+
+ unsigned char *point_formats;
168+
+#endif
169+
+/* ----- JA3 HACK END -------------------------------------------------------*/
170+
};
171+
172+

patches/nginx.latest.patch

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
nginx.1.15.9.ssl.extensions.patch
1+
nginx.1.15.11.ssl.extensions.patch

src/ngx_ssl_ja3.c

Lines changed: 41 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,9 @@ ngx_ssl_ja3_detail_print(ngx_pool_t *pool, ngx_ssl_ja3_t *ja3)
134134
ja3->ciphers_sz);
135135

136136
for (size_t i = 0; i < ja3->ciphers_sz; ++i) {
137-
ngx_log_debug1(NGX_LOG_DEBUG_EVENT,
138-
pool->log, 0, "ssl_ja3: | cipher: %d",
137+
ngx_log_debug2(NGX_LOG_DEBUG_EVENT,
138+
pool->log, 0, "ssl_ja3: | cipher: 0x%04uxD -> %d",
139+
ja3->ciphers[i],
139140
ja3->ciphers[i]
140141
);
141142
}
@@ -146,8 +147,9 @@ ngx_ssl_ja3_detail_print(ngx_pool_t *pool, ngx_ssl_ja3_t *ja3)
146147
ja3->extensions_sz);
147148

148149
for (size_t i = 0; i < ja3->extensions_sz; ++i) {
149-
ngx_log_debug1(NGX_LOG_DEBUG_EVENT,
150-
pool->log, 0, "ssl_ja3: | extension: %d",
150+
ngx_log_debug2(NGX_LOG_DEBUG_EVENT,
151+
pool->log, 0, "ssl_ja3: | extension: 0x%04uxD -> %d",
152+
ja3->extensions[i],
151153
ja3->extensions[i]
152154
);
153155
}
@@ -158,8 +160,9 @@ ngx_ssl_ja3_detail_print(ngx_pool_t *pool, ngx_ssl_ja3_t *ja3)
158160
ja3->curves_sz);
159161

160162
for (size_t i = 0; i < ja3->curves_sz; ++i) {
161-
ngx_log_debug1(NGX_LOG_DEBUG_EVENT,
162-
pool->log, 0, "ssl_ja3: | curves: %d",
163+
ngx_log_debug2(NGX_LOG_DEBUG_EVENT,
164+
pool->log, 0, "ssl_ja3: | curves: 0x%04uxD -> %d",
165+
ja3->curves[i],
163166
ja3->curves[i]
164167
);
165168
}
@@ -181,8 +184,7 @@ ngx_ssl_ja3_detail_print(ngx_pool_t *pool, ngx_ssl_ja3_t *ja3)
181184
void
182185
ngx_ssl_ja3_fp(ngx_pool_t *pool, ngx_ssl_ja3_t *ja3, ngx_str_t *out)
183186
{
184-
size_t len = 0, cur = 0, added = 0;
185-
unsigned short us = 0;
187+
size_t len = 0, cur = 0;
186188

187189
if (pool == NULL || ja3 == NULL || out == NULL) {
188190
return;
@@ -231,18 +233,12 @@ ngx_ssl_ja3_fp(ngx_pool_t *pool, ngx_ssl_ja3_t *ja3, ngx_str_t *out)
231233

232234
if (ja3->ciphers_sz) {
233235
for (size_t i = 0; i < ja3->ciphers_sz; ++i) {
234-
us = ntohs(ja3->ciphers[i]);
235-
if (!ngx_ssl_ja3_is_ext_greased(us)) {
236-
if (added > 0) {
237-
ngx_snprintf(out->data + (cur++), 1, "-");
238-
}
239-
len = ngx_ssj_ja3_num_digits(us);
240-
ngx_snprintf(out->data + cur, len, "%d", us);
241-
cur += len;
242-
if (added == 0) {
243-
added = 1;
244-
}
236+
if (i > 0) {
237+
ngx_snprintf(out->data + (cur++), 1, "-");
245238
}
239+
len = ngx_ssj_ja3_num_digits(ja3->ciphers[i]);
240+
ngx_snprintf(out->data + cur, len, "%d", ja3->ciphers[i]);
241+
cur += len;
246242
}
247243
}
248244
ngx_snprintf(out->data + (cur++), 1, ",");
@@ -301,9 +297,6 @@ ngx_ssl_ja3(ngx_connection_t *c, ngx_pool_t *pool, ngx_ssl_ja3_t *ja3) {
301297

302298
ngx_ssl_session_t *ssl_session;
303299
SSL *ssl;
304-
unsigned short *ciphers_out = NULL;
305-
int *curves_out = NULL;
306-
int *point_formats_out = NULL;
307300
size_t len = 0;
308301
unsigned short us = 0;
309302

@@ -330,71 +323,59 @@ ngx_ssl_ja3(ngx_connection_t *c, ngx_pool_t *pool, ngx_ssl_ja3_t *ja3) {
330323

331324
/* Cipher suites */
332325
ja3->ciphers = NULL;
333-
ja3->ciphers_sz = SSL_get0_raw_cipherlist(ssl, &ciphers_out);
334-
ja3->ciphers_sz /= 2;
326+
ja3->ciphers_sz = 0;
335327

336-
if (ja3->ciphers_sz && ciphers_out) {
337-
len = ja3->ciphers_sz * sizeof(unsigned short);
328+
if (c->ssl->ciphers && c->ssl->ciphers_sz) {
329+
len = c->ssl->ciphers_sz * sizeof(unsigned short);
338330
ja3->ciphers = ngx_pnalloc(pool, len);
339331
if (ja3->ciphers == NULL) {
340332
return NGX_DECLINED;
341333
}
342-
ngx_memcpy(ja3->ciphers, ciphers_out, len);
334+
/* Filter out GREASE extensions */
335+
for (size_t i = 0; i < c->ssl->ciphers_sz; ++i) {
336+
us = ntohs(c->ssl->ciphers[i]);
337+
if (! ngx_ssl_ja3_is_ext_greased(us)) {
338+
ja3->ciphers[ja3->ciphers_sz++] = us;
339+
}
340+
}
343341
}
344342

345343
/* Extensions */
346344
ja3->extensions = NULL;
347345
ja3->extensions_sz = 0;
348-
if (c->ssl->client_extensions_size && c->ssl->client_extensions) {
349-
len = c->ssl->client_extensions_size * sizeof(int);
346+
if (c->ssl->extensions_size && c->ssl->extensions) {
347+
len = c->ssl->extensions_size * sizeof(int);
350348
ja3->extensions = ngx_pnalloc(pool, len);
351349
if (ja3->extensions == NULL) {
352350
return NGX_DECLINED;
353351
}
354-
for (size_t i = 0; i < c->ssl->client_extensions_size; ++i) {
355-
us = ntohs(c->ssl->client_extensions[i]);
356-
if (! ngx_ssl_ja3_is_ext_greased(us)) {
357-
ja3->extensions[ja3->extensions_sz++] =
358-
c->ssl->client_extensions[i];
352+
for (size_t i = 0; i < c->ssl->extensions_size; ++i) {
353+
if (! ngx_ssl_ja3_is_ext_greased(c->ssl->extensions[i])) {
354+
ja3->extensions[ja3->extensions_sz++] = c->ssl->extensions[i];
359355
}
360356
}
361357
}
362358

363359
/* Elliptic curve points */
364-
ja3->curves_sz = SSL_get1_curves(ssl, NULL);
365-
if (ja3->curves_sz) {
366-
curves_out = OPENSSL_malloc(ja3->curves_sz * sizeof(int));
367-
if (curves_out == NULL) {
368-
return NGX_DECLINED;
369-
}
370-
371-
SSL_get1_curves(ssl, curves_out);
372-
373-
len = ja3->curves_sz * sizeof(unsigned short);
360+
ja3->curves = c->ssl->curves;
361+
ja3->curves_sz = 0;
362+
if (c->ssl->curves && c->ssl->curves_sz) {
363+
len = c->ssl->curves_sz * sizeof(int);
374364
ja3->curves = ngx_pnalloc(pool, len);
375365
if (ja3->curves == NULL) {
376366
return NGX_DECLINED;
377367
}
378-
for (size_t i = 0; i < ja3->curves_sz; i++) {
379-
ja3->curves[i] = ngx_ssl_ja3_nid_to_cid(curves_out[i]);
380-
}
381-
382-
if (curves_out) {
383-
OPENSSL_free(curves_out);
368+
for (size_t i = 0; i < c->ssl->curves_sz; i++) {
369+
us = ntohs(c->ssl->curves[i]);
370+
if (! ngx_ssl_ja3_is_ext_greased(us)) {
371+
ja3->curves[ja3->curves_sz++] = ngx_ssl_ja3_nid_to_cid(c->ssl->curves[i]);
372+
}
384373
}
385374
}
386375

387376
/* Elliptic curve point formats */
388-
ja3->point_formats_sz = SSL_get0_ec_point_formats(ssl, &point_formats_out);
389-
if (ja3->point_formats_sz && point_formats_out != NULL) {
390-
391-
len = ja3->point_formats_sz * sizeof(unsigned char);
392-
ja3->point_formats = ngx_pnalloc(pool, len);
393-
if (ja3->point_formats == NULL) {
394-
return NGX_DECLINED;
395-
}
396-
ngx_memcpy(ja3->point_formats, point_formats_out, len);
397-
}
377+
ja3->point_formats_sz = c->ssl->point_formats_sz;
378+
ja3->point_formats = c->ssl->point_formats;
398379

399380
return NGX_OK;
400381
}

src/ngx_ssl_ja3.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ typedef struct ngx_ssl_ja3_s {
3535
unsigned short *ciphers;
3636

3737
size_t extensions_sz;
38-
int *extensions;
38+
unsigned short *extensions;
3939

4040
size_t curves_sz;
4141
unsigned short *curves;

0 commit comments

Comments
 (0)