chore: 使用固定 UA 、可配置默认用户 Cookie

This commit is contained in:
adams549659584 2023-05-16 15:43:28 +08:00
parent 62656b74f3
commit 8ca6c9dbe0
10 changed files with 106 additions and 35 deletions

2
.vscode/launch.json vendored
View File

@ -16,6 +16,8 @@
"Go_Proxy_BingAI_SOCKS_URL": "192.168.0.88:1070",
// "Go_Proxy_BingAI_SOCKS_USER": "xxx",
// "Go_Proxy_BingAI_SOCKS_PWD": "xxx",
// "Go_Proxy_BingAI_USER_TOKEN_1": "xxx",
// "Go_Proxy_BingAI_USER_TOKEN_2": "xxx"
}
}
]

View File

@ -100,6 +100,10 @@ Go_Proxy_BingAI_SOCKS_URL=192.168.0.88:1070
# Socks 账号、密码 可选
Go_Proxy_BingAI_SOCKS_USER=xxx
Go_Proxy_BingAI_SOCKS_PWD=xxx
# 默认用户 Cookie 设置,可选,固定前缀 Go_Proxy_BingAI_USER_TOKEN 可设置多个,未登录用户将随机使用
Go_Proxy_BingAI_USER_TOKEN_1=xxx
Go_Proxy_BingAI_USER_TOKEN_2=xxx
Go_Proxy_BingAI_USER_TOKEN_3=xxx ...
```
## 部署

View File

@ -6,12 +6,14 @@ import (
"fmt"
"io"
"log"
"math/rand"
"net/http"
"net/http/httputil"
"net/url"
"os"
"strconv"
"strings"
"time"
"github.com/andybalholm/brotli"
"golang.org/x/net/proxy"
@ -41,12 +43,28 @@ var (
"https://cn.bing.com",
"https://www.bing.com",
}
USER_TOKEN_COOKIE_NAME = "_U"
RAND_IP_COOKIE_NAME = "BingAI_Rand_IP"
PROXY_WEB_PREFIX_PATH = "/web/"
PROXY_WEB_PAGE_PATH = PROXY_WEB_PREFIX_PATH + "index.html"
USER_TOKEN_COOKIE_NAME = "_U"
RAND_IP_COOKIE_NAME = "BingAI_Rand_IP"
PROXY_WEB_PREFIX_PATH = "/web/"
PROXY_WEB_PAGE_PATH = PROXY_WEB_PREFIX_PATH + "index.html"
USER_TOKEN_ENV_NAME_PREFIX = "Go_Proxy_BingAI_USER_TOKEN"
USER_TOKEN_LIST []string
RAND_COOKIE_INDEX_NAME = "BingAI_Rand_CK"
)
func init() {
initUserToken()
}
func initUserToken() {
for _, env := range os.Environ() {
if strings.HasPrefix(env, USER_TOKEN_ENV_NAME_PREFIX) {
parts := strings.SplitN(env, "=", 2)
USER_TOKEN_LIST = append(USER_TOKEN_LIST, parts[1])
}
}
}
func NewSingleHostReverseProxy(target *url.URL) *httputil.ReverseProxy {
originalScheme := "http"
httpsSchemeName := "https"
@ -54,6 +72,7 @@ func NewSingleHostReverseProxy(target *url.URL) *httputil.ReverseProxy {
var originalPath string
var originalDomain string
var randIP string
var resCKRandIndex string
director := func(req *http.Request) {
if req.URL.Scheme == httpsSchemeName || req.Header.Get("X-Forwarded-Proto") == httpsSchemeName {
originalScheme = httpsSchemeName
@ -83,14 +102,23 @@ func NewSingleHostReverseProxy(target *url.URL) *httputil.ReverseProxy {
}
req.Header.Set("X-Forwarded-For", randIP)
// 未登录用户ua 包含 iPhone Mobile 居然秒创建会话id应该搞了手机优先策略 Android 不行
// 未登录用户
ckUserToken, _ := req.Cookie(USER_TOKEN_COOKIE_NAME)
if ckUserToken == nil || ckUserToken.Value == "" {
ua := req.UserAgent()
if !strings.Contains(ua, "iPhone") && !strings.Contains(ua, "Mobile") {
req.Header.Set("User-Agent", "iPhone Mobile "+ua)
randCKIndex, randCkVal := getRandCookie(req)
if randCkVal != "" {
resCKRandIndex = strconv.Itoa(randCKIndex)
req.AddCookie(&http.Cookie{
Name: USER_TOKEN_COOKIE_NAME,
Value: randCkVal,
})
}
// ua := req.UserAgent()
// if !strings.Contains(ua, "iPhone") || !strings.Contains(ua, "Mobile") {
// req.Header.Set("User-Agent", "iPhone Mobile "+ua)
// }
}
req.Header.Set("User-Agent", "Mozilla/5.0 (iPhone; CPU iPhone OS 15_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.7 Mobile/15E148 Safari/605.1.15 BingSapphire/1.0.410427012")
for hKey, _ := range req.Header {
if _, ok := KEEP_REQ_HEADER_MAP[hKey]; !ok {
@ -135,6 +163,16 @@ func NewSingleHostReverseProxy(target *url.URL) *httputil.ReverseProxy {
}
res.Header.Set("Set-Cookie", ckRandIP.String())
// 设置服务器 cookie 对应索引
if resCKRandIndex != "" {
ckRandIndex := &http.Cookie{
Name: RAND_COOKIE_INDEX_NAME,
Value: resCKRandIndex,
Path: "/",
}
res.Header.Set("Set-Cookie", ckRandIndex.String())
}
// 删除 CSP
res.Header.Del("Content-Security-Policy-Report-Only")
res.Header.Del("Report-To")
@ -202,6 +240,33 @@ func NewSingleHostReverseProxy(target *url.URL) *httputil.ReverseProxy {
return reverseProxy
}
// return cookie index and cookie
func getRandCookie(req *http.Request) (int, string) {
utLen := len(USER_TOKEN_LIST)
if utLen == 0 {
return 0, ""
}
if utLen == 1 {
return 0, USER_TOKEN_LIST[0]
}
ckRandIndex, _ := req.Cookie(RAND_COOKIE_INDEX_NAME)
if ckRandIndex != nil && ckRandIndex.Value != "" {
tmpIndex, err := strconv.Atoi(ckRandIndex.Value)
if err != nil {
log.Println("ckRandIndex err ", err)
return 0, ""
}
if tmpIndex < utLen {
return tmpIndex, USER_TOKEN_LIST[tmpIndex]
}
}
seed := time.Now().UnixNano()
rng := rand.New(rand.NewSource(seed))
randIndex := rng.Intn(len(USER_TOKEN_LIST))
return randIndex, USER_TOKEN_LIST[randIndex]
}
func replaceResBody(originalBody string, originalScheme string, originalHost string) string {
modifiedBodyStr := originalBody
originalDomain := fmt.Sprintf("%s://%s", originalScheme, originalHost)

View File

@ -1,6 +1,6 @@
{
"name": "go-proxy-bingai",
"version": "1.6.4",
"version": "1.6.5",
"private": true,
"scripts": {
"dev": "vite",

View File

@ -26,7 +26,7 @@ devDependencies:
version: 2.0.1
'@types/node':
specifier: ^18.16.8
version: 18.16.9
version: 18.16.10
'@vitejs/plugin-vue':
specifier: ^4.2.3
version: 4.2.3(vite@4.3.6)(vue@3.3.2)
@ -35,7 +35,7 @@ devDependencies:
version: 7.1.0(eslint@8.40.0)(prettier@2.8.8)
'@vue/eslint-config-typescript':
specifier: ^11.0.3
version: 11.0.3(eslint-plugin-vue@9.12.0)(eslint@8.40.0)(typescript@5.0.4)
version: 11.0.3(eslint-plugin-vue@9.13.0)(eslint@8.40.0)(typescript@5.0.4)
'@vue/tsconfig':
specifier: ^0.4.0
version: 0.4.0
@ -47,7 +47,7 @@ devDependencies:
version: 8.40.0
eslint-plugin-vue:
specifier: ^9.11.0
version: 9.12.0(eslint@8.40.0)
version: 9.13.0(eslint@8.40.0)
naive-ui:
specifier: ^2.34.3
version: 2.34.3(vue@3.3.2)
@ -71,7 +71,7 @@ devDependencies:
version: 5.0.4
vite:
specifier: ^4.3.5
version: 4.3.6(@types/node@18.16.9)
version: 4.3.6(@types/node@18.16.10)
vite-plugin-pwa:
specifier: ^0.14.7
version: 0.14.7(vite@4.3.6)(workbox-build@6.5.4)(workbox-window@6.5.4)
@ -1718,14 +1718,14 @@ packages:
resolution: {integrity: sha512-r22s9tAS7imvBt2lyHC9B8AGwWnXaYb1tY09oyLkXDs4vArpYJzw09nj8MLx5VfciBPGIb+ZwG0ssYnEPJxn/g==}
dev: true
/@types/node@18.16.9:
resolution: {integrity: sha512-IeB32oIV4oGArLrd7znD2rkHQ6EDCM+2Sr76dJnrHwv9OHBTTM6nuDLK9bmikXzPa0ZlWMWtRGo/Uw4mrzQedA==}
/@types/node@18.16.10:
resolution: {integrity: sha512-sMo3EngB6QkMBlB9rBe1lFdKSLqljyWPPWv6/FzSxh/IDlyVWSzE9RiF4eAuerQHybrWdqBgAGb03PM89qOasA==}
dev: true
/@types/resolve@1.17.1:
resolution: {integrity: sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==}
dependencies:
'@types/node': 18.16.9
'@types/node': 18.16.10
dev: true
/@types/semver@7.5.0:
@ -1873,7 +1873,7 @@ packages:
vite: ^4.0.0
vue: ^3.2.25
dependencies:
vite: 4.3.6(@types/node@18.16.9)
vite: 4.3.6(@types/node@18.16.10)
vue: 3.3.2
dev: true
@ -1972,7 +1972,7 @@ packages:
prettier: 2.8.8
dev: true
/@vue/eslint-config-typescript@11.0.3(eslint-plugin-vue@9.12.0)(eslint@8.40.0)(typescript@5.0.4):
/@vue/eslint-config-typescript@11.0.3(eslint-plugin-vue@9.13.0)(eslint@8.40.0)(typescript@5.0.4):
resolution: {integrity: sha512-dkt6W0PX6H/4Xuxg/BlFj5xHvksjpSlVjtkQCpaYJBIEuKj2hOVU7r+TIe+ysCwRYFz/lGqvklntRkCAibsbPw==}
engines: {node: ^14.17.0 || >=16.0.0}
peerDependencies:
@ -1986,7 +1986,7 @@ packages:
'@typescript-eslint/eslint-plugin': 5.59.6(@typescript-eslint/parser@5.59.6)(eslint@8.40.0)(typescript@5.0.4)
'@typescript-eslint/parser': 5.59.6(eslint@8.40.0)(typescript@5.0.4)
eslint: 8.40.0
eslint-plugin-vue: 9.12.0(eslint@8.40.0)
eslint-plugin-vue: 9.13.0(eslint@8.40.0)
typescript: 5.0.4
vue-eslint-parser: 9.3.0(eslint@8.40.0)
transitivePeerDependencies:
@ -2228,7 +2228,7 @@ packages:
hasBin: true
dependencies:
caniuse-lite: 1.0.30001487
electron-to-chromium: 1.4.395
electron-to-chromium: 1.4.396
node-releases: 2.0.10
update-browserslist-db: 1.0.11(browserslist@4.21.5)
dev: true
@ -2467,8 +2467,8 @@ packages:
jake: 10.8.6
dev: true
/electron-to-chromium@1.4.395:
resolution: {integrity: sha512-r8IgVPlJsCs7yezgmuBTaOMuu8lgU0mzg+wcLLo0xVy5s+rpuFTI9tEKhHVaMIPgeJPjxwTDHUZqoBEsNMDbCQ==}
/electron-to-chromium@1.4.396:
resolution: {integrity: sha512-pqKTdqp/c5vsrc0xUPYXTDBo9ixZuGY8es4ZOjjd6HD6bFYbu5QA09VoW3fkY4LF1T0zYk86lN6bZnNlBuOpdQ==}
dev: true
/error-ex@1.3.2:
@ -2606,8 +2606,8 @@ packages:
prettier-linter-helpers: 1.0.0
dev: true
/eslint-plugin-vue@9.12.0(eslint@8.40.0):
resolution: {integrity: sha512-xH8PgpDW2WwmFSmRfs/3iWogef1CJzQqX264I65zz77jDuxF2yLy7+GA2diUM8ZNATuSl1+UehMQkb5YEyau5w==}
/eslint-plugin-vue@9.13.0(eslint@8.40.0):
resolution: {integrity: sha512-aBz9A8WB4wmpnVv0pYUt86cmH9EkcwWzgEwecBxMoRNhQjTL5i4sqadnwShv/hOdr8Hbl8XANGV7dtX9UQIAyA==}
engines: {node: ^14.17.0 || >=16.0.0}
peerDependencies:
eslint: ^6.2.0 || ^7.0.0 || ^8.0.0
@ -3241,7 +3241,7 @@ packages:
resolution: {integrity: sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==}
engines: {node: '>= 10.13.0'}
dependencies:
'@types/node': 18.16.9
'@types/node': 18.16.10
merge-stream: 2.0.0
supports-color: 7.2.0
dev: true
@ -4505,14 +4505,14 @@ packages:
fast-glob: 3.2.12
pretty-bytes: 6.1.0
rollup: 3.21.7
vite: 4.3.6(@types/node@18.16.9)
vite: 4.3.6(@types/node@18.16.10)
workbox-build: 6.5.4
workbox-window: 6.5.4
transitivePeerDependencies:
- supports-color
dev: true
/vite@4.3.6(@types/node@18.16.9):
/vite@4.3.6(@types/node@18.16.10):
resolution: {integrity: sha512-cqIyLSbA6gornMS659AXTVKF7cvSHMdKmJJwQ9DXq3lwsT1uZSdktuBRlpHQ8VnOWx0QHtjDwxPpGtyo9Fh/Qg==}
engines: {node: ^14.18.0 || >=16.0.0}
hasBin: true
@ -4537,7 +4537,7 @@ packages:
terser:
optional: true
dependencies:
'@types/node': 18.16.9
'@types/node': 18.16.10
esbuild: 0.17.19
postcss: 8.4.23
rollup: 3.21.7

View File

@ -135,7 +135,7 @@ const clearCache = async () => {
<NInput size="large" v-model:value="userToken" type="text" placeholder="用户 Cookie ,仅需要 _U 的值" />
<template #action>
<NButton size="large" @click="isShowSetTokenModal = false">取消</NButton>
<NButton size="large" type="info" @click="saveUserToken">保存</NButton>
<NButton ghost size="large" type="info" @click="saveUserToken">保存</NButton>
</template>
</NModal>
<NModal v-model:show="isShowClearCacheModal" preset="dialog" :show-icon="false">
@ -144,7 +144,7 @@ const clearCache = async () => {
</template>
<template #action>
<NButton size="large" @click="isShowClearCacheModal = false">取消</NButton>
<NButton size="large" type="warning" @click="resetCache">确定</NButton>
<NButton ghost size="large" type="error" @click="resetCache">确定</NButton>
</template>
</NModal>
</template>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -37,7 +37,7 @@
<script src="/web/js/bing/chat/global.js"></script>
<script src="/web/js/bing/chat/amd.js"></script>
<script src="/web/js/bing/chat/config.js"></script>
<script type="module" crossorigin src="/web/assets/index-fb0759db.js"></script>
<script type="module" crossorigin src="/web/assets/index-2db47a63.js"></script>
<link rel="stylesheet" href="/web/assets/index-2128d00b.css">
<link rel="manifest" href="/web/manifest.webmanifest"><script id="vite-plugin-pwa:register-sw" src="/web/registerSW.js"></script></head>

View File

@ -1 +1 @@
if(!self.define){let e,s={};const i=(i,n)=>(i=new URL(i+".js",n).href,s[i]||new Promise((s=>{if("document"in self){const e=document.createElement("script");e.src=i,e.onload=s,document.head.appendChild(e)}else e=i,importScripts(i),s()})).then((()=>{let e=s[i];if(!e)throw new Error(`Module ${i} didnt register its module`);return e})));self.define=(n,a)=>{const c=e||("document"in self?document.currentScript.src:"")||location.href;if(s[c])return;let r={};const o=e=>i(e,c),f={module:{uri:c},exports:r,require:o};s[c]=Promise.all(n.map((e=>f[e]||o(e)))).then((e=>(a(...e),r)))}}define(["./workbox-118fddf1"],(function(e){"use strict";self.skipWaiting(),e.clientsClaim(),e.precacheAndRoute([{url:"assets/index-0e8bf8a6.css",revision:null},{url:"assets/index-2128d00b.css",revision:null},{url:"assets/index-aec03a9e.js",revision:null},{url:"assets/index-fb0759db.js",revision:null},{url:"assets/setting-c6ca7b14.svg",revision:null},{url:"compose.html",revision:"2c3f93033c3f4cef8136ff5a993a087b"},{url:"favicon.ico",revision:"1272c70e1b86b8956598a0349d2f193c"},{url:"img/compose.svg",revision:"4242b76bb8f4da0baf7a75edab0c6754"},{url:"img/logo.svg",revision:"1da58864f14c1a8c28f8587d6dcbc5d0"},{url:"img/pwa/logo-192.png",revision:"be40443731d9d4ead5e9b1f1a6070135"},{url:"img/pwa/logo-512.png",revision:"1217f1c90acb9f231e3135fa44af7efc"},{url:"index.html",revision:"8a8710d2fb269fa86faada35ba164118"},{url:"js/bing/chat/amd.js",revision:"8d773dc8f2e78b9d29e990aed7821774"},{url:"js/bing/chat/config.js",revision:"3bd7b84479a1f1dcc850abdd4d383a3c"},{url:"js/bing/chat/core.js",revision:"8c11521fd9f049b6ac91e5ad415c2db1"},{url:"js/bing/chat/global.js",revision:"2b5db148d13525a415ecf4e2c929ec43"},{url:"js/bing/chat/lib.js",revision:"1a0f8f43cc025b7b5995e885fed1a3e6"},{url:"registerSW.js",revision:"bf6c2f29aef95e09b1f72cf59f427a55"},{url:"./img/pwa/logo-192.png",revision:"be40443731d9d4ead5e9b1f1a6070135"},{url:"./img/pwa/logo-512.png",revision:"1217f1c90acb9f231e3135fa44af7efc"},{url:"manifest.webmanifest",revision:"ae4ef030ae5d2d4894669fd82aac028d"}],{}),e.cleanupOutdatedCaches(),e.registerRoute(new e.NavigationRoute(e.createHandlerBoundToURL("index.html"))),e.registerRoute(/(.*?)\.(js|css|ts)/,new e.CacheFirst({cacheName:"js-css-cache",plugins:[new e.ExpirationPlugin({maxEntries:100,maxAgeSeconds:604800}),new e.CacheableResponsePlugin({statuses:[0,200]})]}),"GET"),e.registerRoute(/(.*?)\.(png|jpe?g|svg|gif|bmp|psd|tiff|tga|eps|ico)/,new e.CacheFirst({cacheName:"image-cache",plugins:[new e.ExpirationPlugin({maxEntries:100,maxAgeSeconds:604800}),new e.CacheableResponsePlugin({statuses:[0,200]})]}),"GET")}));
if(!self.define){let e,s={};const i=(i,c)=>(i=new URL(i+".js",c).href,s[i]||new Promise((s=>{if("document"in self){const e=document.createElement("script");e.src=i,e.onload=s,document.head.appendChild(e)}else e=i,importScripts(i),s()})).then((()=>{let e=s[i];if(!e)throw new Error(`Module ${i} didnt register its module`);return e})));self.define=(c,n)=>{const a=e||("document"in self?document.currentScript.src:"")||location.href;if(s[a])return;let r={};const o=e=>i(e,a),f={module:{uri:a},exports:r,require:o};s[a]=Promise.all(c.map((e=>f[e]||o(e)))).then((e=>(n(...e),r)))}}define(["./workbox-118fddf1"],(function(e){"use strict";self.skipWaiting(),e.clientsClaim(),e.precacheAndRoute([{url:"assets/index-0e8bf8a6.css",revision:null},{url:"assets/index-2128d00b.css",revision:null},{url:"assets/index-2db47a63.js",revision:null},{url:"assets/index-c6f02c8b.js",revision:null},{url:"assets/setting-c6ca7b14.svg",revision:null},{url:"compose.html",revision:"2c3f93033c3f4cef8136ff5a993a087b"},{url:"favicon.ico",revision:"1272c70e1b86b8956598a0349d2f193c"},{url:"img/compose.svg",revision:"4242b76bb8f4da0baf7a75edab0c6754"},{url:"img/logo.svg",revision:"1da58864f14c1a8c28f8587d6dcbc5d0"},{url:"img/pwa/logo-192.png",revision:"be40443731d9d4ead5e9b1f1a6070135"},{url:"img/pwa/logo-512.png",revision:"1217f1c90acb9f231e3135fa44af7efc"},{url:"index.html",revision:"3446c007832ca09298c737ded8c8ac9c"},{url:"js/bing/chat/amd.js",revision:"8d773dc8f2e78b9d29e990aed7821774"},{url:"js/bing/chat/config.js",revision:"3bd7b84479a1f1dcc850abdd4d383a3c"},{url:"js/bing/chat/core.js",revision:"8c11521fd9f049b6ac91e5ad415c2db1"},{url:"js/bing/chat/global.js",revision:"2b5db148d13525a415ecf4e2c929ec43"},{url:"js/bing/chat/lib.js",revision:"1a0f8f43cc025b7b5995e885fed1a3e6"},{url:"registerSW.js",revision:"bf6c2f29aef95e09b1f72cf59f427a55"},{url:"./img/pwa/logo-192.png",revision:"be40443731d9d4ead5e9b1f1a6070135"},{url:"./img/pwa/logo-512.png",revision:"1217f1c90acb9f231e3135fa44af7efc"},{url:"manifest.webmanifest",revision:"ae4ef030ae5d2d4894669fd82aac028d"}],{}),e.cleanupOutdatedCaches(),e.registerRoute(new e.NavigationRoute(e.createHandlerBoundToURL("index.html"))),e.registerRoute(/(.*?)\.(js|css|ts)/,new e.CacheFirst({cacheName:"js-css-cache",plugins:[new e.ExpirationPlugin({maxEntries:100,maxAgeSeconds:604800}),new e.CacheableResponsePlugin({statuses:[0,200]})]}),"GET"),e.registerRoute(/(.*?)\.(png|jpe?g|svg|gif|bmp|psd|tiff|tga|eps|ico)/,new e.CacheFirst({cacheName:"image-cache",plugins:[new e.ExpirationPlugin({maxEntries:100,maxAgeSeconds:604800}),new e.CacheableResponsePlugin({statuses:[0,200]})]}),"GET")}));