|
| 1 | +diff -r d964b0aee8e7 src/event/ngx_event_openssl.c |
| 2 | +--- a/src/event/ngx_event_openssl.c Thu May 23 16:49:22 2019 +0300 |
| 3 | ++++ b/src/event/ngx_event_openssl.c Sat Jun 01 14:53:52 2019 +0000 |
| 4 | +@@ -1588,6 +1588,107 @@ |
| 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 | ++ } |
| 35 | ++ |
| 36 | ++ /* Elliptic curve points */ |
| 37 | ++ c->ssl->curves_sz = SSL_get1_curves(s, NULL); |
| 38 | ++ if (c->ssl->curves_sz) { |
| 39 | ++ curves_out = OPENSSL_malloc(c->ssl->curves_sz * sizeof(int)); |
| 40 | ++ if (curves_out != NULL) { |
| 41 | ++ SSL_get1_curves(s, curves_out); |
| 42 | ++ len = c->ssl->curves_sz * sizeof(unsigned short); |
| 43 | ++ c->ssl->curves = ngx_pnalloc(c->pool, len); |
| 44 | ++ if (c->ssl->curves != NULL) { |
| 45 | ++ for (size_t i = 0; i < c->ssl->curves_sz; i++) { |
| 46 | ++ c->ssl->curves[i] = curves_out[i]; |
| 47 | ++ } |
| 48 | ++ } |
| 49 | ++ OPENSSL_free(curves_out); |
| 50 | ++ } |
| 51 | ++ } |
| 52 | ++ |
| 53 | ++ /* Elliptic curve point formats */ |
| 54 | ++ c->ssl->point_formats_sz = SSL_get0_ec_point_formats(s, &point_formats_out); |
| 55 | ++ if (c->ssl->point_formats_sz && point_formats_out != NULL) { |
| 56 | ++ len = c->ssl->point_formats_sz * sizeof(unsigned char); |
| 57 | ++ c->ssl->point_formats = ngx_pnalloc(c->pool, len); |
| 58 | ++ if (c->ssl->point_formats != NULL) { |
| 59 | ++ ngx_memcpy(c->ssl->point_formats, point_formats_out, len); |
| 60 | ++ } |
| 61 | ++ } |
| 62 | ++} |
| 63 | ++ |
| 64 | ++/* should *ALWAYS return 1 |
| 65 | ++ * # define SSL_CLIENT_HELLO_SUCCESS 1 |
| 66 | ++ * |
| 67 | ++ * otherwise |
| 68 | ++ * A failure in the ClientHello callback terminates the connection. |
| 69 | ++ */ |
| 70 | ++int |
| 71 | ++ngx_SSL_early_cb_fn(SSL *s, int *al, void *arg) { |
| 72 | ++ |
| 73 | ++ int got_extensions; |
| 74 | ++ int *ext_out; |
| 75 | ++ size_t ext_len; |
| 76 | ++ ngx_connection_t *c; |
| 77 | ++ |
| 78 | ++ c = arg; |
| 79 | ++ |
| 80 | ++ if (c == NULL) { |
| 81 | ++ return 1; |
| 82 | ++ } |
| 83 | ++ |
| 84 | ++ if (c->ssl == NULL) { |
| 85 | ++ return 1; |
| 86 | ++ } |
| 87 | ++ |
| 88 | ++ c->ssl->extensions_size = 0; |
| 89 | ++ c->ssl->extensions = NULL; |
| 90 | ++ got_extensions = SSL_client_hello_get1_extensions_present(s, |
| 91 | ++ &ext_out, |
| 92 | ++ &ext_len); |
| 93 | ++ if (got_extensions) { |
| 94 | ++ if (ext_out && ext_len) { |
| 95 | ++ c->ssl->extensions = |
| 96 | ++ ngx_palloc(c->pool, sizeof(int) * ext_len); |
| 97 | ++ if (c->ssl->extensions != NULL) { |
| 98 | ++ c->ssl->extensions_size = ext_len; |
| 99 | ++ ngx_memcpy(c->ssl->extensions, ext_out, sizeof(int) * ext_len); |
| 100 | ++ OPENSSL_free(ext_out); |
| 101 | ++ } |
| 102 | ++ } |
| 103 | ++ } |
| 104 | ++ |
| 105 | ++ return 1; |
| 106 | ++} |
| 107 | ++#endif |
| 108 | ++/* ----- JA3 HACK END -------------------------------------------------------*/ |
| 109 | + |
| 110 | + ngx_int_t |
| 111 | + ngx_ssl_handshake(ngx_connection_t *c) |
| 112 | +@@ -1603,6 +1704,10 @@ |
| 113 | + |
| 114 | + ngx_ssl_clear_error(c->log); |
| 115 | + |
| 116 | ++#if OPENSSL_VERSION_NUMBER >= 0x10101000L |
| 117 | ++ SSL_CTX_set_client_hello_cb(c->ssl->session_ctx, ngx_SSL_early_cb_fn, c); |
| 118 | ++#endif |
| 119 | ++ |
| 120 | + n = SSL_do_handshake(c->ssl->connection); |
| 121 | + |
| 122 | + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_do_handshake: %d", n); |
| 123 | +@@ -1623,6 +1728,12 @@ |
| 124 | + |
| 125 | + c->ssl->handshaked = 1; |
| 126 | + |
| 127 | ++/* ----- JA3 HACK START -----------------------------------------------------*/ |
| 128 | ++#if OPENSSL_VERSION_NUMBER >= 0x10101000L |
| 129 | ++ ngx_SSL_client_features(c); |
| 130 | ++#endif |
| 131 | ++/* ----- JA3 HACK END -------------------------------------------------------*/ |
| 132 | ++ |
| 133 | + c->recv = ngx_ssl_recv; |
| 134 | + c->send = ngx_ssl_write; |
| 135 | + c->recv_chain = ngx_ssl_recv_chain; |
| 136 | +diff -r d964b0aee8e7 src/event/ngx_event_openssl.h |
| 137 | +--- a/src/event/ngx_event_openssl.h Thu May 23 16:49:22 2019 +0300 |
| 138 | ++++ b/src/event/ngx_event_openssl.h Sat Jun 01 14:53:52 2019 +0000 |
| 139 | +@@ -99,6 +99,23 @@ |
| 140 | + unsigned in_early:1; |
| 141 | + unsigned early_preread:1; |
| 142 | + unsigned write_blocked:1; |
| 143 | ++ |
| 144 | ++/* ----- JA3 HACK START -----------------------------------------------------*/ |
| 145 | ++#if OPENSSL_VERSION_NUMBER >= 0x10101000L |
| 146 | ++ |
| 147 | ++ size_t ciphers_sz; |
| 148 | ++ unsigned short *ciphers; |
| 149 | ++ |
| 150 | ++ size_t extensions_size; |
| 151 | ++ unsigned short *extensions; |
| 152 | ++ |
| 153 | ++ size_t curves_sz; |
| 154 | ++ unsigned short *curves; |
| 155 | ++ |
| 156 | ++ size_t point_formats_sz; |
| 157 | ++ unsigned char *point_formats; |
| 158 | ++#endif |
| 159 | ++/* ----- JA3 HACK END -------------------------------------------------------*/ |
| 160 | + }; |
| 161 | + |
| 162 | + |
0 commit comments