golang web服务端 使用ja3 识别爬虫
网站例子
为什么要用ja3?
- 反爬的代码改动非常小,只需要在几个回调函数中修改即可
- 非常有效的识别python 的请求.
- 更好的和现有的反爬系统相结合,并大幅提高反爬的成功率
gospider 介绍
gospider 是一个golang 爬虫神器,它也提供了服务端ja3指纹加密验证功能
安装
go get -u gitee.com/baixudong/gospider
gitee地址
https://gitee.com/baixudong/gospider
github地址
https://github.com/baixudong007/gospider
ja3 模块
"gitee.com/baixudong/gospider/ja3"
代码示例
http.Server 设置回调函数,GetConfigForClient,ConnContext
server := &http.Server{
ConnContext: ja3.ConnContext,
TLSConfig: &tls.Config{
GetConfigForClient: ja3.GetConfigForClient,
},
}
gin 中使用ja3指纹,可以拦截如下python 库
- requests
- httpx
- urllib
- urllib3
handle.GET("/", func(ctx *gin.Context) {
ja3ContextData := ja3.GetRequestJa3Data(ctx.Request)
ja3Name, ja3Ok := ja3ContextData.Verify()//返回设备名称,是否是安全流量
ja3Md5:=ja3ContextData.Md5()//返回ja3的md5 值
var msg string
if ja3Ok {
msg = "安全的访问"
} else {
msg = "不安全的访问,请使用浏览器访问,这次请求将被拦截"
}
ctx.JSON(200, map[string]any{
"msg": msg,
"id": ja3Md5,
"设备": ja3Name,
})
})
通过 Proto 判断过滤异常流浪
目前浏览器绝大部分都普及了http2,如果发现客户端没有自动升级到http2可以直接判断为异常流量
- requests
- urllib
- urllib3
handle.GET("/", func(ctx *gin.Context) {
var msg string
if ctx.Request.Proto == "HTTP/2.0" {
msg = "安全的访问"
} else {
msg = "不安全的访问,请使用浏览器访问,这次请求将被拦截"
}
ctx.JSON(200, map[string]any{
"msg": msg,
})
})
通过连接是否复用判断,异常流量
由于http2的特性,大部分的连接都会快速的复用,即使没有复用,服务端也可以通过设置使客户端复用连接然后获取数据,如果所有的连接都没有复用那么绝对是异常流量,python中非常有名的指纹请求库都不能复用连接,例如:
- pyhttpx
- curl_cffi
handle.GET("/", func(ctx *gin.Context) {
if !ja3ContextData.Init {//没有复用连接
ja3ContextData.Init = true
//连接没有复用,通知客户端重新尝试一下即可
return
}
//走到这一步说明客户端的连接得到复用,那么它既是正常流量
})
将上面三种手段组合在一起,能干掉99%的python 爬虫,剩下的等我碰到了再升级手段。
辅助提高反爬手段的方法
- 结合浏览器指纹,通过和浏览器指纹一起检测可以大幅提高反爬效率
- 客户端加密一些校验的参数到服务端,服务端颁发token(无论是否校验通过都颁发,这样可以迷惑爬虫,由于服务端知道token是否校验通过,可以在关键数据卡生成假数据迷惑爬虫),这样爬虫会耗费大量时间精力去找问题,可能最后都找不到
ja3反爬最好以隐性的方式辅助其他反爬手段,如果上来爬虫就知道使用ja3反爬了,那么爬虫会立马切换请求库,这样会变相的降低反爬虫效果。结合其它手段,让爬虫认为问题出现在其它手段上,而不往ja3上面想,从而形成降维打击。 因为几乎所有的爬虫从业者都不会上来就使用具有反指纹的请求库(具有ja3反指纹的请求库从来不会是爬虫程序员的默认请求库)。就算使用了,因为有其它反爬手段打掩护,也会给爬虫误判。从而极大提高反爬效果。