From e960a23b0c69a5762eb27d776d33dac443058faf Mon Sep 17 00:00:00 2001 From: Arvin Xu Date: Fri, 20 Sep 2024 23:46:21 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20fix:=20try=20to=20implement=20be?= =?UTF-8?q?tter=20ssrf-protect=20(#4044)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 🐛 fix: try to implement better ssrf-protect * 🐛 fix: fix error * 💄 style: improve pwa --- package.json | 1 + src/app/api/proxy/route.ts | 34 ------------------------------- src/app/webapi/proxy/route.ts | 19 +++++++++++++++++ src/server/routers/lambda/user.ts | 2 +- src/services/_url.ts | 4 ++-- src/services/user/client.ts | 2 +- 6 files changed, 24 insertions(+), 38 deletions(-) delete mode 100644 src/app/api/proxy/route.ts create mode 100644 src/app/webapi/proxy/route.ts diff --git a/package.json b/package.json index 40bc24d58c82..83e944a9fdb6 100644 --- a/package.json +++ b/package.json @@ -203,6 +203,7 @@ "remark": "^14.0.3", "remark-gfm": "^3.0.1", "remark-html": "^15.0.2", + "request-filtering-agent": "^2.0.1", "resolve-accept-language": "^3.1.5", "rtl-detect": "^1.1.2", "semver": "^7.6.3", diff --git a/src/app/api/proxy/route.ts b/src/app/api/proxy/route.ts deleted file mode 100644 index 67277ac7989a..000000000000 --- a/src/app/api/proxy/route.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { isPrivate } from 'ip'; -import { NextResponse } from 'next/server'; -import dns from 'node:dns'; -import { promisify } from 'node:util'; - -const lookupAsync = promisify(dns.lookup); - -export const runtime = 'nodejs'; - -/** - * just for a proxy - */ -export const POST = async (req: Request) => { - const url = new URL(await req.text()); - let address; - - try { - const lookupResult = await lookupAsync(url.hostname); - address = lookupResult.address; - } catch (err) { - console.error(`${url.hostname} DNS parser error:`, err); - - return NextResponse.json({ error: 'DNS parser error' }, { status: 504 }); - } - - const isInternalHost = isPrivate(address); - - if (isInternalHost) - return NextResponse.json({ error: 'Not support internal host proxy' }, { status: 400 }); - - const res = await fetch(url.toString()); - - return new Response(res.body, { headers: res.headers }); -}; diff --git a/src/app/webapi/proxy/route.ts b/src/app/webapi/proxy/route.ts new file mode 100644 index 000000000000..da81e4ae8c2b --- /dev/null +++ b/src/app/webapi/proxy/route.ts @@ -0,0 +1,19 @@ +import { NextResponse } from 'next/server'; +import fetch from 'node-fetch'; +import { useAgent as ssrfAgent } from 'request-filtering-agent'; + +/** + * just for a proxy + */ +export const POST = async (req: Request) => { + const url = await req.text(); + + try { + const res = await fetch(url, { agent: ssrfAgent(url) }); + + return new Response(await res.arrayBuffer(), { headers: { ...res.headers } }); + } catch (err) { + console.error(err); // DNS lookup 127.0.0.1(family:4, host:127.0.0.1.nip.io) is not allowed. Because, It is private IP address. + return NextResponse.json({ error: 'Not support internal host proxy' }, { status: 400 }); + } +}; diff --git a/src/server/routers/lambda/user.ts b/src/server/routers/lambda/user.ts index 4e5796afccaa..9660a955e691 100644 --- a/src/server/routers/lambda/user.ts +++ b/src/server/routers/lambda/user.ts @@ -63,7 +63,7 @@ export const userRouter = router({ const sessionCount = await sessionModel.count(); return { - canEnablePWAGuide: messageCount >= 2, + canEnablePWAGuide: messageCount >= 4, canEnableTrace: messageCount >= 4, // 有消息,或者创建过助手,则认为有 conversation hasConversation: messageCount > 0 || sessionCount > 1, diff --git a/src/services/_url.ts b/src/services/_url.ts index 1bbcee7672a7..5b110bef7062 100644 --- a/src/services/_url.ts +++ b/src/services/_url.ts @@ -1,4 +1,4 @@ -// TODO: 未来路由需要迁移到 trpc or /webapi +// TODO: 未来所有核心路由需要迁移到 trpc,部分不需要迁移的则走 webapi /* eslint-disable sort-keys-fix/sort-keys-fix */ import { transform } from 'lodash-es'; @@ -17,7 +17,7 @@ const mapWithBasePath = (apis: T): T => { }; export const API_ENDPOINTS = mapWithBasePath({ - proxy: '/api/proxy', + proxy: '/webapi/proxy', oauth: '/api/auth', // agent markets diff --git a/src/services/user/client.ts b/src/services/user/client.ts index f7ac9c7b11da..4554b16fa4be 100644 --- a/src/services/user/client.ts +++ b/src/services/user/client.ts @@ -23,7 +23,7 @@ export class ClientService implements IUserService { return { avatar: user.avatar, - canEnablePWAGuide: messageCount >= 2, + canEnablePWAGuide: messageCount >= 4, canEnableTrace: messageCount >= 4, hasConversation: messageCount > 0 || sessionCount > 0, isOnboard: true,