我之前的文章介紹了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即可
具體效果可以往下看
解壓後如上圖,包含2個檔案
-
ja3proxy.exe ja3proxy是go開發的一個控制檯程式 -
localhost_root.pfx 本地證照
(測試加我要)
為了方便本機測試,先安裝localhost_root.pfx證照, (如果不安裝證照,也可以執行,只不過你需要將請求忽略ssl verify)
證照密碼為123456
選擇位置為:受信任的根證照頒發機構
安裝成功後,使用如下命令 執行ja3proxy.exe
ja3proxy.exe -pfxFile=localhost_root.pfx -pfxPwd=123456
支援的引數共有如下:
-
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);
});
h2的header順序:m,a,s,p 和chrome保持一致
原理
ja3proxy(是一箇中間人)接管你的請求,然後自己去目標建立tls,clienthello就用你指定的ja3引數