一日一技:Golang 如何突破 JA3?
在之前的文章里面,我们讲到了网站通过 JA3算法,利用一些指纹信息来识别你的请求,无论你是否使用了代理 IP,网站都能识别到你。
今天我们首先讲讲在 Golang 下面,如何修改这个指纹。
我们先来写一段代码,观察在使用了代理以后, Golang 的 JA3指纹依然不变:
package main
import (
"crypto/tls"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"time"
)
func req() {
proxyUrl, err := url.Parse("http://隧道代理IP:PORT")
client := &http.Client{
Transport: &http.Transport{Proxy: http.ProxyURL(proxyUrl),
TLSClientConfig: &tls.Config{InsecureSkipVerify: false}},
}
resp, err := client.Get("https://httpbin.org/ip")
if err != nil {
fmt.Println(err)
}
defer resp.Body.Close()
content, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println(err)
}
fmt.Println(string(content))
}
func main() {
for i := 0; i < 10; i++ {
req()
time.Sleep(time.Second)
}
}
运行效果如下图所示:
但是,当我要访问 JA3测试页面的时候,发现返回的签名字符串始终是一样的:
为了解决这个问题,我们可以使用一个第三方的包,叫做: ja3transport[1] 。
这个包的使用方法如下面代码所示:
package main
import (
"fmt"
"github.com/CUCyber/ja3transport"
tls "github.com/refraction-networking/utls"
"io/ioutil"
"net/http"
)
type Browser struct {
Ja3 string
UserAgent string
}
func req(browser Browser) {
config := tls.Config{
InsecureSkipVerify: true,
}
tr, _ := ja3transport.NewTransportWithConfig(browser.Ja3, &config)
client := &http.Client{
Transport: tr,
}
req, _ := http.NewRequest("GET", "https://ja3er.com/json", nil)
req.Header.Set("User-Agent", browser.UserAgent)
resp, err := client.Do(req)
if err != nil {
fmt.Println(err)
}
defer resp.Body.Close()
content, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println(err)
}
fmt.Println(string(content))
}
func main() {
ja3List := []Browser{
{Ja3: "771,4865-4866-4867-49195-49199-49196-49200-52393-52392-49171-49172-156-157-47-53-10,0-23-65281-10-11-35-16-5-13-18-51-45-43-27,29-23-24,0",UserAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.2 Safari/605.1.15"},
{Ja3: "771,4865-4866-4867-49196-49195-52393-49200-49199-52392-49188-49187-49162-49161-49192-49191-49172-49171-157-156-61-60-53-47-49160-49170-10,0-23-65281-10-11-16-5-13-18-51-45-43-21,29-23-24-25,0", UserAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36 Edg/92.0.902.67"},
{Ja3: "771,4865-4866-4867-49196-49195-49188-49187-49162-49161-52393-49200-49199-49192-49191-49172-49171-52392-157-156-61-60-53-47-49160-49170-10,65281-0-23-13-5-18-16-11-51-45-43-10-21,29-23-24-25,0", UserAgent: "Mozilla/5.0 (iPhone; CPU iPhone OS 13_1_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.1 Mobile/15E148 Safari/604.1"},
}
for _, ja3 := range ja3List{
req(ja3)
}
}
运行效果如下图所示:
这段代码的关键是:tr, _ := ja3transport.NewTransportWithConfig(browser.Ja3, &config)
,这一行代码,把我们自定义的 JA3指纹字符串传入进去,这个库在发起请求的时候,修改请求的数据包,用我们自定义的指纹字符串替换原来的默认字符串,从而实现修改 JA3指纹的目的。大家关注上面图中我标记的3个ja3_hash
。他们不同了,说明修改 JA3指纹成功。
JA3有自己的生成规则,所以并不能随便乱改。但确实里面有一些地方也可以改。大家可以用测试网站进行测试,看改了以后能不能正确返回不同的 ja3_hash
。如果能返回,说明改对了。如果报错了,说明改错了。
当然,最简单的方法是收集尽可能多的不同类别不同型号的浏览器指纹和对应的 User-Agent,然后随机选择一对,轮换使用,这样就可以有效规避网站对 JA3字符串频率的检查。
关于今天用到的ja3transport
,如果大家有兴趣可以去看作者写的文章,介绍了这个包的工作原理: Impersonating JA3 Fingerprints.[2] 。
好了,今天使用 Golang 突破 JA3的方法就介绍到这里。请大家期待后面使用 Python 突破 JA3的方法。
参考文献
[2] Impersonating JA3 Fingerprints.: https://medium.com/cu-cyber/impersonating-ja3-fingerprints-b9f555880e42
- 点赞
- 收藏
- 关注作者
评论(0)