Skip to content

Commit 803cbc1

Browse files
authored
Merge pull request #2003 from cprussin/add-ip-whitelist
feat(staking): add IP whitelist
2 parents 6f02bbb + 2fb8c57 commit 803cbc1

File tree

4 files changed

+33
-9
lines changed

4 files changed

+33
-9
lines changed

apps/staking/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
"clsx": "^2.1.1",
4141
"dnum": "^2.13.1",
4242
"framer-motion": "^11.3.8",
43+
"ip-range-check": "^0.2.0",
4344
"next": "^14.2.5",
4445
"pino": "^9.3.2",
4546
"proxycheck-ts": "^0.0.11",

apps/staking/src/config/server.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ export const WALLETCONNECT_PROJECT_ID = demandInProduction(
5454
export const MAINNET_RPC = process.env.MAINNET_RPC;
5555
export const HERMES_URL = getOr("HERMES_URL", "https://hermes.pyth.network");
5656
export const BLOCKED_REGIONS = transformOr("BLOCKED_REGIONS", fromCsv, []);
57+
export const IP_ALLOWLIST = transformOr("IP_ALLOWLIST", fromCsv, []);
5758
export const GOVERNANCE_ONLY_REGIONS = transformOr(
5859
"GOVERNANCE_ONLY_REGIONS",
5960
fromCsv,

apps/staking/src/middleware.ts

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import ipRangeCheck from "ip-range-check";
12
import { type NextRequest, NextResponse } from "next/server";
23
import ProxyCheck from "proxycheck-ts";
34

@@ -10,6 +11,7 @@ import {
1011
BLOCKED_REGIONS,
1112
GOVERNANCE_ONLY_REGIONS,
1213
PROXYCHECK_API_KEY,
14+
IP_ALLOWLIST,
1315
} from "./config/server";
1416

1517
const GEO_BLOCKED_PATH = `/${GEO_BLOCKED_SEGMENT}`;
@@ -21,22 +23,32 @@ const proxyCheckClient = PROXYCHECK_API_KEY
2123
: undefined;
2224

2325
export const middleware = async (request: NextRequest) => {
24-
if (await isProxyBlocked(request)) {
25-
return rewrite(request, VPN_BLOCKED_PATH);
26-
} else if (isGovernanceOnlyRegion(request)) {
27-
return rewrite(request, GOVERNANCE_ONLY_PATH);
28-
} else if (isRegionBlocked(request)) {
29-
return rewrite(request, GEO_BLOCKED_PATH);
30-
} else if (isBlockedSegment(request)) {
31-
return rewrite(request, "/not-found");
26+
if (isIpAllowlisted(request)) {
27+
return isBlockedSegment(request)
28+
? rewrite(request, "/not-found")
29+
: undefined;
3230
} else {
33-
return;
31+
if (await isProxyBlocked(request)) {
32+
return rewrite(request, VPN_BLOCKED_PATH);
33+
} else if (isGovernanceOnlyRegion(request)) {
34+
return rewrite(request, GOVERNANCE_ONLY_PATH);
35+
} else if (isRegionBlocked(request)) {
36+
return rewrite(request, GEO_BLOCKED_PATH);
37+
} else if (isBlockedSegment(request)) {
38+
return rewrite(request, "/not-found");
39+
} else {
40+
return;
41+
}
3442
}
3543
};
3644

3745
const rewrite = (request: NextRequest, path: string) =>
3846
NextResponse.rewrite(new URL(path, request.url));
3947

48+
const isIpAllowlisted = ({ ip }: NextRequest) =>
49+
ip !== undefined &&
50+
IP_ALLOWLIST.some((allowedRange) => ipRangeCheck(ip, allowedRange));
51+
4052
const isGovernanceOnlyRegion = ({ geo }: NextRequest) =>
4153
geo?.country !== undefined &&
4254
GOVERNANCE_ONLY_REGIONS.includes(geo.country.toLowerCase());

pnpm-lock.yaml

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)