Skip to content

Commit

Permalink
fix: 增加JA3_PROXY的配置,方便后续更新
Browse files Browse the repository at this point in the history
  • Loading branch information
liuhuapiaoyuan committed Apr 16, 2024
1 parent eed4abb commit d8633a8
Show file tree
Hide file tree
Showing 22 changed files with 212 additions and 45 deletions.
113 changes: 96 additions & 17 deletions backend-api/backend-api.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"chatgpt-mirror-server/config"
"chatgpt-mirror-server/modules/chatgpt/model"
"chatgpt-mirror-server/modules/chatgpt/service"
"chatgpt-mirror-server/utility"
"compress/gzip"
"crypto/tls"
"io"
Expand Down Expand Up @@ -48,6 +49,69 @@ func NotFound(r *ghttp.Request) {
r.Response.WriteStatus(http.StatusNotFound)
}

// 代理请求
func ProxyRequestGet(path string, r *ghttp.Request) (resStr string, err error) {
ctx := r.GetCtx()
userToken := ""
Authorization := r.Header.Get("Authorization")
if Authorization != "" {
userToken = r.Header.Get("Authorization")[7:]
}
userId, chatgptId, accessToken, err := ChatgptSessionService.GetAccessToken(ctx, userToken)

g.Log().Debug(ctx, "userToken", userToken)
g.Log().Debug(ctx, "userId", userId)
g.Log().Debug(ctx, "chatgptId", chatgptId)
UpStream := config.CHATPROXY(ctx)
if err != nil {
// 处理错误
panic(err)
}

// 设置HTTP Transport
transport := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
if config.Ja3Proxy != nil {
g.Log().Debug(ctx, "存在ja3proxy 重新配置")

transport = &http.Transport{
Proxy: http.ProxyURL(config.Ja3Proxy),
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
}
}
// 创建HTTP客户端
client := &http.Client{Transport: transport}

// 设置请求头
req, err := http.NewRequestWithContext(ctx, "GET", UpStream+"/backend-api/me", nil)
if err != nil {
// 处理错误
panic(err)
}
req.Header.Add("Authorization", "Bearer "+accessToken)
req.Header.Add("User-Agent", r.Header.Get("User-Agent"))
req.Header.Set("Host", "chat.openai.com")
req.Header.Set("Origin", "https://chat.openai.com/chat")
req.Header.Set("Referer", "https://chat.openai.com/")

// 使用客户端发送请求
resp, err := client.Do(req)
if err != nil {
// 处理错误
panic(err)
}
defer resp.Body.Close()
originalBody, shouldReturn, err := loadRespString(resp)
if err != nil || shouldReturn {
return "", err
}
return string(originalBody), nil

}

func ProxyAll(r *ghttp.Request) {

ctx := r.GetCtx()
Expand All @@ -72,28 +136,43 @@ func ProxyAll(r *ghttp.Request) {
r.Response.WriteStatus(http.StatusUnauthorized)
return
}
UpStream := config.CHATPROXY(ctx)
WsUpStream := config.WS_SERVICE(ctx)
u, _ := url.Parse(UpStream)
proxy := httputil.NewSingleHostReverseProxy(u)
// g.Log().Info(ctx, "ProxyBackendApi:", path)
proxy := &httputil.ReverseProxy{}
UpStream := config.CHATPROXY(ctx)

proxy.Transport = &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
}
proxy.ErrorHandler = func(writer http.ResponseWriter, request *http.Request, e error) {
g.Log().Error(ctx, e)
writer.WriteHeader(http.StatusBadGateway)
if config.Ja3Proxy != nil {
proxy.Transport = &http.Transport{
Proxy: http.ProxyURL(config.Ja3Proxy),
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
}
}
newreq := r.Request.Clone(ctx)
newreq.URL.Host = u.Host
newreq.URL.Scheme = u.Scheme
newreq.Host = u.Host
newreq.Header.Set("authkey", config.AUTHKEY(ctx))

newreq.Header.Set("Host", "chat.openai.com")
newreq.Header.Set("Origin", "https://chat.openai.com/chat")
OPENAI, err := url.Parse(UpStream)
if err != nil {
g.Log().Error(ctx, err)
r.Response.WriteStatus(http.StatusServiceUnavailable)
return
}
proxy.Rewrite = func(proxyRequest *httputil.ProxyRequest) {
proxyRequest.SetURL(OPENAI)
}

header := r.Request.Header
header.Set("Origin", "https://chat.openai.com")
header.Set("Referer", "https://chat.openai.com/")
// header.Del("Cookie")
header.Del("Accept-Encoding")
if accessToken != "" {
newreq.Header.Set("Authorization", "Bearer "+accessToken)
header.Set("Authorization", "Bearer "+accessToken)
}
utility.HeaderModify(&r.Request.Header)

// g.Dump(newreq.URL)
cdnhost := config.CDNHOST(ctx)
Expand Down Expand Up @@ -161,7 +240,7 @@ func ProxyAll(r *ghttp.Request) {
return nil
}

proxy.ServeHTTP(r.Response.Writer.RawWriter(), newreq)
proxy.ServeHTTP(r.Response.RawWriter(), r.Request)

}

