Używamy cookies, żeby zwiększyć Twoje doświadczenia na stronie
CodeWorlds

SSL/TLS i HTTPS Configuration - tarcza obronna Imperium

Legionisto cyberbezpieczenstwa! Architekt Vitruvius wie, ze kazda prowincja Imperium potrzebuje solidnych fortyfikacji. Tak jak mury obronne chroniły Rzym przed najeźdźcami, tak SSL/TLS i zabezpieczenia HTTP chronią nasze aplikacje NestJS przed atakami z sieci. Czas poznać sztukę budowania cyfrowych murów obronnych!

SSL (Secure Sockets Layer) i jego następca TLS (Transport Layer Security) to protokoły kryptograficzne zapewniające bezpieczną komunikację w sieci. HTTPS to HTTP działający przez warstwę SSL/TLS - szyfruje dane przesyłane między klientem a serwerem.

Generowanie certyfikatów SSL

Pierwszym krokiem w budowie murów obronnych jest pozyskanie certyfikatów. W środowisku deweloperskim możemy wygenerować certyfikaty samopodpisane, a na produkcji korzystamy z Let's Encrypt lub komercyjnych dostawców.

Certyfikaty deweloperskie (self-signed)

1// scripts/generate-dev-cert.ts
2import { execSync } from 'child_process';
3import * as fs from 'fs';
4import * as path from 'path';
5
6const certsDir = path.join(__dirname, '..', 'certs');
7
8// Tworzenie katalogu na certyfikaty
9if (!fs.existsSync(certsDir)) {
10  fs.mkdirSync(certsDir, { recursive: true });
11}
12
13// Generowanie klucza prywatnego i certyfikatu
14execSync(`openssl req -x509 -newkey rsa:4096 \
15  -keyout ${certsDir}/key.pem \
16  -out ${certsDir}/cert.pem \
17  -days 365 -nodes \
18  -subj "/C=PL/ST=Roma/L=Roma/O=Imperium/CN=localhost"`);
19
20console.log('Certyfikaty deweloperskie wygenerowane w katalogu certs/');

Konfiguracja HTTPS w NestJS

1// src/main.ts - uruchomienie serwera z HTTPS
2import { NestFactory } from '@nestjs/core';
3import { AppModule } from './app.module';
4import * as fs from 'fs';
5import * as path from 'path';
6
7async function bootstrap() {
8  const isProduction = process.env.NODE_ENV === 'production';
9
10  // Opcje HTTPS - certyfikaty SSL
11  const httpsOptions = isProduction
12    ? {
13        key: fs.readFileSync(process.env.SSL_KEY_PATH),
14        cert: fs.readFileSync(process.env.SSL_CERT_PATH),
15        ca: fs.readFileSync(process.env.SSL_CA_PATH), // Chain certyfikatow
16      }
17    : {
18        key: fs.readFileSync(path.join(__dirname, '..', 'certs', 'key.pem')),
19        cert: fs.readFileSync(path.join(__dirname, '..', 'certs', 'cert.pem')),
20      };
21
22  const app = await NestFactory.create(AppModule, { httpsOptions });
23
24  // Wymuszenie przekierowania HTTP -> HTTPS
25  if (isProduction) {
26    app.use((req, res, next) => {
27      if (req.headers['x-forwarded-proto'] !== 'https') {
28        return res.redirect(301, `https://${req.headers.host}${req.url}`);
29      }
30      next();
31    });
32  }
33
34  await app.listen(process.env.PORT || 3000);
35}
36bootstrap();

Helmet.js - nagłówki bezpieczeństwa HTTP

Helmet.js to jak hełm centuriona - chroni głowę (nagłówki HTTP) przed najczęstszymi atakami. Ustawia odpowiednie nagłówki bezpieczeństwa automatycznie.

1// src/main.ts - konfiguracja Helmet
2import helmet from 'helmet';
3
4async function bootstrap() {
5  const app = await NestFactory.create(AppModule);
6
7  // Podstawowa konfiguracja Helmet
8  app.use(helmet());
9
10  // Zaawansowana konfiguracja Helmet
11  app.use(helmet({
12    // Content-Security-Policy - kontroluje skad ladowane sa zasoby
13    contentSecurityPolicy: {
14      directives: {
15        defaultSrc: ["'self'"],
16        scriptSrc: ["'self'", "'unsafe-inline'"],
17        styleSrc: ["'self'", "'unsafe-inline'", 'https://fonts.googleapis.com'],
18        fontSrc: ["'self'", 'https://fonts.gstatic.com'],
19        imgSrc: ["'self'", 'data:', 'https:'],
20        connectSrc: ["'self'", process.env.API_URL],
21        frameSrc: ["'none'"],
22        objectSrc: ["'none'"],
23      },
24    },
25    // Strict-Transport-Security - wymusza HTTPS
26    hsts: {
27      maxAge: 31536000, // 1 rok
28      includeSubDomains: true,
29      preload: true,
30    },
31    // X-Frame-Options - zapobiega clickjacking
32    frameguard: { action: 'deny' },
33    // X-Content-Type-Options - zapobiega MIME sniffing
34    noSniff: true,
35    // Referrer-Policy
36    referrerPolicy: { policy: 'strict-origin-when-cross-origin' },
37  }));
38}

