什么是TLS指纹以及如何绕过它

TLS 指纹分析是网站用来防止恶意攻击的反机器人检测解决方案之一。使用此方法,Web 服务器能够识别哪个 Web 客户端正在尝试发起对话,然后决定是阻止还是允许该请求。

虽然他们的目标不是道德数据提取工具,但您的网络抓取工具可能仍然会被阻止。

在本文中,我们将通过讨论它是什么、它如何工作以及解决它的不同方法来指导您如何绕过 TLS 指纹识别以用于道德网络抓取目的。

什么是 TLS 指纹识别?

TLS 指纹识别是一种流行的服务器端指纹识别技术。在高度准确的情况下,它使网络服务器能够确定网络客户端的身份,在任何应用程序数据交换发生之前仅使用第一个数据包连接中的参数。Web 客户端,在这种情况下指的是发起请求的应用程序,可以是浏览器、CLI 工具、脚本(机器人)等。Cloudflare等解决方案使用 TLS 指纹来识别和记录恶意攻击。

一种不同类型的指纹识别是客户端指纹识别,它涉及使用 JavaScript 测试客户端。这可能是另一天的讨论,但对于本文,我们的重点是服务器端指纹识别。

TLS 代表“传输层安全性”,它是一种加密协议,旨在保护 Web 客户端和服务器之间的连接。虽然它经常与 SSL 互换使用,但 TLS 是从 SSL 演变而来的,现在是当今使用最广泛的 Web 通信安全协议。

当网络抓取工具向 HTTPS 网站发送请求时,它会通过 TLS 安全性进行发送。虽然这对网络抓取工具没有特别的意义,但在其网络中使用 TLS 指纹的网站不仅将您识别为恶意机器人,而且还完全拒绝您访问。

TLS 指纹如何工作?

对于通过安全通道与 Web 服务器通信的 Web 客户端,双方必须就该对话的加密算法和加密密钥达成一致。该协议是通过TLS 握手达成的:客户端和服务器交换建立安全连接所需的重要信息的整个序列。

通常,客户端在此握手中的第一个方法是使用 TLS 客户端的问候消息,客户端在其中声明它支持的 TLS 参数集。其中一些参数包括:

  • 它支持的最大 TLS 版本(TLS 1.0 – TLS 1.3)。
  • 密码套件列表,即用于加密的密码算法。
  • 支持的扩展列表。

每个客户端使用不同的 TLS 库,其中包括 Firefox – NSS、Chrome – BoringSSL、Python – OpenSSL 和 Safari – Secure Transport,因此这些参数的值因 Web 客户端而有很大差异。

由于此消息未加密,我们可以使用 Wireshark 等 NSM 工具查看它。下面是Chrome 发送到维基百科的TLS客户端问候消息,由 Wireshark 捕获。

tls-client-hello-message

树、它们的内容和它们的顺序,特别是密码套件的顺序因 Web 客户端而异。以下是 Chrome 的密码套件内容和顺序:

cipher-suite

TLS 协议很复杂,信息量很大,从上面的client hello示例中的扩展数量可以看出。每个扩展都包含自己的一组参数,例如一些客户端支持伪造的 TLS 扩展 GREASE。

使用所有这些信息,TLS 指纹识别可以计算 TLS 签名,也称为 Web 客户端的“指纹”。服务器然后在发送任何类型的数据之前使用此签名来推断客户端,这就是发生阻塞的地方。

那么,这个签名是如何创建的呢?如果我们了解生成此签名的幕后发生的事情,我们就可以执行 TLS 指纹绕过。

TLS 签名计算

TLS 指纹识别基于未加密的客户端问候消息中的参数,使其对连接路径上的任何人都可见。通过按顺序获取每个参数的 ID 并对结果字符串进行哈希处理,我们可以获得唯一的指纹。生成它的实际标准算法称为 JA3。

JA3 的工作原理是连接客户端问候消息中五个字段的字节的十进制值,然后对它们进行哈希处理。这些字段是:

TLS version 
Cipher suites 
Extensions 
Elliptic curves 
Elliptic curve point formats

每个字段由逗号 (“,”) 分隔,字段中的元素由破折号 (“-“) 分隔。然后使用 MD5 对该字符串进行哈希处理以生成其 JA3 指纹。

由于 JA3 已集成到 Wireshark 中,我们可以从前面的示例中看到我们的 JA3 完整字符串和指纹。

771,4867-4865-4866-52393-52392-49195-49199-49196-49200-49171-49172-156-157-47-53,0-23-65281-10-11-35-16-5-13-18-51-45-43-27-17513-21-41,29-23-24,0

MD5指纹

fedca33016b974c390faa610378b5a62

简而言之,每个 Web 客户端都有一个独特的指纹,检测发出 HTTPS 请求的客户端类型就像将签名与数据库匹配一样简单。以下是一些 Web 客户端及其签名:

Firefox 94: 2312b27cb2c9ea5cabb52845cafff423 
Firefox 87: bc6c386f480ee97b9d9e52d472b772d8 
Chrome 97: b32309a26951912be7dba376398abc3b 
Chrome 70: 5353c0796e25725adfdb93f35f5a18f7

