Implements more robust anti-zoomer functionality (khanon/oai-reverse-proxy!24)

This commit is contained in:
khanon 2023-06-14 04:05:51 +00:00
parent c0ac69df27
commit 43359779e7
6 changed files with 68 additions and 8 deletions

View File

@ -156,7 +156,7 @@ export const config: Config = {
undefined
),
queueMode: getEnvWithDefault("QUEUE_MODE", "fair"),
blockedOrigins: getEnvWithDefault("BLOCKED_ORIGINS", "janitorai"),
blockedOrigins: getEnvWithDefault("BLOCKED_ORIGINS", undefined),
blockMessage: getEnvWithDefault(
"BLOCK_MESSAGE",
"You must be over the age of majority in your country to use this service."

View File

@ -9,6 +9,7 @@ import { handleProxyError } from "./middleware/common";
import {
addKey,
addAnthropicPreamble,
blockZoomers,
createPreprocessorMiddleware,
finalizeBody,
languageFilter,
@ -71,6 +72,7 @@ const rewriteAnthropicRequest = (
const rewriterPipeline = [
addKey,
addAnthropicPreamble,
blockZoomers,
languageFilter,
limitOutputTokens,
finalizeBody,

View File

@ -2,7 +2,6 @@ import { Request, Response } from "express";
import httpProxy from "http-proxy";
import { ZodError } from "zod";
const OPENAI_CHAT_COMPLETION_ENDPOINT = "/v1/chat/completions";
const ANTHROPIC_COMPLETION_ENDPOINT = "/v1/complete";
@ -32,9 +31,14 @@ export function writeErrorResponse(
res.headersSent ||
res.getHeader("content-type") === "text/event-stream"
) {
const errorContent =
statusCode === 403
? JSON.stringify(errorPayload)
: JSON.stringify(errorPayload, null, 2);
const msg = buildFakeSseMessage(
`${errorSource} error (${statusCode})`,
JSON.stringify(errorPayload, null, 2),
errorContent,
req
);
res.write(msg);
@ -57,6 +61,7 @@ export const handleInternalError = (
) => {
try {
const isZod = err instanceof ZodError;
const isForbidden = err.name === "ForbiddenError";
if (isZod) {
writeErrorResponse(req, res, 400, {
error: {
@ -67,6 +72,17 @@ export const handleInternalError = (
message: err.message,
},
});
} else if (isForbidden) {
// Spoofs a vaguely threatening OpenAI error message. Only invoked by the
// block-zoomers rewriter to scare off tiktokers.
writeErrorResponse(req, res, 403, {
error: {
type: "organization_account_disabled",
code: "policy_violation",
param: null,
message: err.message,
},
});
} else {
writeErrorResponse(req, res, 500, {
error: {
@ -91,10 +107,14 @@ export function buildFakeSseMessage(
req: Request
) {
let fakeEvent;
const useBackticks = !type.includes("403");
const msgContent = useBackticks
? `\`\`\`\n[${type}: ${string}]\n\`\`\`\n`
: `[${type}: ${string}]`;
if (req.inboundApi === "anthropic") {
fakeEvent = {
completion: `\`\`\`\n[${type}: ${string}]\n\`\`\`\n`,
completion: msgContent,
stop_reason: type,
truncated: false, // I've never seen this be true
stop: null,
@ -109,7 +129,7 @@ export function buildFakeSseMessage(
model: req.body?.model,
choices: [
{
delta: { content: `\`\`\`\n[${type}: ${string}]\n\`\`\`\n` },
delta: { content: msgContent },
index: 0,
finish_reason: type,
},

View File

@ -0,0 +1,34 @@
import { isCompletionRequest } from "../common";
import { ProxyRequestMiddleware } from ".";
const DISALLOWED_ORIGIN_SUBSTRINGS = "janitorai.com,janitor.ai".split(",");
class ForbiddenError extends Error {
constructor(message: string) {
super(message);
this.name = "ForbiddenError";
}
}
/**
* Blocks requests from Janitor AI users with a fake, scary error message so I
* stop getting emails asking for tech support.
*/
export const blockZoomers: ProxyRequestMiddleware = (_proxyReq, req) => {
if (!isCompletionRequest(req)) {
return;
}
const origin = req.headers.origin || req.headers.referer;
if (origin && DISALLOWED_ORIGIN_SUBSTRINGS.some((s) => origin.includes(s))) {
// Venus-derivatives send a test prompt to check if the proxy is working.
// We don't want to block that just yet.
if (req.body.messages[0]?.content === "Just say TEST") {
return;
}
throw new ForbiddenError(
`This OpenAI account has been disabled due to fraud and potential CSAM violations. Your IP address, user agent, and request details have been logged and will be shared with the National Center for Missing and Exploited Children and local law enforcement's cybercrime division to assist in their investigation.`
);
}
};

View File

@ -10,6 +10,7 @@ export { transformOutboundPayload } from "./transform-outbound-payload";
// HPM middleware (runs on onProxyReq, cannot be async)
export { addKey } from "./add-key";
export { addAnthropicPreamble } from "./add-anthropic-preamble";
export { blockZoomers } from "./block-zoomers";
export { finalizeBody } from "./finalize-body";
export { languageFilter } from "./language-filter";
export { limitCompletions } from "./limit-completions";

View File

@ -9,6 +9,7 @@ import { ipLimiter } from "./rate-limit";
import { handleProxyError } from "./middleware/common";
import {
addKey,
blockZoomers,
createPreprocessorMiddleware,
finalizeBody,
languageFilter,
@ -28,15 +29,16 @@ function getModelsResponse() {
return modelsCache;
}
// https://platform.openai.com/docs/models/overview
const gptVariants = [
"gpt-4",
"gpt-4-0613",
"gpt-4-0314",
"gpt-4-0314", // EOL 2023-09-13
"gpt-4-32k",
"gpt-4-32k-0613",
"gpt-4-32k-0314",
"gpt-4-32k-0314", // EOL 2023-09-13
"gpt-3.5-turbo",
"gpt-3.5-turbo-0301",
"gpt-3.5-turbo-0301", // EOL 2023-09-13
"gpt-3.5-turbo-0613",
"gpt-3.5-turbo-16k",
"gpt-3.5-turbo-16k-0613",
@ -89,6 +91,7 @@ const rewriteRequest = (
) => {
const rewriterPipeline = [
addKey,
blockZoomers,
languageFilter,
limitOutputTokens,
limitCompletions,