Golang原生实现JA3指纹修改,并支持Proxy代理

起因

抓取某个HTTPS网站的时候
开启charles代理能够抓取成功,关闭被风控
通过检测,怀疑可能是tls的时候有区别

尝试

golang的http中,Transport.TLSClientConfig是可以自定义设置的
但起初通过随意设置并不能绕过风控

困难

  1. 使用golang的http客户端,修改DialTLSContext函数的方式是可以实绕过风控,但使用proxy的时候,代码会使用pconn.addTLS(ctx, cm.tlsHost(), trace) 重新以普通方式进行握手,导致JA3修改失败
  2. 因为golang强关联,第三方库并不能完美的集成到现有代码中,都需要重构代码
  3. 某些网站会对于新建链接进行ClientSession检测,因此需要 KeepAlive+ClientSessionCache,这样通过复用连接减少风控概率

最终实现

  1. 只需要拿到合法的参数,并且配置到TLSClientConfig里即可
  2. 使用github.com/refraction-networking/utls中的UTLSIdToSpec拿到CipherSuites并传入
package main
import ("bytes""crypto/tls"tlsx "github.com/refraction-networking/utls""net/http"
)
func main() {c, _ := tlsx.UTLSIdToSpec(tlsx.HelloRandomized)a := &http.Client{Transport: &http.Transport{DisableKeepAlives: false,Proxy: proxy,TLSClientConfig: &tls.Config{InsecureSkipVerify: true,MinVersion:         c.TLSVersMin,MaxVersion:         c.TLSVersMax,CipherSuites:       c.CipherSuites,ClientSessionCache: tls.NewLRUClientSessionCache(32),},},}aw, bw := a.Get("https://tls.browserleaks.com/json")defer aw.Body.Close()var buf bytes.Bufferaw.Write(&buf)println(string(buf.String()), bw)
}

参考文章

  1. https://github.com/baixudong007/gospider
  2. https://juejin.cn/post/7073264626506399751 用Go构建你专属的JA3指纹
  3. https://blog.csdn.net/qq523176585/article/details/127116542 好库推荐|强烈推荐,支持Ja3指纹修改的golang请求库
  4. https://github.com/wangluozhe/requests
  5. https://github.com/refraction-networking/utls
  6. http://www.ctfiot.com/64337.html 如何绕过 JA3 指纹校验?
  7. https://www.coder.work/article/7192419 http - 发送请求时如何使用uTLS连接?
  8. https://segmentfault.com/a/1190000041699815/en Build your own JA3 fingerprint with Go
  9. https://zhuanlan.zhihu.com/p/601474166 curl_cffi: 支持原生模拟浏览器 TLS/JA3 指纹的 Python 库
  10. https://tools.scrapfly.io/api/fp/ja3

历史编写的代码

这些代码都不太好用

