Block bad actors and mitigate DDoS attacks with JA4 fingerprints

In my opinion, fraud and abuse prevention starts with identifying groups of traffic. You start with the broadest pool, everything, and as you add more information, it gets narrowed down and split into groups that you start to understand. Eventually you can start taking action: rate limiting, blocking, or allow-listing to keep the good traffic safe and the unwanted traffic off your systems.

The JA4 fingerprint is a powerful tool to identify types of traffic that access your server. Because it helps identify the type of client accessing your server, it is extremely effective at DDoS mitigation and can also be used for access control.

In this blog, I will walk you through two possible use cases of JA4 fingerprint and the Traffic Policy: protecting your apps and APIs from DDoS attacks, and accessing your agents with a JA4-based allowlist.

What is the JA4 fingerprint?

The JA4 fingerprint is calculated from the handshake between client and server when establishing an TLS connection between each other. This means that it can be used for both HTTPS and secure TCP connections.

The basics of secure connection establishment are: 

First, a handshake between client and server is completed to set up the parameters around the basic communication. For ngrok, our base protocol is TCP.

Second, the secure channel is negotiated. This allows the traffic to be encrypted and opaque to outside observers. The secure channel negotiation begins with the “ClientHello” message, in which the client declares what types of encryption it can support and would prefer to use.

This “ClientHello” is what contains the details that are used to create the JA4 fingerprint. If you would like an in-depth understanding of exactly what fields make up the ClientHello, Joshua Davies has a great article on the subject.

Example: DDoS protection

The JA4 fingerprint can effectively tie traffic together across IP addresses when it is originating from a similar source. For example, you can differentiate between the same request that came from a Bash script or Python’s HTTP library without relying on the easily spoofed user-agent.

To use the fingerprint to effectively mitigate DDoS attacks, you can either identify the attacker's fingerprint during an ongoing attack, and block it completely (which would require an update to Traffic Policy), or create rate limit buckets that use the JA4 fingerprint as a key.

on_http_request:
  - actions:
      - type: rate-limit
        config:
          name: Only allow 3000 requests per minute
          algorithm: sliding_window
          capacity: 3000
          rate: 60s
          bucket_key:
            - ${conn.tls.ja4_fingerprint}

Example: Agent access control

ngrok supports many types of access control, IP-based restrictions, oAuth, password, etc. JA4 can fit nicely into the stack if you have dynamic IPs, don’t need something as heavy as session-based management, and have a specific type of client that accesses your endpoints. Perhaps you have an embedded device that connects to your application running behind ngrok.

When your pool of expected traffic comes from similar devices, they will likely share JA4 fingerprints. We can take advantage of this known, finite set, and keep out “unknown” fingerprints of curious 3rd parties from trying to intrude.

Our first step is to identify the fingerprints of all your devices using the Traffic Inspector.

Then, you can embed these “known” JA4 fingerprints into the policy, using the deny Traffic Policy action:

on_tcp_connect:
  - expressions:
      - conn.tls.ja4_fingerprint != 't13d1717h2_5b57614c22b0_e6dcd7ae0a9e'
    actions:
      - type: deny
        config:
          status_code: 403

This Traffic Policy Action blocks all incoming TCP connections that aren’t from the known trusted fingerprint t13d1717h2_5b57614c22b0_e6dcd7ae0a9e

This block action is extremely lightweight and fast because it is completely upstream of your application, and takes action after the first packet is exchanged over the TCP connection. Although it is not nearly as secure as authentication, it is extremely effective at keeping unwanted load off your systems!

Other questions

Is the JA4 fingerprint considered PII or subject to data privacy protection acts?

No. The JA4 fingerprint is not specific to a given user, but rather corresponds to a mechanism of action. It defines a pool of traffic and not a specific user or device.

Is a TLS client fingerprint sufficient to authenticate a user?

No, TLS Client Fingerprinting is not a standalone security solution, and is not the same as authentication.

For authentication, I recommend using OAuth, OpenID, or Basic Auth.

However, much like Restrict IPs, placing limits based on the JA4 fingerprint can add another layer of protection to your ngrok endpoints. Use it as an inexpensive way to shed unwanted traffic, keeping your compute resources dedicated to your expected clients.

Where can I find the JA4 fingerprint for connecting clients?

The client connecting to your ngrok-powered destination is the one that is fingerprinted. The collected fingerprints are available in the Traffic Inspector, in the Request Details view.

Why is the JA4 fingerprint “None”?

The fingerprint is set to “None” when the connection is not made over TLS. When there is no security protocol negotiation there is nothing to fingerprint! Some TCP-powered applications choose speed and low latency over the security of encryption, or fully encrypt their data before connecting to ngrok, rendering an additional layer of encryption unnecessary.

What is the difference between JA4 and JA3?

The JA4 specification was developed by FoxIO as a successor to JA3 fingerprinting, and released under a public domain license. They published some nice documentation in their open source repository if you would like to see the technical details of what parts of the ClientHello exactly are composed into the fingerprint.

JA4 was created as a replacement for JA3 after the Chrome browser made some significant changes in how it presents the TLS handshake, crushing the effectiveness of JA3. Before those changes, JA3 was quite sensitive to minor changes in application versions- e.g. it could differentiate between individual releases of the major browsers. To cope with the changes Chrome made to its handshake, JA4 was designed to have less specificity, its categories are much broader than its predecessor, but more resistant to spoofing.

Eric Leblond of Stamus Networks had a nice article about JA3’s downfall if you want to read more. 

Where can you take JA4 fingerprinting from here?

JA4 fingerprints might not be a silver bullet for preventing abuse and fraud, but they are a precise tool to help you control who (or what) gets access to your APIs and apps. With Traffic Inspector to help you identify pools and the Traffic Policy toolbox to let you take action, you can now do it all in one place.

Ready to start with these fingerprints?

As we learn more about abuse and fraud prevention here at ngrok, we're passing the tools onto you—and JA4 is just one piece of a lot more to come.

Share this post
Allison Carlisle
Allison is a Software Engineer specializing in fraud and abuse prevention.
Authentication
Traffic Inspector
Traffic Policy
Features
Security
Production