突破tls/ja3新轮子
我之前的文章介绍了SSL指纹识别
https://mp.weixin.qq.com/s/BvotXrFXwYvGWpqHKoj3uQ
很多人来问我BYPass的方法
主流的BYPASS方法有两大类:
-
使用定制ja3的网络库 go在这块的库比较流行(比如go的库requests还有cycletls) 缺点在于,就是得用go语言开发(cycletls有nodejs的但是也是开了一个go语言的一个websocket)
-
魔改curl,最有名的就是curl-impersonate 对应win版本的 https://github.com/depler/curl-impersonate-win 缺点就是编译复杂,使用方式上,得用包装curl的第三方库,用的多就是python的pycurl 其他语言的比较少
正好五一有时间,站在巨人们的肩膀上我用go语言开发了一个代理服务.
只需要设置这个代理服务,就可以自定义ja3参数
这样任何语言都可以直接用了,而且只需要加一个webproxy即可
具体效果可以往下看
image解压后如上图,包含2个文件
- ja3proxy.exe ja3proxy是go开发的一个控制台程序
- localhost_root.pfx 本地证书
(测试加我要)
为了方便本机测试,先安装localhost_root.pfx证书, (如果不安装证书,也可以运行,只不过你需要将请求忽略ssl verify)
证书密码为123456
image选择位置为:受信任的根证书颁发机构
image安装成功后,使用如下命令 运行ja3proxy.exe
ja3proxy.exe -pfxFile=localhost_root.pfx -pfxPwd=123456
image
支持的参数共有如下:
- pfxFile (pfx类型证书)
- pfxPwd (pfx证书的密码)
- authName 如果你要开启ja3proxy代理服务的basicauth认证,可以设置
- authPwd (同上)
- httpPort (ja3proxy代理的http端口,默认为8080)
- httpsPort (ja3proxy代理的https端口,默认为8443)
- certFile 非pfx类型证书可以设置
- keyFile 同上
ja3proxy运行成功后,测试代码如下:
var proxy = new WebProxy
{
// 这就是我们的ja3proxy
Address = new Uri($"http://localhost:8080")
};
var httpClientHandler = new HttpClientHandler
{
Proxy = proxy,
};
// 因为我们再上面把证书添加到本机受信任了 所以这行代码不需要,如果你不操作受信任证书的话,就需要
//httpClientHandler.ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
var client2 = new HttpClient(handler: httpClientHandler, disposeHandler: true);
// 设置ja3指纹
client2.DefaultRequestHeaders.Add("tls-ja3","771,4865-4866-4867-49195-49199-49196-49200-52393-52392-49171-49172-156-157-47-53,17513-10-18-11-51-13-27-0-35-65281-43-16-45-5-23-21,29-23-24,0");
// 设置ja3proxy执行请求的超时
client2.DefaultRequestHeaders.Add("tls-timeout","10");
// 设置ja3proxy执行请求用代理,设置后请求目标服务器拿到的就是代理ip
// client2.DefaultRequestHeaders.Add("tls-proxy","http://252.45.26.333:5543");
// 设置当前请求的useragent
client2.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36");
var result = await client2.GetStringAsync("https://kawayiyi.com/tls");
Console.WriteLine(result);
执行后,校验ja3一致
{
"sni": "kawayiyi.com",
"tlsVersion": "Tls13",
"tcpConnectionId": "0HMQ8N2PQCRQE",
"random": "AwN2jHvxe/TKafrfmZ1KG2JWrD7u6M1N4dpeIGdYQwA=",
"sessionId": "FvNiwCLizsA2JZt0/8865tX2A5VsfbgjlCu4Qg4jPjg=",
"tlsHashOrigin": "771,4865-4866-4867-49195-49199-49196-49200-52393-52392-49171-49172-156-157-47-53,17513-10-18-11-51-13-27-0-35-65281-43-16-45-5-23-21,29-23-24,0",
"tlsHashMd5": "05556c7568c3d3a65c4e35d42f102d78",
"cipherList": [
"TLS_AES_128_GCM_SHA256",
"TLS_AES_256_GCM_SHA384",
"TLS_CHACHA20_POLY1305_SHA256",
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
"TLS_RSA_WITH_AES_128_GCM_SHA256",
"TLS_RSA_WITH_AES_256_GCM_SHA384",
"TLS_RSA_WITH_AES_128_CBC_SHA",
"TLS_RSA_WITH_AES_256_CBC_SHA"
],
"extentions": [
"extensionApplicationSettings",
"supported_groups",
"signed_certificate_timestamp",
"ec_point_formats",
"key_share",
"signature_algorithms",
"compress_certificate",
"server_name",
"session_ticket",
"renegotiation_info",
"supported_versions",
"application_layer_protocol_negotiation",
"psk_key_exchange_modes",
"status_request",
"extended_master_secret",
"padding"
],
"supportedgroups": [
"X25519",
"CurveP256",
"CurveP384"
],
"ecPointFormats": [
"uncompressed"
],
"proto": "HTTP/2",
"h2": {
"SETTINGS": {
"1": "65536",
"3": "1000",
"4": "6291456",
"5": "16384",
"6": "262144"
},
"WINDOW_UPDATE": "15663105",
"HEADERS": [
":method",
":authority",
":scheme",
":path"
]
},
"user_agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36",
"clientIp": "103.219.192.197"
}
nodejs测试
const request = require('request');
const options = {
url:'https://kawayiyi.com/tls',
method: 'GET',
headers: {
'tls-ja3':'771,4865-4866-4867-49195-49199-49196-49200-52393-52392-49171-49172-156-157-47-53,17513-10-18-11-51-13-27-0-35-65281-43-16-45-5-23-21,29-23-24,0',
'tls-timeout':'10',
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36', // 设置请求头中的 User-Agent
},
proxy: 'http://localhost:8080',
strictSSL:false
};
request.get(options, (error, response, body) => {
if (error) {
console.error(error);
return;
}
console.log('body:', body);
});
image
h2的header顺序:m,a,s,p 和chrome保持一致
原理
imageja3proxy(是一个中间人)接管你的请求,然后自己去目标建立tls,clienthello就用你指定的ja3参数
使用方式(20230617新增)
header中支持添加如下几项
tls-ja3:771,4865-4866-4867-49195-49199-49196-49200-52393-52392-49171-49172-156-157-47-53,0-23-65281-10-11-35-16-5-13-18-51-45-43-27-17513-21,29-23-24,0 (可以https://tls.peet.ws/api/all查看)
tls-timeout: 10 (单位s 代表proxy去发请求的超时时间)
tls-h2settings:1:65536,2:0,3:1000,4:6291456,6:262144 (可以https://tls.peet.ws/api/all查看http2.sent_frames)
tls-proxy:http://127.0.0.1:1080 (代表proxy发请求的时候走代理,也支持socks5://127.0.0.1:1080)
tls-https:true (代表会将你请求的http升级为https,好处是你不需要导入证书,也不必用代码来忽略证书问题)
可以关注后回复ja3proxy下载,包含windows,linux,mac三端都可以用,
license找我免费颁发。
如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,转载文章之后须在文章页面明显位置给出作者和原文连接,谢谢。