package mainimport ("context""fmt"tls "github.com/refraction-networking/utls"xtls "github.com/refraction-networking/utls""net""net/http"
)func GetTransport(helloID *xtls.ClientHelloID) *http.Transport {if helloID == nil {helloID = &xtls.HelloChrome_83}transport := http.DefaultTransport.(*http.Transport).Clone()transport.DialTLSContext = func(ctx context.Context, network, addr string) (_ net.Conn, err error) {dialer := net.Dialer{}con, err := dialer.DialContext(ctx, network, addr)if err != nil {return nil, err}// 根据地址获取host信息host, _, err := net.SplitHostPort(addr)if err != nil {return nil, err}c := transport.TLSClientConfig// 并且不验证host信息xtlsConf := &xtls.Config{ServerName: host,//Renegotiation:      xtls.RenegotiateNever,ClientSessionCache: xtls.NewLRUClientSessionCache(32),NextProtos:         []string{"h2", "http/1.1"},Rand: c.Rand,Time: c.Time,VerifyPeerCertificate: c.VerifyPeerCertificate,RootCAs: c.RootCAs,ClientCAs:                c.ClientCAs,InsecureSkipVerify:       c.InsecureSkipVerify,CipherSuites:             c.CipherSuites,PreferServerCipherSuites: c.PreferServerCipherSuites,SessionTicketsDisabled:   c.SessionTicketsDisabled,SessionTicketKey:         c.SessionTicketKey,MinVersion: c.MinVersion,MaxVersion: c.MaxVersion,DynamicRecordSizingDisabled: c.DynamicRecordSizingDisabled,KeyLogWriter: c.KeyLogWriter,}// 构建tls.UConnxtlsConn := xtls.UClient(con, xtlsConf, *helloID)// 握手err = xtlsConn.HandshakeContext(ctx)if err != nil {return nil, err}fmt.Println("当前请求使用协议:", xtlsConn.HandshakeState.ServerHello.AlpnProtocol)return xtlsConn, err}//transport.DialContext = transport.DialTLSContexttransport.DisableKeepAlives = truereturn transport
}
func CreateHTTPClient() *http.Transport {return &http.Transport{DialTLSContext: func(ctx context.Context, network, addr string) (net.Conn, error) {//initialize the tcp connectiontcpConn, err := (&net.Dialer{}).DialContext(ctx, network, addr)if err != nil {return nil, err}host, _, err := net.SplitHostPort(addr)if err != nil {return nil, err}//initialize the conifg for tlsconfig := tls.Config{ServerName:         host, //set the server name with the provided addrClientSessionCache: xtls.NewLRUClientSessionCache(0),}//initialize a tls connection with the underlying tcop connection and configtlsConn := tls.UClient(tcpConn, &config, tls.HelloRandomized)//start the tls handshake between serverserr = tlsConn.Handshake()if err != nil {return nil, fmt.Errorf("uTlsConn.Handshake() error: %w", err)}return tlsConn, nil},ForceAttemptHTTP2: false,}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/40964.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用Python批量将Word文件转为PDF文件

说明:在使用Minio服务器时,无法对word文件预览,如果有需要的话,可以将word文件转为pdf文件,再存储到Minio中,本文介绍如何批量将word文件,转为pdf格式的文件; 安装库 首先&#xff…

神经网络基础-神经网络补充概念-12-向量化逻辑回归的梯度输出

代码实现 import numpy as npdef sigmoid(z):return 1 / (1 np.exp(-z))def compute_loss(X, y, theta):m len(y)h sigmoid(X.dot(theta))loss (-1/m) * np.sum(y * np.log(h) (1 - y) * np.log(1 - h))return lossdef compute_gradient(X, y, theta):m len(y)h sigmoi…

Python系统学习1-9-类一之类语法

一、类之初印象 1、类就是空表格,将变量(列名)和函数(行为)结合起来 2、创建对象,表达具体行 3、创建类就是创建数据的模板 --操作数据时有提示 --还能再组合数据的行为 --结构更加清晰 4、类的内存分配…

vue项目根据word模版导出word文件

一、安装依赖 //1、docxtemplaternpm install docxtemplater pizzip -S//2、jszip-utilsnpm install jszip-utils -S//3、pizzipnpm install pizzip -S//4、FileSaver npm install file-saver --save二、创建word模版 也就是编辑一个word文档,文档中需要动态取值的…

【JAVA】数组练习

⭐ 作者:小胡_不糊涂 🌱 作者主页:小胡_不糊涂的个人主页 📀 收录专栏:浅谈Java 💖 持续更文,关注博主少走弯路,谢谢大家支持 💖 数组练习 1. 数组转字符串2. 数组拷贝3.…

arm-linux-gnueabihf-g++ gcc编译、优化命令 汇总

gcc优化选项,可在编译时间,目标文件长度,执行效率三个维度,进行不同的取舍和平衡。 gcc 常用编译选项 arm-linux-gnueabihf-g -O3 -marcharmv7-a -mcpucortex-a9 -ftree-vectorize -mfpuneon -mfpuvfpv3-fp16 -mfloat-abihard -…

js的FileSaver.saveAs()方法:监听保存进度,进度条等方法

在使用FileSaver.saveAs保存表格到本地时,如果想要获取导出/保存进度可以如下操作 FileSaver.js的saveAs()方法是一个异步操作,它将文件保存到用户设备上。在调用saveAs()方法后,可以通过使用回调函数、Promise、或监听相关事件来确定saveAs(…

在vue中使用swiper轮播图(搭配watch和$nextTick())

在组件中使用轮播图展示图片信息: 1.下载swiper,5版本为稳定版本 cnpm install swiper5 2.在组件中引入swiper包和对应样式,若多组件使用swiper,可以把swiper引入到main.js入口文件中: import swiper/css/swiper.css //引入swipe…

SpringBoot系列---【SpringBoot在多个profiles环境中自由切换】

SpringBoot在多个profiles环境中自由切换 1.在resource目录下新建dev,prod两个目录,并分别把dev环境的配置文件和prod环境的配置文件放到对应目录下,可以在配置文件中指定激活的配置文件,也可以默认不指定。 2.在pom.xml中最后位置…

07微服务的事务管理机制

一句话导读 在单体应用程序中,事务通常是在单个数据库或单个操作系统中管理的,而在微服务架构中,事务需要跨越多个服务和数据库,这就使得事务管理变得更加复杂和困难。 目录 一句话导读 一、微服务事务管理的定义和意义 二、微…

Layui列表表头去掉复选框改为选择

效果&#xff1a; 代码&#xff1a; // 表头复选框去掉改为选择 $(".layui-table th[data-field"0"] .layui-table-cell").html("<span>选择</span>");

做好以下几点,可以让我们延长周末体验感,好好放松!!!

工作以后常常容易感到疲于奔命&#xff0c;让我们找到适合自己方式&#xff0c;来让我们度过一个充实放松的周末! 方向一&#xff1a;分享你周末的时间规划 我们可以把每个月当做一个周期&#xff0c;制定一个简单的计划&#xff0c;如&#xff1a;第一周&#xff0c;锻炼身体…

基于Prometheus监控Kubernetes集群

目录 一、环境准备 1.1、主机初始化配置 1.2、部署docker环境 二、部署kubernetes集群 2.1、组件介绍 2.2、配置阿里云yum源 2.3、安装kubelet kubeadm kubectl 2.4、配置init-config.yaml 2.5、安装master节点 2.6、安装node节点 2.7、安装flannel、cni 2.8、部署测…

Go 1.21新增的内置函数(built-in functions)详解

Go 1.21新增的内置函数分别是 min、max 和 clear&#xff0c;接下来看下这几个函数的用途和使用示例。 在编程过程中&#xff0c;需要知道一组值中的最大或最小值的场景是很常见的&#xff0c;比如排序、统计等场景。之前都需要自己写代码来实现这个功能&#xff0c;现在 Go 1…

低成本无刷高速吹风机单片机方案

高速吹风机的转速一般是普通吹风机的5倍左右。一般来说&#xff0c;吹风机的电机转速一般为2-3万转/分钟&#xff0c;而高速吹风机的电机转速一般为10万转/分钟左右。高转速增加了高风速。一般来说&#xff0c;吹风机的风力只有12-17米/秒&#xff0c;而高速吹风机的风力可以达…

安卓获取当前的IP地址

文章目录 获取IP地址完整示例代码 获取IP地址 在安卓中&#xff0c;我们使用静态方法NetworkInterface.getNetworkInterfaces() 来获取当前设备上所有的网络接口。 网络接口是指设备上用于进行网络通信的硬件或软件。这些接口可以是物理接口&#xff08;如以太网接口、无线网…

使用Docker搭建MySQL主从复制(一主一从)

Docker安装MySQL docker pull mysql:5.7 docker images mysql安装步骤 1.新建主服务器容器实例3307 docker run -p 3307:3306 --name mysql-master -v /usr/local/docker/mysql5.7/data/mysql-master/logs:/var/log/mysql -v /usr/local/docker/mysql5.7/data/mysql-master/…

Day 31 C++ STL常用算法(下)

文章目录 常用拷贝和替换算法copy——容器内指定范围的元素拷贝到另一容器中函数原型注意——利用copy算法在拷贝时&#xff0c;目标容器要提前开辟空间示例 replace——将容器内指定范围的第一个旧元素修改为新元素函数原型注意——replace只会替换区间内满足条件的第一个旧元…

cve-2016-7193:wwlib 模块堆数据结构溢出

简介 漏洞编号&#xff1a;cve-2016-7193漏洞类型&#xff1a;堆溢出软件名称&#xff1a;Office模块名称&#xff1a;wwlib历史漏洞&#xff1a;较多影响的版本 攻击利用&#xff1a;APT 攻击利器-Word 漏洞 CVE-2016-7193 原理揭秘 操作环境 系统&#xff1a;Win10 1607软…

C++ 动态内存

C 动态内存 C 程序中的内存分为两个部分&#xff1a; 栈&#xff1a;在函数内部声明的所有变量都将占用栈内存堆&#xff1a;这是程序中未使用的内存&#xff0c;在程序运行时可用于动态分配内存 很多时候&#xff0c;无法提前预知需要多少内存来存储某个定义变量中的特定信…