Skip to content

Commit 91d0623

Browse files
committed
Add ip-restriction middleware
1 parent e183618 commit 91d0623

File tree

8 files changed

+1398
-5
lines changed

8 files changed

+1398
-5
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@rabbit-company/web-monorepo",
3-
"version": "0.8.0",
3+
"version": "0.9.0",
44
"description": "High-performance web framework monorepo",
55
"private": true,
66
"type": "module",

packages/core/jsr.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@rabbit-company/web",
3-
"version": "0.8.0",
3+
"version": "0.9.0",
44
"license": "MIT",
55
"exports": "./src/index.ts",
66
"publish": {

packages/core/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@rabbit-company/web",
3-
"version": "0.8.0",
3+
"version": "0.9.0",
44
"description": "High-performance web framework",
55
"main": "./dist/index.js",
66
"types": "./dist/index.d.ts",

packages/middleware/README.md

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ console.log("Server running at http://localhost:3000");
8888

8989
- [**CORS**](#cors) - Cross-Origin Resource Sharing
9090
- [**Rate Limit**](#rate-limit) - Request rate limiting with multiple algorithms
91+
- [**IP Restriction**](#ip-restriction) - Limits access to resources based on the IP address
9192

9293
### 📊 Utils
9394

@@ -941,6 +942,149 @@ if (process.env.NODE_ENV === "development") {
941942
- Test your configuration with tools like `curl -H "X-Forwarded-For: fake"`
942943
- Consider using cloud provider presets for automatic secure configuration
943944
945+
### IP Restriction
946+
947+
Control access to your application by allowing or blocking specific IP addresses and CIDR ranges. Supports both whitelist and blacklist modes with IPv4/IPv6.
948+
949+
```js
950+
import { ipRestriction, ipRestrictionPresets, createDynamicIpRestriction } from "@rabbit-company/web-middleware/ip-restriction";
951+
952+
// Whitelist mode - only allow specific IPs
953+
app.use(ipRestriction({
954+
mode: "whitelist",
955+
ips: ["192.168.1.0/24", "10.0.0.1", "::1"],
956+
message: "Access restricted to internal network"
957+
}));
958+
959+
// Blacklist mode - block specific IPs
960+
app.use(ipRestriction({
961+
mode: "blacklist",
962+
ips: ["192.168.1.100", "10.0.0.0/16"],
963+
logDenied: true,
964+
logger: (message, ip) => console.log(`Blocked: ${ip}`)
965+
}));
966+
967+
// Use presets for common scenarios
968+
app.use(ipRestriction(ipRestrictionPresets.localhostOnly()));
969+
app.use(ipRestriction(ipRestrictionPresets.privateNetworkOnly()));
970+
971+
// Behind a proxy? Use with ipExtract
972+
app.use(ipExtract("cloudflare"));
973+
app.use(ipRestriction({
974+
mode: "whitelist",
975+
ips: ["203.0.113.0/24"]
976+
}));
977+
978+
// Protect admin routes
979+
app.use("/admin", ipRestriction({
980+
mode: "whitelist",
981+
ips: ["10.0.0.0/8"],
982+
message: (ip) => `Access denied for ${ip}. Admin panel is restricted.`,
983+
statusCode: 401
984+
}));
985+
986+
// Skip restriction for authenticated users
987+
app.use(ipRestriction({
988+
mode: "blacklist",
989+
ips: knownBadIps,
990+
skip: async (ctx) => {
991+
const user = ctx.get("user");
992+
return user?.role === "admin" || user?.verified === true;
993+
}
994+
}));
995+
996+
// Dynamic IP management
997+
const restriction = createDynamicIpRestriction({
998+
mode: "blacklist",
999+
ips: [],
1000+
logDenied: true
1001+
});
1002+
1003+
app.use(restriction.middleware);
1004+
1005+
// Ban IPs dynamically
1006+
app.post("/api/security/ban", async (ctx) => {
1007+
const { ip } = await ctx.req.json();
1008+
restriction.addIp(ip);
1009+
return ctx.json({ banned: ip });
1010+
});
1011+
1012+
// Unban IPs
1013+
app.post("/api/security/unban", async (ctx) => {
1014+
const { ip } = await ctx.req.json();
1015+
restriction.removeIp(ip);
1016+
return ctx.json({ unbanned: ip });
1017+
});
1018+
1019+
// Different restrictions for different environments
1020+
const ipConfig = process.env.NODE_ENV === "production"
1021+
? {
1022+
mode: "whitelist" as const,
1023+
ips: ["10.0.0.0/8", "172.16.0.0/12"] // Private networks only
1024+
}
1025+
: ipRestrictionPresets.localhostOnly(); // Dev: localhost only
1026+
1027+
app.use(ipRestriction(ipConfig));
1028+
1029+
// Debug headers for testing
1030+
app.use(ipRestriction({
1031+
mode: "whitelist",
1032+
ips: ["192.168.1.0/24"],
1033+
setHeader: true,
1034+
headerName: "X-IP-Status" // Response will include X-IP-Status: allowed/denied
1035+
}));
1036+
1037+
// Complex CIDR ranges with IPv6
1038+
app.use(ipRestriction({
1039+
mode: "whitelist",
1040+
ips: [
1041+
// IPv4 ranges
1042+
"10.0.0.0/8", // Private network class A
1043+
"172.16.0.0/12", // Private network class B
1044+
"192.168.0.0/16", // Private network class C
1045+
1046+
// IPv6 ranges
1047+
"::1/128", // Localhost
1048+
"fc00::/7", // Unique local addresses
1049+
"2001:db8::/32" // Documentation prefix
1050+
]
1051+
}));
1052+
```
1053+
1054+
#### Options:
1055+
1056+
- `mode`: Operation mode - "whitelist" (allow only listed) or "blacklist" (block listed)
1057+
- `ips`: Array of IP addresses or CIDR ranges (supports IPv4 and IPv6)
1058+
- `message`: Custom denial message - string or function(ip)
1059+
- `statusCode`: HTTP status when denied (default: 403)
1060+
- `skip`: Function to conditionally skip restrictions
1061+
- `logDenied`: Log denied requests (default: false)
1062+
- `logger`: Custom logging function
1063+
- `setHeader`: Add debug header with allow/deny status
1064+
- `headerName`: Custom header name (default: "X-IP-Restriction")
1065+
1066+
#### Presets:
1067+
1068+
- `localhostOnly()`: Allow only 127.0.0.1 and ::1
1069+
- `privateNetworkOnly()`: Allow RFC 1918 private networks
1070+
1071+
#### Features:
1072+
1073+
- **CIDR Support**: Use ranges like "192.168.1.0/24" or "2001:db8::/32"
1074+
- **IPv4/IPv6**: Full support for both protocols
1075+
- **Dynamic Management**: Add/remove IPs at runtime
1076+
- **Conditional Bypass**: Skip restrictions for certain users/conditions
1077+
- **Debug Headers**: Optional headers for testing restrictions
1078+
- **Custom Messages**: Dynamic error messages based on blocked IP
1079+
1080+
#### Security Notes:
1081+
1082+
- Always use with `ipExtract` middleware when behind proxies
1083+
- For direct connections, `ctx.clientIp` is used automatically
1084+
- Test CIDR ranges carefully to avoid blocking legitimate users
1085+
- Consider using whitelist mode for sensitive endpoints
1086+
- Log denied attempts to monitor potential attacks
1087+
9441088
## 📦 Dependencies
9451089
9461090
- `@rabbit-company/web` - Core web framework (peer dependency)

packages/middleware/jsr.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
{
22
"name": "@rabbit-company/web-middleware",
3-
"version": "0.8.0",
3+
"version": "0.9.0",
44
"license": "MIT",
55
"exports": {
66
"./basic-auth": "./src/basic-auth.ts",
77
"./bearer-auth": "./src/bearer-auth.ts",
8+
"./body-limit": "./src/body-limit.ts",
89
"./cache": "./src/cache.ts",
910
"./cors": "./src/cors.ts",
1011
"./ip-extract": "./src/ip-extract.ts",
12+
"./ip-restriction": "./src/ip-restriction.ts",
1113
"./logger": "./src/logger.ts",
1214
"./rate-limit": "./src/rate-limit.ts"
1315
},

packages/middleware/package.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@rabbit-company/web-middleware",
3-
"version": "0.8.0",
3+
"version": "0.9.0",
44
"description": "Official middleware collection for Rabbit Company Web Framework",
55
"type": "module",
66
"homepage": "https://github.com/Rabbit-Company/Web-JS",
@@ -33,6 +33,10 @@
3333
"types": "./dist/ip-extract.d.ts",
3434
"import": "./dist/ip-extract.js"
3535
},
36+
"./ip-restriction": {
37+
"types": "./dist/ip-restriction.d.ts",
38+
"import": "./dist/ip-restriction.js"
39+
},
3640
"./logger": {
3741
"types": "./dist/logger.d.ts",
3842
"import": "./dist/logger.js"
@@ -74,6 +78,7 @@
7478
"cache",
7579
"cors",
7680
"ip-extract",
81+
"ip-restriction",
7782
"logging",
7883
"rate-limit"
7984
],

0 commit comments

Comments
 (0)