Skip to content

Commit

Permalink
feat: add geoip based request blocking
Browse files Browse the repository at this point in the history
  • Loading branch information
techsavvyash committed Jan 4, 2024
1 parent 49f854d commit 1237bc7
Show file tree
Hide file tree
Showing 4 changed files with 814 additions and 16 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"@fastify/helmet": "8.0.0",
"@fastify/multipart": "6.0.0",
"@fastify/static": "5.0.0",
"@nestjs/axios": "^3.0.1",
"@nestjs/cache-manager": "^2.1.0",
"@nestjs/common": "8.0.0",
"@nestjs/config": "1.1.6",
Expand Down
40 changes: 40 additions & 0 deletions src/interceptors/geoip.interceptor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { Injectable, NestInterceptor, ExecutionContext, CallHandler, Logger, HttpStatus, InternalServerErrorException, HttpException } from '@nestjs/common';
import { Observable } from 'rxjs';
import { HttpService } from '@nestjs/axios';

@Injectable()
export class GeoIPInterceptor implements NestInterceptor {
private logger: Logger;
private readonly httpService: HttpService;

constructor() {
this.logger = new Logger('GeoIPInterceptor');
this.httpService = new HttpService();
}

async intercept(context: ExecutionContext, next: CallHandler): Promise<Observable<any>> {
const request = context.switchToHttp().getRequest();
const clientIp = request.headers['x-forwarded-for'] || request.ip; // Get client IP address

// Call the geolocation service to get the country from the IP
const { country, regionName } = await this.getLocation(clientIp);

if (country !== 'India') {
this.logger.verbose('Denying request from ip: ' + clientIp + ' country: ' + country)
throw new HttpException('Access Denied', HttpStatus.FORBIDDEN);
}

this.logger.verbose('Allowed request from ip: ' + clientIp + ' region: ' + regionName)
return next.handle();
}

private async getLocation(ip: any): Promise<any> {
try {
const resp = await this.httpService.axiosRef.get(`https://geoip.samagra.io/city/${ip}`)
return { country: resp.data.country, regionName: resp.data.regionName };
} catch (err) {
this.logger.error('Error occured while reading the geoip database', err);
throw new InternalServerErrorException('Error occured while reading the geoip database');
}
}
}
9 changes: 6 additions & 3 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import compression from "@fastify/compress";
import { join } from "path";
import { CustomLogger } from "./common/logger";
import { MonitoringService } from "./modules/monitoring/monitoring.service";
import { GeoIPInterceptor } from "./interceptors/geoip.interceptor";

async function bootstrap() {
const logger = new CustomLogger("Main");
Expand All @@ -21,7 +22,7 @@ async function bootstrap() {
AppModule,
new FastifyAdapter({ bodyLimit: 10048576 })
);

/** Register Prismaservice LifeCycle hooks */
const prismaService: PrismaService = app.get(PrismaService);
prismaService.enableShutdownHooks(app);
Expand All @@ -39,7 +40,9 @@ async function bootstrap() {
},
});

process.on('exit', (code)=>{
app.useGlobalInterceptors(new GeoIPInterceptor())

process.on('exit', (code) => {
console.log(`Process is exiting with code: ${code}`);
})

Expand All @@ -55,7 +58,7 @@ async function bootstrap() {
await monitoringService.onExit();
process.exit(0);
});

process.on('SIGTERM', async () => {
console.log('Received SIGTERM signal. Gracefully shutting down...');
const monitoringService = app.get<MonitoringService>(MonitoringService);
Expand Down
Loading

0 comments on commit 1237bc7

Please sign in to comment.