如何绕过 TLS 指纹识别

让我们快速浏览一下教程,我们将使用 NodeJS。因此,您需要安装Node和 npm(某些系统已预先安装)。通过运行 npm install 安装所有必要的库:

npm init -y 
npm install axios

理想情况下,您可以通过使用合法 Web 客户端的客户端问候消息来掩盖您的客户端问候消息来击败 TLS 指纹识别。如果您的请求生成与最新版本的 Firefox 相同的 TLS 指纹,则没有服务器会发现差异。

事实是,它要复杂得多。使用脚本或命令行工具不容易控制或操纵客户端问候消息的大多数字段。

例如,在 NodeJS 和 Python 中,您可以控制密码套件列表,在某些情况下还可以控制 TLS 版本,但不能更多。TLS 扩展命令几乎已经就位。

在实施 TLS 指纹识别时,服务器无法基于锁定的指纹白名单数据库运行。当 Web 客户端或 TLS 库发布新版本时,会出现新的指纹。因此,他们不得不依靠黑名单数据库为生。

我们可以利用这一点,这意味着如果我们可以生成一个不在服务器的阻止列表数据库中的新指纹,我们就可以绕过它的 TLS 指纹阻止。

您可以通过重新排列特定的密码顺序在 Node.js 中实现这一点。Node.js v19的默认密码列表是:

node -p crypto.constants.defaultCoreCipherList | tr ':' 'n' 
TLS_AES_256_GCM_SHA384 
TLS_CHACHA20_POLY1305_SHA256 
TLS_AES_128_GCM_SHA256 
ECDHE-RSA-AES128-GCM-SHA256 
ECDHE-ECDSA-AES128-GCM-SHA256 
ECDHE-RSA-AES256-GCM-SHA384 
ECDHE-ECDSA-AES256-GCM-SHA384 
DHE-RSA-AES128-GCM-SHA256 
ECDHE-RSA-AES128-SHA256 
DHE-RSA-AES128-SHA256 
ECDHE-RSA-AES256-SHA384 
DHE-RSA-AES256-SHA384 
ECDHE-RSA-AES256-SHA256 
DHE-RSA-AES256-SHA256 
HIGH 
!aNULL 
!eNULL 
!EXPORT 
!DES 
!RC4 
!MD5 
!PSK 
!SRP 
!CAMELLIA

如果您以任何方式更改上述列表的顺序,您将获得一个新的指纹。但是您应该如何进行这些更改呢?

如果您熟悉密码,您会注意到前三个密码都是强烈推荐的 TLS v 1.3 密码,因此所有现代客户端都将它们作为首选,但顺序不同。

从我们之前的 Wireshark 捕获中,我们可以看到 Chrome 使用这些与第一个选项相同的密码,但顺序如下。

chrome-ciphers

保留前三个是安全的,但打乱剩余的密码,您可以使用具有此配置的 Node.js 绕过 TLS 指纹检查。

const crypto = require('crypto'); 
 
const request = require('request'); 
const https = require('https'); 
 
const nodeOrderedCipherList = crypto.constants.defaultCipherList.split(':'); 
 
    // keep the most important ciphers in the same order 
    const fixedCipherList = nodeOrderedCipherList.slice(0, 3); 
 
    // shuffle the rest 
    const shuffledCipherList = nodeOrderedCipherList.slice(3) 
        .map(cipher => ({ cipher, sort: Math.random() })) 
        .sort((a, b) => a.sort - b.sort) 
        .map(({ cipher }) => cipher);

您甚至可以进一步重新排序前三个密码,但您必须小心。某些密码列表重新排列可能会危及您的请求安全性。因此,如果您正在从事安全敏感的项目,请确保您进行了研究。此外,绕过Akamai 指纹识别等解决方案可能需要更多工作。这里的目标是确保您的指纹不会太罕见而被列入黑名单。

其他绕过 TLS 指纹识别的方法

还有其他可用的方法来运行 TLS 指纹绕过。最受欢迎的选项包括:

无头浏览器

当您在抓取时以无头模式运行浏览器时,您会获得该浏览器的指纹。因此网络服务器将您视为浏览器网络客户端。

Python

您可以通过使用HTTP 适配器和请求欺骗密码套件和 TLS 版本来绕过 Python 中的 TLS 指纹检测。

爪哇

在 Java 中,您可以使用该方法重新配置已启用的密码套件列表ssl-config.enabledCipherSuites您可以在其文档中找到更多信息。

Go

Go 是一种支持 JA3 签名伪造的编程语言,它通过欺骗JA3 算法使用的客户端问候消息的五个字段来识别 TLS 签名。这可以使用以下 Golang 库,如Refraction Networking 的 utlsja3transport

结论

虽然我们已经了解了一些关于如何在不被阻止的情况下抓取网页的技巧,但在本教程中,我们更侧重于绕过 TLS 指纹识别。

我们知道逃避 TLS 指纹识别并不意味着合适,但是您可以通过将指纹更改为未列入黑名单的指纹来获得成功。

回顾一下,以下是绕过 TLS 指纹的方法:

  1. 获取默认密码列表。
  2. 保持前三个密码的顺序固定。
  3. 打乱其余的。

类似文章