2023-05-22-【研发】nestjs安全

text

前言
在后端服务中,我们总是会遇到一些不安全的情况,毕竟 web 本身也不是一点漏洞都没有,好在有一些便捷的插件拱我们使用。

helmet,通过设置 HTTP 响应标头来帮助保护 Express 应用程序;
express-rate-limit,用于限制对公共 API 和/或终结点(例如密码重置)的重复请求,防止暴力攻击;

安装依赖

1
pnpm i helmet express-rate-limit

main.ts 修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import { NestFactory } from "@nestjs/core";
import { AppModule } from "./app.module";
import helmet from "helmet";
import rateLimit from "express-rate-limit";

async function bootstrap() {
const app = await NestFactory.create(AppModule);

// 头信息安全处理
app.use(helmet());
// 限制请求频率
app.use(
rateLimit({
windowMs: 15 * 60 * 1000, // 15 分钟
max: 100, // 15分钟中最大 100 个请求
standardHeaders: "draft-7",
legacyHeaders: false
})
);


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

真实 ip 获取

由于 express-rate-limit 是通过 ip 判断唯一性,所以应确保 ip 的真实性

  1. nginx 配置
  • 排查访问链路所有转发地址,均需要对 nginx 配置进行修改,
  • 配置如下:
1
2
3
4
5
6
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://localhost:3000;

注:X-Forwarded-For 变量的值有$proxy_add_x_forwarded_for和$remote_addr,在只有一个代理服务器的转发的情况下,两者的效果貌似差不多,都可以真实的显示出客户端原始 ip。多台 nginx 转发时,$remote_addr为第一台nginx的ip,$proxy_add_x_forwarded_for 的值为 第 n 台 nginx 的 ip, …第一台 nginx 的 ip;$scheme 为当前协议 http 或 https

  1. nestjs 设置

创建 nestjs 服务需显示设置创建类型 NestExpressApplication,否则仅 x-forwarded-for 能获取真实 iP

1
2
3
4
5
6
7
8
9
10
import { NestExpressApplication } from "@nestjs/platform-express";

async function bootstrap() {
// const app = await NestFactory.create(AppModule);
const app: NestExpressApplication =
(await NestFactory.create) < NestExpressApplication > AppModule;
//此接口NestExpressApplication才有
app.set("trust proxy", true);
await app.listen(port);
}
  • @Request 与@Req 区别,理论上 Request 包含信息更全,Req 适用于 auth 认证头部信息获取
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Public()
@Get('getCode')
getCode(@Res() res, @Req() req) {
const captcha = svgCaptcha.create({
size: 4,
noise: 2,
color: true,
fontSize: 60,
inverse: false,
background: '#F5F7FA',
});
req.session.captcha = captcha.text;

const ip = req.ip;
const host = req.headers?.host;
const headerRealIP: string = req?.headers['x-real-ip'];
const XForwardedFor: string = req?.headers['x-forwarded-for'];
// this.logger.log('生产 验证码:' + req.session.captcha);
this.logger.log(`生产 验证码:1234; ${ip} - ${host}; - ${headerRealIP}; - ${XForwardedFor}`);
res.set('Content-Type', 'image/svg+xml');
res.send(captcha.data);
}

2023-05-22-【研发】nestjs安全
https://zhangyingxuan.github.io/2023-05-22-【研发】nestjs安全/
作者
blowsysun
许可协议