How to Block Bot Traffic in NestJS With No Extra Infra

NestJS guards, interceptors, and global middleware all give you bot-blocking hooks. Here's the cleanest pattern for each.

May 9, 2026·6 min read

How to Block Bot Traffic in NestJS With No Extra Infra

NestJS gives you several places to add bot blocking. The cleanest is global middleware — it runs before guards, before interceptors, and before any handler logic. Here's the production setup.

For broader context see the SecureNow Firewall page.

The simplest setup: SecureNow preload

npm install securenow

# Update your start script:
node -r securenow/firewall-only dist/main.js

This sits below NestJS at the HTTP server level. Bad IPs get blocked before NestJS routes the request. A known-bad IP feed refreshed hourly, plus your own blocklist. No NestJS-specific code.

For full SecureNow (firewall + tracing + AI investigation):

node -r securenow/register dist/main.js

The hand-rolled NestJS middleware

If you want middleware-level control inside NestJS:

// src/firewall.middleware.ts
import { Injectable, NestMiddleware, HttpException, HttpStatus } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';

const BLOCKED_IPS = new Set([
  '185.220.101.42',
]);

const BAD_UA = /sqlmap|nikto|acunetix|masscan|nmap|python-requests/i;
const GOOD_BOTS = /googlebot|bingbot|gptbot|claudebot|perplexitybot/i;

@Injectable()
export class FirewallMiddleware implements NestMiddleware {
  use(req: Request, res: Response, next: NextFunction) {
    const ip = (req.headers['x-forwarded-for'] as string)?.split(',')[0]?.trim()
      || req.socket.remoteAddress;
    const ua = req.headers['user-agent'] || '';

    if (GOOD_BOTS.test(ua)) return next();
    if (BLOCKED_IPS.has(ip || '')) throw new HttpException('Forbidden', HttpStatus.FORBIDDEN);
    if (BAD_UA.test(ua)) throw new HttpException('Forbidden', HttpStatus.FORBIDDEN);

    next();
  }
}

Wire it globally in your AppModule:

// src/app.module.ts
import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common';
import { FirewallMiddleware } from './firewall.middleware';

@Module({
  imports: [/* ... */],
  controllers: [/* ... */],
  providers: [/* ... */],
})
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer.apply(FirewallMiddleware).forRoutes('*');
  }
}

When to use which

ScenarioApproach
Production NestJS, want maintenance-freeSecureNow preload
Need custom logic + reuse across multiple appsNestJS middleware (above)
Need NestJS Guard semantics (per-route)Custom Guard
Only blocking specific routesApply middleware via forRoutes('login')

With Fastify adapter

If you've switched NestJS to Fastify:

// main.ts
import { NestFactory } from '@nestjs/core';
import { FastifyAdapter, NestFastifyApplication } from '@nestjs/platform-fastify';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create<NestFastifyApplication>(
    AppModule,
    new FastifyAdapter()
  );

  app.getHttpAdapter().getInstance().addHook('onRequest', async (req, reply) => {
    const ip = req.headers['x-forwarded-for']?.toString().split(',')[0]?.trim() || req.ip;
    if (BLOCKED_IPS.has(ip)) {
      reply.status(403).send('Forbidden');
    }
  });

  await app.listen(3000);
}
bootstrap();

Fastify hooks have different ergonomics but achieve the same effect.

Verifying it works

npx securenow firewall status

Or with curl against a known-bad UA:

curl -i https://yourapp.com/ -H "User-Agent: sqlmap/1.5.7"

Frequently Asked Questions

Should I use a Guard, Interceptor, or Middleware?

Middleware for IP blocking (runs first, before guards). Guards for authorization-style checks. Interceptors for response transformation. Bot blocking belongs in middleware.

Does NestJS run on Node runtime?

Always. NestJS apps run on Node, so the SecureNow preload (`-r securenow/firewall-only`) works without modification.

Can I use Express middleware in NestJS?

Yes — NestJS sits on top of Express by default (or Fastify). Express middleware works directly via `app.use()` in main.ts.

What about Fastify-mode NestJS?

If you've configured NestJS with the Fastify adapter, use Fastify hooks instead. The preload still works since both use Node HTTP servers.

Recommended reading

Block an IP, a Range or One Route Without a Deploy (Node.js)

Block one IP, a CIDR range, or a single route and method in a Node.js app within seconds, with no code change: setup, scoping, CLI, MCP, verification and undo.

Oct 27
11 Signs Your AI-Built App Needs a Security Audit

Built your app with a coding agent? 11 warning signs it needs a security audit, each checkable in five minutes, and how to run the full audit yourself.

Oct 26
AI Security Audit Part 1: Set Up Your Agent to Audit Code

Part 1 of the AI security audit series: set up an AI coding agent to audit your app locally, connect SecureNow, and run your first threat-model pass.

Jul 24