【Python工程师之requests如何突破 JA3 指纹】

前言

之前一期我讲过怎么利用scrapy去突破指纹,这一期来讲讲怎么用python原生库requests突破指纹。

正文

首先,我们知道请求是基于urllib3实现的。为了修改与JA3相关的基础参数,今天我们将在urllib3中修改一些东西。
我们知道,JA3指纹里面,有一个很大的部分,叫做 CipherSuits。默认加密算法如下:

ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+HIGH:DH+HIGH:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+HIGH:RSA+3DES:!aNULL:!eNULL:!MD5

冒号将不同加密算法分割开来。每一种加密算法都对应着JA3字符串,只要修改顺序,就可以得到不同的JA3字符串。
requests中,修改 Cipher Suits中的加密算法需要修改urllib3中的 ssl上下文,并实现 HTTP适配器(HTTP Adapter)。在这个适配器中,每次请求都会随机地更换加密算法。但有一点需要注意!ANULL:!EULL:!不需要修改MD5,把它们放在最后。
所涉及的代码如下:

from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.ssl_ import create_urllib3_context

ORIGIN_CIPHERS = ('ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+HIGH:'
'DH+HIGH:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+HIGH:RSA+3DES')


class DESAdapter(HTTPAdapter):
    def __init__(self, *args, **kwargs):
        """
        A TransportAdapter that re-enables 3DES support in Requests.
        """
        CIPHERS = ORIGIN_CIPHERS.split(':')
        random.shuffle(CIPHERS)
        CIPHERS = ':'.join(CIPHERS)
        self.CIPHERS = CIPHERS + ':!aNULL:!eNULL:!MD5'
        super().__init__(*args, **kwargs)
        
        
    def init_poolmanager(self, *args, **kwargs):
        context = create_urllib3_context(ciphers=self.CIPHERS)
        kwargs['ssl_context'] = context
        return super(DESAdapter, self).init_poolmanager(*args, **kwargs)

    def proxy_manager_for(self, *args, **kwargs):
        context = create_urllib3_context(ciphers=self.CIPHERS)
        kwargs['ssl_context'] = context
        return super(DESAdapter, self).proxy_manager_for(*args, **kwargs)

一般来说,实现子类时,init__的第一行应该是 super ().init(* args,** kwargs),但是由于init_poolmanagerproxy_manager_for是复写父类的两种方法。因此,当我们随机设置 CipherSuits时,需要将它放在 super ().init( args,* kwargs)**前面。
有了适配器,当我们使用 requests时,初始化会话,然后绑定到特定网站:

import requests
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.134 Safari/537.36 Edg/103.0.1264.71'}
s = requests.Session()
s.headers.update(headers)

for _ in range(3):
    s.mount('https://ja3er.com', DESAdapter())
    resp = s.get('https://ja3er.com/json').json()
    print(resp)

其中,s.mount的第一个参数表示该适配器仅在以https://ja3er.com开头的网址中生效。
运行效果如下:

图片

可以看到,ja3_hash已经改变了,说明我们请求时的 JA3指纹已经发生了改变。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值