mirror of
https://github.com/fosrl/pangolin.git
synced 2026-02-26 11:13:37 +00:00
Compare commits
3 Commits
cache
...
1.15.4-s.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
978ac8f53c | ||
|
|
49a326cde7 | ||
|
|
63e208f4ec |
@@ -16,6 +16,11 @@ const internalPort = config.getRawConfig().server.internal_port;
|
|||||||
export function createInternalServer() {
|
export function createInternalServer() {
|
||||||
const internalServer = express();
|
const internalServer = express();
|
||||||
|
|
||||||
|
const trustProxy = config.getRawConfig().server.trust_proxy;
|
||||||
|
if (trustProxy) {
|
||||||
|
internalServer.set("trust proxy", trustProxy);
|
||||||
|
}
|
||||||
|
|
||||||
internalServer.use(helmet());
|
internalServer.use(helmet());
|
||||||
internalServer.use(cors());
|
internalServer.use(cors());
|
||||||
internalServer.use(stripDuplicateSesions);
|
internalServer.use(stripDuplicateSesions);
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { redisManager } from "@server/private/lib/redis";
|
|||||||
|
|
||||||
// Create local cache with maxKeys limit to prevent memory leaks
|
// Create local cache with maxKeys limit to prevent memory leaks
|
||||||
// With ~10k requests/day and 5min TTL, 10k keys should be more than sufficient
|
// With ~10k requests/day and 5min TTL, 10k keys should be more than sufficient
|
||||||
const localCache = new NodeCache({
|
export const localCache = new NodeCache({
|
||||||
stdTTL: 3600,
|
stdTTL: 3600,
|
||||||
checkperiod: 120,
|
checkperiod: 120,
|
||||||
maxKeys: 10000
|
maxKeys: 10000
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ import {
|
|||||||
enforceResourceSessionLength
|
enforceResourceSessionLength
|
||||||
} from "#dynamic/lib/checkOrgAccessPolicy";
|
} from "#dynamic/lib/checkOrgAccessPolicy";
|
||||||
import { logRequestAudit } from "./logRequestAudit";
|
import { logRequestAudit } from "./logRequestAudit";
|
||||||
import cache from "@server/lib/cache";
|
import { localCache } from "@server/lib/cache";
|
||||||
import { APP_VERSION } from "@server/lib/consts";
|
import { APP_VERSION } from "@server/lib/consts";
|
||||||
import { isSubscribed } from "#dynamic/lib/isSubscribed";
|
import { isSubscribed } from "#dynamic/lib/isSubscribed";
|
||||||
import { tierMatrix } from "@server/lib/billing/tierMatrix";
|
import { tierMatrix } from "@server/lib/billing/tierMatrix";
|
||||||
@@ -137,7 +137,7 @@ export async function verifyResourceSession(
|
|||||||
headerAuthExtendedCompatibility: ResourceHeaderAuthExtendedCompatibility | null;
|
headerAuthExtendedCompatibility: ResourceHeaderAuthExtendedCompatibility | null;
|
||||||
org: Org;
|
org: Org;
|
||||||
}
|
}
|
||||||
| undefined = await cache.get(resourceCacheKey);
|
| undefined = localCache.get(resourceCacheKey);
|
||||||
|
|
||||||
if (!resourceData) {
|
if (!resourceData) {
|
||||||
const result = await getResourceByDomain(cleanHost);
|
const result = await getResourceByDomain(cleanHost);
|
||||||
@@ -161,7 +161,7 @@ export async function verifyResourceSession(
|
|||||||
}
|
}
|
||||||
|
|
||||||
resourceData = result;
|
resourceData = result;
|
||||||
await cache.set(resourceCacheKey, resourceData, 5);
|
localCache.set(resourceCacheKey, resourceData, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@@ -405,7 +405,7 @@ export async function verifyResourceSession(
|
|||||||
// check for HTTP Basic Auth header
|
// check for HTTP Basic Auth header
|
||||||
const clientHeaderAuthKey = `headerAuth:${clientHeaderAuth}`;
|
const clientHeaderAuthKey = `headerAuth:${clientHeaderAuth}`;
|
||||||
if (headerAuth && clientHeaderAuth) {
|
if (headerAuth && clientHeaderAuth) {
|
||||||
if (await cache.get(clientHeaderAuthKey)) {
|
if (localCache.get(clientHeaderAuthKey)) {
|
||||||
logger.debug(
|
logger.debug(
|
||||||
"Resource allowed because header auth is valid (cached)"
|
"Resource allowed because header auth is valid (cached)"
|
||||||
);
|
);
|
||||||
@@ -428,7 +428,7 @@ export async function verifyResourceSession(
|
|||||||
headerAuth.headerAuthHash
|
headerAuth.headerAuthHash
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
await cache.set(clientHeaderAuthKey, clientHeaderAuth, 5);
|
localCache.set(clientHeaderAuthKey, clientHeaderAuth, 5);
|
||||||
logger.debug("Resource allowed because header auth is valid");
|
logger.debug("Resource allowed because header auth is valid");
|
||||||
|
|
||||||
logRequestAudit(
|
logRequestAudit(
|
||||||
@@ -520,7 +520,7 @@ export async function verifyResourceSession(
|
|||||||
|
|
||||||
if (resourceSessionToken) {
|
if (resourceSessionToken) {
|
||||||
const sessionCacheKey = `session:${resourceSessionToken}`;
|
const sessionCacheKey = `session:${resourceSessionToken}`;
|
||||||
let resourceSession: any = await cache.get(sessionCacheKey);
|
let resourceSession: any = localCache.get(sessionCacheKey);
|
||||||
|
|
||||||
if (!resourceSession) {
|
if (!resourceSession) {
|
||||||
const result = await validateResourceSessionToken(
|
const result = await validateResourceSessionToken(
|
||||||
@@ -529,7 +529,7 @@ export async function verifyResourceSession(
|
|||||||
);
|
);
|
||||||
|
|
||||||
resourceSession = result?.resourceSession;
|
resourceSession = result?.resourceSession;
|
||||||
await cache.set(sessionCacheKey, resourceSession, 5);
|
localCache.set(sessionCacheKey, resourceSession, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resourceSession?.isRequestToken) {
|
if (resourceSession?.isRequestToken) {
|
||||||
@@ -662,7 +662,7 @@ export async function verifyResourceSession(
|
|||||||
}:${resource.resourceId}`;
|
}:${resource.resourceId}`;
|
||||||
|
|
||||||
let allowedUserData: BasicUserData | null | undefined =
|
let allowedUserData: BasicUserData | null | undefined =
|
||||||
await cache.get(userAccessCacheKey);
|
localCache.get(userAccessCacheKey);
|
||||||
|
|
||||||
if (allowedUserData === undefined) {
|
if (allowedUserData === undefined) {
|
||||||
allowedUserData = await isUserAllowedToAccessResource(
|
allowedUserData = await isUserAllowedToAccessResource(
|
||||||
@@ -671,7 +671,7 @@ export async function verifyResourceSession(
|
|||||||
resourceData.org
|
resourceData.org
|
||||||
);
|
);
|
||||||
|
|
||||||
await cache.set(userAccessCacheKey, allowedUserData, 5);
|
localCache.set(userAccessCacheKey, allowedUserData, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@@ -974,11 +974,11 @@ async function checkRules(
|
|||||||
): Promise<"ACCEPT" | "DROP" | "PASS" | undefined> {
|
): Promise<"ACCEPT" | "DROP" | "PASS" | undefined> {
|
||||||
const ruleCacheKey = `rules:${resourceId}`;
|
const ruleCacheKey = `rules:${resourceId}`;
|
||||||
|
|
||||||
let rules: ResourceRule[] | undefined = await cache.get(ruleCacheKey);
|
let rules: ResourceRule[] | undefined = localCache.get(ruleCacheKey);
|
||||||
|
|
||||||
if (!rules) {
|
if (!rules) {
|
||||||
rules = await getResourceRules(resourceId);
|
rules = await getResourceRules(resourceId);
|
||||||
await cache.set(ruleCacheKey, rules, 5);
|
localCache.set(ruleCacheKey, rules, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rules.length === 0) {
|
if (rules.length === 0) {
|
||||||
@@ -1208,13 +1208,13 @@ async function isIpInAsn(
|
|||||||
async function getAsnFromIp(ip: string): Promise<number | undefined> {
|
async function getAsnFromIp(ip: string): Promise<number | undefined> {
|
||||||
const asnCacheKey = `asn:${ip}`;
|
const asnCacheKey = `asn:${ip}`;
|
||||||
|
|
||||||
let cachedAsn: number | undefined = await cache.get(asnCacheKey);
|
let cachedAsn: number | undefined = localCache.get(asnCacheKey);
|
||||||
|
|
||||||
if (!cachedAsn) {
|
if (!cachedAsn) {
|
||||||
cachedAsn = await getAsnForIp(ip); // do it locally
|
cachedAsn = await getAsnForIp(ip); // do it locally
|
||||||
// Cache for longer since IP ASN doesn't change frequently
|
// Cache for longer since IP ASN doesn't change frequently
|
||||||
if (cachedAsn) {
|
if (cachedAsn) {
|
||||||
await cache.set(asnCacheKey, cachedAsn, 300); // 5 minutes
|
localCache.set(asnCacheKey, cachedAsn, 300); // 5 minutes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1224,14 +1224,14 @@ async function getAsnFromIp(ip: string): Promise<number | undefined> {
|
|||||||
async function getCountryCodeFromIp(ip: string): Promise<string | undefined> {
|
async function getCountryCodeFromIp(ip: string): Promise<string | undefined> {
|
||||||
const geoIpCacheKey = `geoip:${ip}`;
|
const geoIpCacheKey = `geoip:${ip}`;
|
||||||
|
|
||||||
let cachedCountryCode: string | undefined = await cache.get(geoIpCacheKey);
|
let cachedCountryCode: string | undefined = localCache.get(geoIpCacheKey);
|
||||||
|
|
||||||
if (!cachedCountryCode) {
|
if (!cachedCountryCode) {
|
||||||
cachedCountryCode = await getCountryCodeForIp(ip); // do it locally
|
cachedCountryCode = await getCountryCodeForIp(ip); // do it locally
|
||||||
// Only cache successful lookups to avoid filling cache with undefined values
|
// Only cache successful lookups to avoid filling cache with undefined values
|
||||||
if (cachedCountryCode) {
|
if (cachedCountryCode) {
|
||||||
// Cache for longer since IP geolocation doesn't change frequently
|
// Cache for longer since IP geolocation doesn't change frequently
|
||||||
await cache.set(geoIpCacheKey, cachedCountryCode, 300); // 5 minutes
|
localCache.set(geoIpCacheKey, cachedCountryCode, 300); // 5 minutes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,31 +2,22 @@ import { headers } from "next/headers";
|
|||||||
|
|
||||||
export async function authCookieHeader() {
|
export async function authCookieHeader() {
|
||||||
const otherHeaders = await headers();
|
const otherHeaders = await headers();
|
||||||
const otherHeadersObject = Object.fromEntries(otherHeaders.entries());
|
const otherHeadersObject = Object.fromEntries(
|
||||||
|
Array.from(otherHeaders.entries()).map(([k, v]) => [k.toLowerCase(), v])
|
||||||
|
);
|
||||||
|
|
||||||
|
console.info(`Setting cookie... x-forwarded-for: ${otherHeadersObject["x-forwarded-for"]}`)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
headers: {
|
headers: {
|
||||||
cookie:
|
cookie: otherHeadersObject["cookie"],
|
||||||
otherHeadersObject["cookie"] || otherHeadersObject["Cookie"],
|
host: otherHeadersObject["host"],
|
||||||
host: otherHeadersObject["host"] || otherHeadersObject["Host"],
|
"user-agent": otherHeadersObject["user-agent"],
|
||||||
"user-agent":
|
"x-forwarded-for": otherHeadersObject["x-forwarded-for"],
|
||||||
otherHeadersObject["user-agent"] ||
|
"x-forwarded-host": otherHeadersObject["x-forwarded-host"],
|
||||||
otherHeadersObject["User-Agent"],
|
"x-forwarded-port": otherHeadersObject["x-forwarded-port"],
|
||||||
"x-forwarded-for":
|
"x-forwarded-proto": otherHeadersObject["x-forwarded-proto"],
|
||||||
otherHeadersObject["x-forwarded-for"] ||
|
"x-real-ip": otherHeadersObject["x-real-ip"]
|
||||||
otherHeadersObject["X-Forwarded-For"],
|
|
||||||
"x-forwarded-host":
|
|
||||||
otherHeadersObject["fx-forwarded-host"] ||
|
|
||||||
otherHeadersObject["Fx-Forwarded-Host"],
|
|
||||||
"x-forwarded-port":
|
|
||||||
otherHeadersObject["x-forwarded-port"] ||
|
|
||||||
otherHeadersObject["X-Forwarded-Port"],
|
|
||||||
"x-forwarded-proto":
|
|
||||||
otherHeadersObject["x-forwarded-proto"] ||
|
|
||||||
otherHeadersObject["X-Forwarded-Proto"],
|
|
||||||
"x-real-ip":
|
|
||||||
otherHeadersObject["x-real-ip"] ||
|
|
||||||
otherHeadersObject["X-Real-IP"]
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user