From b711cb8778c39ba0eb138a36c6b79684769c6461 Mon Sep 17 00:00:00 2001 From: Kevin Date: Sat, 4 May 2024 17:40:29 +1000 Subject: [PATCH 1/2] Temporarily disabling getip vpn check until a limiter is added --- src/util/vpnDetection.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/util/vpnDetection.ts b/src/util/vpnDetection.ts index b6f1ced75..eb713ea68 100644 --- a/src/util/vpnDetection.ts +++ b/src/util/vpnDetection.ts @@ -62,12 +62,18 @@ const isVPN = async (ip: string): Promise => { // Must pass both vpn checks const VpnCheck1 = await isVpnCheck1(ip); - const VpnCheck2 = await isVpnCheck2(ip); + + // TODO-kev: Temporarily commenting out until a limiter is added in + // const VpnCheck2 = await isVpnCheck2(ip); + // console.log( + // `VPN Detection Result: vpnapi.io=${VpnCheck1} check.getipintel.net=${VpnCheck2}`, + // ); console.log( - `VPN Detection Result: vpnapi.io=${VpnCheck1} check.getipintel.net=${VpnCheck2}`, + `VPN Detection Result: vpnapi.io=${VpnCheck1} check.getipintel.net=temporarily disabled`, ); - const result = VpnCheck1 || VpnCheck2; + // const result = VpnCheck1 || VpnCheck2; + const result = VpnCheck1; vpnCache.get(ip).setIsVpn(result); From 8b7de90f42c07ad359a4b6b8958bb29cc653b5b1 Mon Sep 17 00:00:00 2001 From: Kevin Date: Sat, 4 May 2024 18:12:23 +1000 Subject: [PATCH 2/2] Added limiter for VPN detection --- src/util/vpnDetection.ts | 43 +++++++++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/src/util/vpnDetection.ts b/src/util/vpnDetection.ts index eb713ea68..427d7778e 100644 --- a/src/util/vpnDetection.ts +++ b/src/util/vpnDetection.ts @@ -1,6 +1,9 @@ import { RequestHandler } from 'express'; -const VPN_TIMEOUT = 1000 * 60 * 60 * 12; // 12 hours +const VPN_TIMEOUT = 12 * 60 * 60 * 1000; // 12 hours +const VPN_LIMITER_VPNAPI = 500; +const VPN_LIMITER_GETIP = 1000; +const VPN_LIMITER_RESET_INTERVAL = 24 * 60 * 60 * 1000; // 24 hours let whitelistedUsernames: string[] = []; if (process.env.WHITELISTED_VPN_USERNAMES) { @@ -44,7 +47,7 @@ type IP = string; const vpnCache: Map = new Map(); -const isVPN = async (ip: string): Promise => { +const isVPN = async (ip: string, totalDailyCalls: number): Promise => { if (vpnCache.has(ip)) { // Clear the cache entry if it's timed out. if (vpnCache.get(ip).isTimedOut(new Date())) { @@ -61,19 +64,26 @@ const isVPN = async (ip: string): Promise => { console.log(`VPN Cache size: ${vpnCache.size}`); // Must pass both vpn checks - const VpnCheck1 = await isVpnCheck1(ip); + let VpnCheck1; + let VpnCheck2; + + if (totalDailyCalls < VPN_LIMITER_VPNAPI) { + VpnCheck1 = await isVpnCheck1(ip); + } + + if (totalDailyCalls < VPN_LIMITER_GETIP) { + VpnCheck2 = await isVpnCheck2(ip); + } + + const msg = 'Max daily calls reached'; - // TODO-kev: Temporarily commenting out until a limiter is added in - // const VpnCheck2 = await isVpnCheck2(ip); - // console.log( - // `VPN Detection Result: vpnapi.io=${VpnCheck1} check.getipintel.net=${VpnCheck2}`, - // ); console.log( - `VPN Detection Result: vpnapi.io=${VpnCheck1} check.getipintel.net=temporarily disabled`, + `VPN Detection Result: vpnapi.io="${ + VpnCheck1 ? VpnCheck1 : msg + }" check.getipintel.net="${VpnCheck2 ? VpnCheck2 : msg}"`, ); - // const result = VpnCheck1 || VpnCheck2; - const result = VpnCheck1; + const result = VpnCheck1 || VpnCheck2; vpnCache.get(ip).setIsVpn(result); @@ -115,6 +125,13 @@ const isVpnCheck2 = async (ip: string): Promise => { return result; }; +let disallowVPNsCallCount = 0; + +// Reset disallowVPNsCallCount every 24 hours +setInterval(() => { + disallowVPNsCallCount = 0; +}, VPN_LIMITER_RESET_INTERVAL); + export const disallowVPNs: RequestHandler = (req, res, next) => { if (process.env.ENV === 'local') { next(); @@ -126,7 +143,9 @@ export const disallowVPNs: RequestHandler = (req, res, next) => { return; } - isVPN(req.ip) + disallowVPNsCallCount++; + + isVPN(req.ip, disallowVPNsCallCount) .then((vpn) => { if (vpn) { console.log(`Blocked ${req.body.username} on ip ${req.ip}`);