{"id":17747,"library":"koa-ip","title":"Koa IP Filter Middleware","description":"The `koa-ip` package provides a robust IP filtering middleware specifically designed for Koa applications. It allows developers to manage network access by configuring either a `whitelist` to permit specific IP addresses or a `blacklist` to deny them. The package accommodates both literal IP strings and regular expressions for defining patterns, enabling flexible control over single IPs, IP ranges, or subnets. Currently stable at version 2.1.4, `koa-ip` exhibits a stable release cadence, typical for well-defined utility middleware, suggesting ongoing maintenance rather than rapid feature development. Its key differentiators include a minimalist API, seamless integration into the Koa middleware chain, and built-in TypeScript definitions, making it easy to adopt in modern Koa projects. By default, it returns a 403 Forbidden status for blacklisted IPs, a behavior that can be customized with an asynchronous handler function, offering fine-grained control over denied requests.","status":"active","version":"2.1.4","language":"javascript","source_language":"en","source_url":"https://github.com/nswbmw/koa-ip","tags":["javascript","koa","ip","whitelist","blacklist","typescript"],"install":[{"cmd":"npm install koa-ip","lang":"bash","label":"npm"},{"cmd":"yarn add koa-ip","lang":"bash","label":"yarn"},{"cmd":"pnpm add koa-ip","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Runtime dependency as `koa-ip` is a middleware designed for Koa applications.","package":"koa","optional":false}],"imports":[{"note":"The standard way to import the `koa-ip` middleware in CommonJS environments, which is the default module system for this package.","symbol":"ip","correct":"const ip = require('koa-ip');"},{"note":"TypeScript-specific CommonJS import syntax for `koa-ip`, especially in projects that compile to CommonJS or have specific `tsconfig.json` settings like `\"esModuleInterop\": false`.","wrong":"import { ip } from 'koa-ip';","symbol":"ip","correct":"import ip = require('koa-ip');"},{"note":"For projects configured to use ECMAScript Modules (ESM) with a bundler (like Webpack, Rollup) or Babel/TypeScript for transpilation (often requiring `\"esModuleInterop\": true` in `tsconfig.json`). Native Node.js ESM might require dynamic `import()` or specific configuration due to `koa-ip` being a CommonJS module by default.","wrong":"import { ip } from 'koa-ip';","symbol":"ip","correct":"import ip from 'koa-ip';"}],"quickstart":{"code":"import Koa from 'koa';\nimport ip from 'koa-ip';\n\nconst app = new Koa();\n\n// Middleware to simulate ctx.request.ip for testing\n// In a real application, ctx.request.ip is usually populated by Koa's proxy support or underlying Node.js\napp.use(async (ctx, next) => {\n  if (ctx.url === '/test-blacklist') {\n    ctx.request.ip = '127.0.0.1'; // Simulate a blacklisted IP\n  } else if (ctx.url === '/test-whitelist') {\n    ctx.request.ip = '192.168.0.50'; // Simulate a whitelisted IP\n  } else {\n    ctx.request.ip = '203.0.113.1'; // Default IP for other requests\n  }\n  await next();\n});\n\n// Configure koa-ip with both whitelist and a blacklist with a custom handler\napp.use(ip({\n  whitelist: ['192.168.0.*', /^10\\.0\\.\\d{1,3}\\.\\d{1,3}$/], // Allow local subnet and 10.0.x.x\n  blacklist: ['127.0.0.1', '198.51.100.0/24'], // Deny localhost and a specific CIDR range\n  handler: async (ctx) => {\n    ctx.status = 403;\n    ctx.body = 'Access Denied: Your IP (' + ctx.request.ip + ') is not permitted.';\n  }\n}));\n\n// This middleware will only be reached if the IP is not blacklisted and matches whitelist (if whitelist is active)\napp.use(async (ctx) => {\n  ctx.status = 200;\n  ctx.body = 'Welcome, your IP (' + ctx.request.ip + ') is allowed!';\n});\n\nconst PORT = process.env.PORT || 3000;\napp.listen(PORT, () => {\n  console.log(`Server running on http://localhost:${PORT}`);\n  console.log('Try visiting these URLs:');\n  console.log(`- http://localhost:${PORT}/test-whitelist (should show welcome)`);\n  console.log(`- http://localhost:${PORT}/test-blacklist (should show access denied)`);\n  console.log(`- http://localhost:${PORT}/ (should show welcome if default IP is not blacklisted)`);\n});","lang":"typescript","description":"This example demonstrates how to set up `koa-ip` middleware with both whitelist and blacklist configurations, including a custom handler for blacklisted IPs. It also includes a simulated IP setter for easy local testing of different scenarios."},"warnings":[{"fix":"Ensure `app.use(ip(...))` is called before other route-handling or request-processing middlewares.","message":"The order of middleware in Koa is crucial. `koa-ip` should be placed early in the middleware chain to ensure IP filtering occurs before other request handlers or route-matching logic. If placed too late, an unpermitted request might still be processed.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Provide a custom `handler` function in the `koa-ip` options object: `{ blacklist: [...], handler: async (ctx, next) => { ctx.status = 401; ctx.body = 'Unauthorized'; } }`","message":"By default, if an IP matches an entry in the `blacklist` and no custom `handler` function is provided, `koa-ip` will automatically set `ctx.status = 403`. Developers expecting a different default response or behavior must explicitly define a `handler`.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"If your Koa app is behind a proxy, set `app.proxy = true;` during Koa application initialization to correctly parse client IPs from `X-Forwarded-For`.","message":"When `app.proxy` is enabled in Koa (e.g., when behind a load balancer or reverse proxy), `ctx.request.ip` will use the `X-Forwarded-For` header. Ensure `app.proxy = true` is set if relying on forwarded headers, otherwise, `koa-ip` might filter based on the proxy's IP rather than the client's actual IP.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Thoroughly test all IP patterns (whitelist and blacklist) to confirm they match intended IP ranges. Use online regex testers for complex regular expressions. Refer to `koa-ip` documentation for supported wildcard syntax and CIDR interpretation.","message":"IP patterns using regular expressions or wildcards (`*`) require careful construction. Incorrect patterns can inadvertently block legitimate users or fail to block malicious ones. For CIDR notation (e.g., '192.168.1.0/24'), ensure the library correctly interprets it or convert to appropriate regex if needed (though `koa-ip` supports CIDR directly).","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-23T00:00:00.000Z","next_check":"2026-07-22T00:00:00.000Z","problems":[{"fix":"Ensure you have `const Koa = require('koa');` (or `import Koa from 'koa';`) and `const app = new Koa();` at the start of your application file.","cause":"The Koa application instance (`app`) has not been correctly initialized or is not an instance of Koa.","error":"TypeError: app.use is not a function"},{"fix":"Verify `koa-ip` is `app.use()`d early in your middleware stack. Double-check your `whitelist` and `blacklist` patterns. If behind a proxy, ensure `app.proxy = true;` is configured.","cause":"This typically happens if `koa-ip` is placed too late in the Koa middleware chain, the IP patterns are incorrect, or `ctx.request.ip` is not accurately reflecting the client's IP (e.g., due to proxy configuration issues).","error":"No IP filtering is occurring / Requests are not being blocked"},{"fix":"Either use the TypeScript-specific CommonJS import: `import ip = require('koa-ip');` or enable `\"esModuleInterop\": true` and `\"allowSyntheticDefaultImports\": true` in your `tsconfig.json`.","cause":"Attempting to use `import ip from 'koa-ip';` in a TypeScript project where `esModuleInterop` is `false` or `allowSyntheticDefaultImports` is `false` in `tsconfig.json`, and `koa-ip` is a CommonJS module.","error":"TypeScript Error: Module '\"koa-ip\"' has no default export."}],"ecosystem":"npm","meta_description":null,"install_score":null,"install_tag":null,"quickstart_score":null,"quickstart_tag":null}