@@ -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)
0 commit comments