Skip to content
24 changes: 14 additions & 10 deletions plugins/experimental/jax_fingerprint/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,30 +22,34 @@ add_atsplugin(
userarg.cc
header.cc
log.cc
ja3/ja3_method.cc
ja3/ja3_utils.cc
ja4/ja4_method.cc
ja3/method.cc
ja3/utils.cc
ja4/method.cc
ja4/ja4.cc
ja4/datasource.cc
ja4/tls_client_hello_summary.cc
ja4h/ja4h_method.cc
ja4h/method.cc
ja4h/ja4h.cc
ja4h/datasource.cc
ja4_common/utils.cc
)
target_link_libraries(jax_fingerprint PRIVATE OpenSSL::Crypto OpenSSL::SSL)
verify_global_plugin(jax_fingerprint)
target_include_directories(jax_fingerprint BEFORE PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
verify_global_plugin(jax_fingerprint)
verify_remap_plugin(jax_fingerprint)

if(BUILD_TESTING)
add_executable(
test_jax
ja3/test_ja3.cc
ja3/ja3_utils.cc
ja4/test_ja4.cc
ja3/test.cc
ja3/utils.cc
ja4/test.cc
ja4/ja4.cc
ja4/tls_client_hello_summary.cc
ja4h/test_ja4h.cc
ja4/datasource.cc
ja4h/test.cc
ja4h/ja4h.cc
ja4h/datasource.cc
ja4_common/utils.cc
)
target_link_libraries(test_jax PRIVATE Catch2::Catch2WithMain OpenSSL::Crypto OpenSSL::SSL)
target_include_directories(test_jax BEFORE PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,38 +24,22 @@

#include <plugin.h>
#include <context.h>
#include "ja3_method.h"
#include "ja3_utils.h"
#include "method.h"
#include "utils.h"

#include <openssl/ssl.h>
#include <openssl/md5.h>
#include <openssl/opensslv.h>

#include <algorithm>

namespace ja3_method
{

void on_client_hello(JAxContext *, TSVConn);

struct Method method = {
"JA3",
Method::Type::CONNECTION_BASED,
on_client_hello,
nullptr,
};

} // namespace ja3_method

namespace
{
constexpr int ja3_hash_included_byte_count{16};
static_assert(ja3_hash_included_byte_count <= MD5_DIGEST_LENGTH);

constexpr int ja3_hash_hex_string_with_null_terminator_length{2 * ja3_hash_included_byte_count + 1};

} // end anonymous namespace

static std::string
get_fingerprint(TSClientHello ch)
{
Expand Down Expand Up @@ -115,8 +99,13 @@ get_fingerprint(TSClientHello ch)
return {fingerprint};
}

} // end anonymous namespace

namespace ja3
{

void
ja3_method::on_client_hello(JAxContext *ctx, TSVConn vconn)
on_client_hello(JAxContext *ctx, TSVConn vconn)
{
TSClientHello ch = TSVConnClientHelloGet(vconn);

Expand All @@ -126,3 +115,12 @@ ja3_method::on_client_hello(JAxContext *ctx, TSVConn vconn)
ctx->set_fingerprint(get_fingerprint(ch));
}
}

struct Method method = {
"JA3",
Method::Type::CONNECTION_BASED,
on_client_hello,
nullptr,
};

} // namespace ja3
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

#include <method.h>

namespace ja4_method
namespace ja3
{

extern struct Method method;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
*/

#include "ja3_utils.h"
#include "utils.h"

#include <catch2/catch_test_macros.hpp>

Expand Down
73 changes: 73 additions & 0 deletions plugins/experimental/jax_fingerprint/ja4/datasource.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/** @file

@section license License

Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#include "datasource.h"

#include <array>
#include <algorithm>

constexpr std::array<std::uint16_t, 16> GREASE_values{0x0a0a, 0x1a1a, 0x2a2a, 0x3a3a, 0x4a4a, 0x5a5a, 0x6a6a, 0x7a7a,
0x8a8a, 0x9a9a, 0xaaaa, 0xbaba, 0xcaca, 0xdada, 0xeaea, 0xfafa};

ja4::Datasource::Protocol
ja4::Datasource::get_protocol()
{
return this->_protocol;
}

int
ja4::Datasource::get_version()
{
return this->_version;
}

ja4::Datasource::SNI
ja4::Datasource::get_sni_type()
{
return this->_has_SNI ? ja4::Datasource::SNI::to_domain : ja4::Datasource::SNI::to_IP;
}

int
ja4::Datasource::get_cipher_count()
{
return this->_n_ciphers;
}

int
ja4::Datasource::get_extension_count()
{
return this->_n_extensions + (this->_has_ALPN ? 1 : 0) + (this->_has_SNI ? 1 : 0);
}

/**
* Check whether @a value is a GREASE value.
*
* These are reserved extensions randomly advertised to keep implementations
* well lubricated. They are ignored in all parts of JA4 because of their
* random nature.
*
* @return Returns true if the value is a GREASE value, false otherwise.
*/
bool
ja4::Datasource::_is_GREASE(uint16_t value)
{
return std::binary_search(GREASE_values.begin(), GREASE_values.end(), value);
}
72 changes: 72 additions & 0 deletions plugins/experimental/jax_fingerprint/ja4/datasource.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/** @file

@section license License

Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

*/

#pragma once

#include <string_view>
#include <cstdint>

constexpr uint16_t EXT_SNI{0x0};
constexpr uint16_t EXT_ALPN{0x10};
constexpr uint16_t EXT_SUPPORTED_VERSIONS{0x2b};

namespace ja4
{

class Datasource
{
public:
Datasource() = default;
virtual ~Datasource() = default;

enum class Protocol {
DTLS = 'd',
QUIC = 'q',
TLS = 't',
};

enum class SNI {
to_domain = 'd',
to_IP = 'i',
};

Protocol get_protocol();
int get_version();
SNI get_sni_type();
int get_cipher_count();
int get_extension_count();
virtual std::string_view get_first_alpn() = 0;
virtual void get_cipher_suites_hash(unsigned char out[32]) = 0;
virtual void get_extension_hash(unsigned char out[32]) = 0;

protected:
bool _is_GREASE(uint16_t value);

Protocol _protocol;
int _version = 0;
bool _has_ALPN = false;
bool _has_SNI = false;
int _n_ciphers = 0;
int _n_extensions = 0;
};

} // namespace ja4
Loading