Expand Down
54 changes: 27 additions & 27 deletions backend-api/me.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package backendapi

import (
"chatgpt-mirror-server/config"
"net/http"

"github.com/gogf/gf/v2/encoding/gjson"
Expand All @@ -20,39 +19,40 @@ func Me(r *ghttp.Request) {
r.Response.WriteStatus(http.StatusUnauthorized)
return
}
if record.IsEmpty() {
g.Log().Error(ctx, "session is empty")
r.Response.WriteStatus(http.StatusUnauthorized)
return
}
AccessToken := ""
// 如果 record mode ==1
if record["mode"].Int() == 1 {
AccessToken = record["officialSession"].String()
} else {
officialSession := gjson.New(record["officialSession"].String())
AccessToken = officialSession.Get("accessToken").String()
// if record.IsEmpty() {
// g.Log().Error(ctx, "session is empty")
// r.Response.WriteStatus(http.StatusUnauthorized)
// return
// }
// AccessToken := ""
// // 如果 record mode ==1
// if record["mode"].Int() == 1 {
// AccessToken = record["officialSession"].String()
// } else {
// officialSession := gjson.New(record["officialSession"].String())
// AccessToken = officialSession.Get("accessToken").String()

}
// }
resStr, err := ProxyRequestGet("/backend-api/me", r)

UpStream := config.CHATPROXY(ctx)
// 请求后端接口
res, err := g.Client().SetHeaderMap(map[string]string{
"Authorization": "Bearer " + AccessToken,
"User-Agent": r.Header.Get("User-Agent"),
"authKey": config.AUTHKEY(ctx),
}).Get(ctx, UpStream+"/backend-api/me")
// UpStream := config.CHATPROXY(ctx)
// // 请求后端接口
// res, err := g.Client().SetHeaderMap(map[string]string{
// "Authorization": "Bearer " + AccessToken,
// "User-Agent": r.Header.Get("User-Agent"),
// "authKey": config.AUTHKEY(ctx),
// }).Get(ctx, UpStream+"/backend-api/me")
if err != nil {
r.Response.WriteStatus(http.StatusUnauthorized)
return
}
resStr := res.ReadAllString()
if res.StatusCode != http.StatusOK {
r.Response.Status = res.StatusCode
r.Response.Write(resStr)
// resStr := res.ReadAllString()
// if res.StatusCode != http.StatusOK {
// r.Response.Status = res.StatusCode
// r.Response.Write(resStr)

return
}
// return
// }
resJson := gjson.New(resStr)
resJson.Set("email", "[email protected]")
resJson.Set("name", record["user_username"].String())
Expand Down
5 changes: 4 additions & 1 deletion config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,10 @@ modules:
enable: 1

# 接入网关地址
CHATPROXY: "https://demo.xyhelper.cn"
CHATPROXY: "https://38.207.162.134:8443"
#CHATPROXY: "https://chat.openai.com"
#JA3_PROXY: "http://a:[email protected]:9988"
#JA3_PROXY: "http://a:[email protected]:9988"
#CHATPROXY: "http://host.docker.internal:7999"
#CHATPROXY: "https://chatgpt.ggss.club/gateway"
#ARKOSE_URL: "https://chatgpt.ggss.club/arkose/v2/"
Expand Down
27 changes: 27 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ package config

import (
"math/rand"
"net/url"
"time"

"github.com/gogf/gf/v2/container/garray"
"github.com/gogf/gf/v2/encoding/gjson"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/gclient"
"github.com/gogf/gf/v2/os/gctx"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/os/gview"
Expand All @@ -33,12 +35,14 @@ func USERTOKENLOCK(ctx g.Ctx) bool {
var (
DefaultModel = "text-davinci-002-render-sha"
FreeModels = garray.NewStrArray()
Ja3Proxy *url.URL // ja3代理
PlusModels = garray.NewStrArray()
ArkoseUrl = "https://tcr9i.closeai.biz/v2/"
BuildId = "LxJWDayKNMzRjO_Ay4ljN"
CacheBuildId = "LxJWDayKNMzRjO_Ay4ljN"
AssetPrefix = "https://oaistatic-cdn.closeai.biz"
PK40 = "35536E1E-65B4-4D96-9D97-6ADB7EFF8147"
ProxyClient *gclient.Client
PK35 = "3D86FBBA-9D22-402A-B512-3420086BA6CC"
envScriptTpl = `
<script>
Expand All @@ -52,6 +56,29 @@ var (

func init() {
ctx := gctx.GetInitCtx()
ProxyClient = g.Client().SetBrowserMode(true).SetHeaderMap(g.MapStrStr{
"Origin": "https://chat.openai.com",
"Referer": "https://chat.openai.com/",
"Host": "chat.openai.com",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3",
})
// 读取ja3代理
ja3Proxy := g.Cfg().MustGetWithEnv(ctx, "JA3_PROXY").String()
if ja3Proxy != "" {

u, err := url.Parse(ja3Proxy)
if err != nil {
panic(err)
}
Ja3Proxy = u
g.Log().Info(ctx, "JA3_PROXY:", Ja3Proxy.String())
ProxyClient = g.Client().Proxy(Ja3Proxy.String()).SetBrowserMode(true).SetHeaderMap(g.MapStrStr{
"Origin": "https://chat.openai.com",
"Referer": "https://chat.openai.com/",
"Host": "chat.openai.com",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3",
})
}

FreeModels.Append("text-davinci-002-render-sha")
FreeModels.Append("text-davinci-002-render-sha-mobile")
Expand Down
6 changes: 6 additions & 0 deletions public-api/proxypublic.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package publicapi

import (
"chatgpt-mirror-server/config"
"crypto/tls"
"net/http"
"net/http/httputil"
"net/url"
Expand All @@ -18,6 +19,11 @@ func ProxyPublic(r *ghttp.Request) {
g.Log().Error(ctx, e)
writer.WriteHeader(http.StatusBadGateway)
}
proxy.Transport = &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
}
newreq := r.Request.Clone(ctx)
newreq.URL.Host = u.Host
newreq.URL.Scheme = u.Scheme
Expand Down
1 change: 1 addition & 0 deletions resource/template/4DtybnrborNWeufDD8H-a/chat.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<!DOCTYPE html><html data-build="prod-e3f63e92a6423f531218665f67cc22d6fa99a672"><head>{{.envScript}}<meta charSet="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><link rel="apple-touch-icon" sizes="180x180" href="{{.assetPrefix}}/_next/static/media/apple-touch-icon.59f2e898.png" /><link rel="icon" type="image/png" sizes="32x32" href="{{.assetPrefix}}/_next/static/media/favicon-32x32.be48395e.png" /><link rel="icon" type="image/png" sizes="16x16" href="{{.assetPrefix}}/_next/static/media/favicon-16x16.9b8dbb69.png" /><link rel="preconnect" href="{{.assetPrefix}}" /><title>ChatGPT</title><meta name="title" content="ChatGPT: Get instant answers, find inspiration, learn something new" /><meta name="description" content="ChatGPT is a free-to-use AI system. Use it for engaging conversations, gain insights, automate tasks, and witness the future of AI, all in one place." /><meta name="keywords" content="ai chat,ai,chap gpt,chat gbt,chat gpt 3,chat gpt login,chat gpt website,chat gpt,chat gtp,chat openai,chat,chatai,chatbot gpt,chatg,chatgpt login,chatgpt,gpt chat,open ai,openai chat,openai chatgpt,openai" /><meta property="og:description" content="A conversational AI system that listens, learns, and challenges" /><meta name="robots" content="index, follow" /><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><meta property="og:title" content="ChatGPT" /><meta property="og:image" content="{{.assetPrefix}}/_next/static/media/chatgpt-share-og.49cbbffe.png" /><meta property="og:url" content="https://chat.openai.com" /><meta name="apple-itunes-app" content="app-id=6448311069" /><meta name="next-head-count" content="17" /><link rel="preload" href="{{.assetPrefix}}/_next/static/media/soehne-buch.13189857.woff2" as="font" crossorigin /><link rel="preload" href="{{.assetPrefix}}/_next/static/media/soehne-halbfett.977f1845.woff2" as="font" crossorigin /><link rel="preload" href="{{.assetPrefix}}/_next/static/media/soehne-kraftig.204b461c.woff2" as="font" crossorigin /><link data-next-font rel="preconnect" href="/" crossorigin="anonymous" /><link rel="preload" href="{{.assetPrefix}}/_next/static/css/69d45a43fffef6f2.css?dpl=e3f63e92a6423f531218665f67cc22d6fa99a672" as="style" crossorigin="anonymous" /><link rel="stylesheet" href="{{.assetPrefix}}/_next/static/css/69d45a43fffef6f2.css?dpl=e3f63e92a6423f531218665f67cc22d6fa99a672" crossorigin="anonymous" data-n-g /><noscript data-n-css></noscript><script defer crossorigin="anonymous" nomodule src="{{.assetPrefix}}/_next/static/chunks/polyfills-c67a75d1b6f99dc8.js?dpl=e3f63e92a6423f531218665f67cc22d6fa99a672"></script><script src="{{.assetPrefix}}/_next/static/chunks/webpack-428ae3a66ed57c56.js?dpl=e3f63e92a6423f531218665f67cc22d6fa99a672" defer crossorigin="anonymous"></script><script src="{{.assetPrefix}}/_next/static/chunks/framework-d69d7cd8328ac368.js?dpl=e3f63e92a6423f531218665f67cc22d6fa99a672" defer crossorigin="anonymous"></script><script src="{{.assetPrefix}}/_next/static/chunks/vendor-3adbe9ef4b7dd8f7.js?dpl=e3f63e92a6423f531218665f67cc22d6fa99a672" defer crossorigin="anonymous"></script><script src="{{.assetPrefix}}/_next/static/chunks/main-e7f84069c815d1a0.js?dpl=e3f63e92a6423f531218665f67cc22d6fa99a672" defer crossorigin="anonymous"></script><script src="{{.assetPrefix}}/_next/static/chunks/pages/_app-8dff4b8fba8c4d5d.js?dpl=e3f63e92a6423f531218665f67cc22d6fa99a672" defer crossorigin="anonymous"></script><script src="{{.assetPrefix}}/_next/static/chunks/pages/%5B%5B...default%5D%5D-afdd4e016ec92443.js?dpl=e3f63e92a6423f531218665f67cc22d6fa99a672" defer crossorigin="anonymous"></script><script src="{{.assetPrefix}}/_next/static/4DtybnrborNWeufDD8H-a/_buildManifest.js?dpl=e3f63e92a6423f531218665f67cc22d6fa99a672" defer crossorigin="anonymous"></script><script src="{{.assetPrefix}}/_next/static/4DtybnrborNWeufDD8H-a/_ssgManifest.js?dpl=e3f63e92a6423f531218665f67cc22d6fa99a672" defer crossorigin="anonymous"></script></head><body class="antialiased"><div id="__next"><script>!function(){try{var d=document.documentElement,c=d.classList;c.remove('light','dark');var e=localStorage.getItem('theme');if('system'===e||(!e&&true)){var t='(prefers-color-scheme: dark)',m=window.matchMedia(t);if(m.media!==t||m.matches){d.style.colorScheme = 'dark';c.add('dark')}else{d.style.colorScheme = 'light';c.add('light')}}else if(e){c.add(e|| '')}if(e==='light'||e==='dark')d.style.colorScheme=e}catch(e){}}()</script><div class="relative z-0 flex h-full w-full overflow-hidden"><div class="relative flex h-full max-w-full flex-1 flex-col overflow-hidden"><main class="relative h-full w-full flex-1 overflow-auto transition-width"></main></div></div><div class="absolute left-0 right-0 top-0 z-[2]"></div><audio class="fixed bottom-0 left-0 hidden h-0 w-0" autoplay crossorigin="anonymous"></audio></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{{.props}}</script><script></script></body></html>
1 change: 1 addition & 0 deletions resource/template/4DtybnrborNWeufDD8H-a/discovery.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<!DOCTYPE html><html data-build="prod-e3f63e92a6423f531218665f67cc22d6fa99a672"><head>{{.envScript}}<meta charSet="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><link rel="apple-touch-icon" sizes="180x180" href="{{.assetPrefix}}/_next/static/media/apple-touch-icon.59f2e898.png" /><link rel="icon" type="image/png" sizes="32x32" href="{{.assetPrefix}}/_next/static/media/favicon-32x32.be48395e.png" /><link rel="icon" type="image/png" sizes="16x16" href="{{.assetPrefix}}/_next/static/media/favicon-16x16.9b8dbb69.png" /><link rel="preconnect" href="{{.assetPrefix}}" /><title>ChatGPT</title><meta name="title" content="ChatGPT: Get instant answers, find inspiration, learn something new" /><meta name="description" content="ChatGPT is a free-to-use AI system. Use it for engaging conversations, gain insights, automate tasks, and witness the future of AI, all in one place." /><meta name="keywords" content="ai chat,ai,chap gpt,chat gbt,chat gpt 3,chat gpt login,chat gpt website,chat gpt,chat gtp,chat openai,chat,chatai,chatbot gpt,chatg,chatgpt login,chatgpt,gpt chat,open ai,openai chat,openai chatgpt,openai" /><meta property="og:description" content="A conversational AI system that listens, learns, and challenges" /><meta name="robots" content="index, follow" /><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><meta property="og:title" content="ChatGPT" /><meta property="og:image" content="{{.assetPrefix}}/_next/static/media/chatgpt-share-og.49cbbffe.png" /><meta property="og:url" content="https://chat.openai.com" /><meta name="apple-itunes-app" content="app-id=6448311069" /><meta name="next-head-count" content="17" /><link rel="preload" href="{{.assetPrefix}}/_next/static/media/soehne-buch.13189857.woff2" as="font" crossorigin /><link rel="preload" href="{{.assetPrefix}}/_next/static/media/soehne-halbfett.977f1845.woff2" as="font" crossorigin /><link rel="preload" href="{{.assetPrefix}}/_next/static/media/soehne-kraftig.204b461c.woff2" as="font" crossorigin /><link data-next-font rel="preconnect" href="/" crossorigin="anonymous" /><link rel="preload" href="{{.assetPrefix}}/_next/static/css/69d45a43fffef6f2.css?dpl=e3f63e92a6423f531218665f67cc22d6fa99a672" as="style" crossorigin="anonymous" /><link rel="stylesheet" href="{{.assetPrefix}}/_next/static/css/69d45a43fffef6f2.css?dpl=e3f63e92a6423f531218665f67cc22d6fa99a672" crossorigin="anonymous" data-n-g /><noscript data-n-css></noscript><script defer crossorigin="anonymous" nomodule src="{{.assetPrefix}}/_next/static/chunks/polyfills-c67a75d1b6f99dc8.js?dpl=e3f63e92a6423f531218665f67cc22d6fa99a672"></script><script src="{{.assetPrefix}}/_next/static/chunks/webpack-428ae3a66ed57c56.js?dpl=e3f63e92a6423f531218665f67cc22d6fa99a672" defer crossorigin="anonymous"></script><script src="{{.assetPrefix}}/_next/static/chunks/framework-d69d7cd8328ac368.js?dpl=e3f63e92a6423f531218665f67cc22d6fa99a672" defer crossorigin="anonymous"></script><script src="{{.assetPrefix}}/_next/static/chunks/vendor-3adbe9ef4b7dd8f7.js?dpl=e3f63e92a6423f531218665f67cc22d6fa99a672" defer crossorigin="anonymous"></script><script src="{{.assetPrefix}}/_next/static/chunks/main-e7f84069c815d1a0.js?dpl=e3f63e92a6423f531218665f67cc22d6fa99a672" defer crossorigin="anonymous"></script><script src="{{.assetPrefix}}/_next/static/chunks/pages/_app-8dff4b8fba8c4d5d.js?dpl=e3f63e92a6423f531218665f67cc22d6fa99a672" defer crossorigin="anonymous"></script><script src="{{.assetPrefix}}/_next/static/chunks/pages/gpts-2f1723e4bc885593.js?dpl=e3f63e92a6423f531218665f67cc22d6fa99a672" defer crossorigin="anonymous"></script><script src="{{.assetPrefix}}/_next/static/4DtybnrborNWeufDD8H-a/_buildManifest.js?dpl=e3f63e92a6423f531218665f67cc22d6fa99a672" defer crossorigin="anonymous"></script><script src="{{.assetPrefix}}/_next/static/4DtybnrborNWeufDD8H-a/_ssgManifest.js?dpl=e3f63e92a6423f531218665f67cc22d6fa99a672" defer crossorigin="anonymous"></script></head><body class="antialiased"><div id="__next"><script>!function(){try{var d=document.documentElement,c=d.classList;c.remove('light','dark');var e=localStorage.getItem('theme');if('system'===e||(!e&&true)){var t='(prefers-color-scheme: dark)',m=window.matchMedia(t);if(m.media!==t||m.matches){d.style.colorScheme = 'dark';c.add('dark')}else{d.style.colorScheme = 'light';c.add('light')}}else if(e){c.add(e|| '')}if(e==='light'||e==='dark')d.style.colorScheme=e}catch(e){}}()</script><div class="absolute left-0 right-0 top-0 z-[2]"></div><audio class="fixed bottom-0 left-0 hidden h-0 w-0" autoplay crossorigin="anonymous"></audio></div><script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">{{.props}}</script><script></script></body></html>
Loading

0 comments on commit d8633a8

Please sign in to comment.