CORS dla produkcji

CORS (Cross-Origin Resource Sharing) kontroluje, które domeny mogą komunikować się z naszym API. To jak lista zaufanych ambasadorów Imperium.

1// src/main.ts - produkcyjna konfiguracja CORS
2import { CorsOptions } from '@nestjs/common/interfaces/external/cors-options.interface';
3
4const corsOptions: CorsOptions = {
5  origin: (origin, callback) => {
6    const allowedOrigins = process.env.CORS_ORIGINS?.split(',') || [];
7
8    // Pozwol na requesty bez origin (mobile, Postman)
9    if (!origin) return callback(null, true);
10
11    if (allowedOrigins.includes(origin)) {
12      callback(null, true);
13    } else {
14      callback(new Error(`Origin ${origin} nie jest dozwolony przez CORS`));
15    }
16  },
17  methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],
18  allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With'],
19  exposedHeaders: ['X-Total-Count', 'X-Page-Count'],
20  credentials: true,
21  maxAge: 86400, // Cache preflight na 24h
22};
23
24app.enableCors(corsOptions);

Rate Limiting z @nestjs/throttler

Rate limiting to jak strażnicy przy bramach miasta - kontrolują, ile osób może wejść w danym czasie, zapobiegając szturmowi (atakom DDoS).

1// src/app.module.ts - konfiguracja ThrottlerModule
2import { Module } from '@nestjs/common';
3import { ThrottlerModule, ThrottlerGuard } from '@nestjs/throttler';
4import { APP_GUARD } from '@nestjs/core';
5
6@Module({
7  imports: [
8    ThrottlerModule.forRoot([
9      {
10        name: 'short',  // Krotkoterminowy limit
11        ttl: 1000,      // 1 sekunda
12        limit: 3,       // Max 3 requesty na sekunde
13      },
14      {
15        name: 'medium', // Sredni limit
16        ttl: 10000,     // 10 sekund
17        limit: 20,      // Max 20 requestow na 10 sekund
18      },
19      {
20        name: 'long',   // Dlugoterminowy limit
21        ttl: 60000,     // 1 minuta
22        limit: 100,     // Max 100 requestow na minute
23      },
24    ]),
25  ],
26  providers: [
27    {
28      provide: APP_GUARD,
29      useClass: ThrottlerGuard,
30    },
31  ],
32})
33export class AppModule {}
34
35// Wylaczenie rate limitingu dla konkretnych endpointow
36import { SkipThrottle, Throttle } from '@nestjs/throttler';
37
38@Controller('legions')
39export class LegionsController {
40  @SkipThrottle()  // Bez limitu dla health check
41  @Get('health')
42  healthCheck() {
43    return { status: 'ok' };
44  }
45
46  @Throttle({ short: { ttl: 1000, limit: 1 } }) // Surowszy limit
47  @Post('login')
48  login() {
49    // Logowanie z ograniczeniem 1 req/s
50  }
51}

Ochrona CSRF

CSRF (Cross-Site Request Forgery) to atak, w którym złośliwa strona wykonuje żądania w imieniu zalogowanego użytkownika. Chronimy się przed nim za pomocą tokenów CSRF.

1// src/main.ts - ochrona CSRF z csurf
2import * as csurf from 'csurf';
3
4async function bootstrap() {
5  const app = await NestFactory.create(AppModule);
6
7  // CSRF protection (dla aplikacji z sesja/cookies)
8  app.use(csurf({
9    cookie: {
10      httpOnly: true,
11      secure: process.env.NODE_ENV === 'production',
12      sameSite: 'strict',
13    },
14  }));
15
16  // Middleware ustawiajacy CSRF token w odpowiedzi
17  app.use((req, res, next) => {
18    res.cookie('XSRF-TOKEN', req.csrfToken(), {
19      httpOnly: false, // Frontend musi moc odczytac
20      secure: process.env.NODE_ENV === 'production',
21      sameSite: 'strict',
22    });
23    next();
24  });
25}

Kompletna konfiguracja bezpieczeństwa

1// src/security/security.module.ts
2import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
3import { ThrottlerModule } from '@nestjs/throttler';
4import helmet from 'helmet';
5
6@Module({
7  imports: [
8    ThrottlerModule.forRoot([
9      { name: 'short', ttl: 1000, limit: 3 },
10      { name: 'long', ttl: 60000, limit: 100 },
11    ]),
12  ],
13})
14export class SecurityModule implements NestModule {
15  configure(consumer: MiddlewareConsumer) {
16    consumer
17      .apply(
18        helmet(),
19        helmet.contentSecurityPolicy({
20          directives: {
21            defaultSrc: ["'self'"],
22            scriptSrc: ["'self'"],
23          },
24        }),
25      )
26      .forRoutes('*');
27  }
28}

Bezpieczenstwo to nie jednorazowe zadanie, a ciagły proces - tak jak obrona murów Imperium wymagała stałej czujności strażników! Każda warstwa zabezpieczeń (SSL, Helmet, CORS, Rate Limiting, CSRF) dodaje kolejny mur obronny wokół Twojej aplikacji.

Przejdź do CodeWorlds