HTTPS moduli


ULASHISH

HTTPS moduliga kirish

HTTPS moduli asosiy Node.js moduli bo‘lib, HTTPS protokolini amalga oshirishni ta’minlaydi, bu esa TLS/SSL orqali HTTP hisoblanadi.

Bu HTTP modulining xavfsiz versiyasi bo‘lib, mijozlar va serverlar o‘rtasida shifrlangan aloqani ta’minlaydi.

Nima uchun HTTPS dan foydalanish kerak?

HTTPS zamonaviy veb-ilovalar uchun juda muhim, chunki u:

  • Ma’lumotlarni shifrlaydi: parollar, kredit karta raqamlari va shaxsiy ma’lumotlar kabi maxfiy ma’lumotlarni tinglashdan himoya qiladi
  • Serverlarni autentifikatsiya qiladi: Mijozlar mo‘ljallangan server bilan aloqa o‘rnatayotganligini tasdiqlaydi
  • Ma’lumotlar yaxlitligini ta’minlaydi: O‘tkazish vaqtida ma’lumotlarning o‘zgarishi yoki buzilishining oldini oladi
  • Ishonchni mustahkamlaydi: Vizual ko‘rsatkichlar (masalan, qulf belgisi) foydalanuvchi ishonchini oshiradi
  • SEO-ni yaxshilaydi: Qidiruv tizimlari qidiruv natijalarida HTTPS veb-saytlariga ustunlik beradi
  • Zamonaviy funksiyalarni yoqadi: Ko‘pgina veb-APIlar (masalan, Geolocation, Service Workers) HTTPS talab qiladi

HTTPS qanday ishlaydi

  1. Mijoz serverga xavfsiz ulanishni boshlaydi
  2. Server mijozga SSL/TLS sertifikatini taqdim etadi
  3. Mijoz sertifikatni ishonchli sertifikatlash markazi (CA) orqali tekshiradi
  4. Shifrlangan seans assimetrik shifrlash yordamida o‘rnatiladi
  5. Haqiqiy ma’lumotlarni uzatish uchun simmetrik shifrlash qo‘llaniladi

Eslatma: Zamonaviy HTTPS SSL (Secure Sockets Layer) ning vorisi bo‘lgan TLS (Transport Layer Security) dan foydalanadi. Ko‘pincha atamalar bir-birining o‘rnida ishlatiladi, ammo SSL endi eskirgan hisoblanadi.

Muhim: 2023 yildan boshlab barcha asosiy brauzerlar yangi veb funksiyalar va API uchun HTTPSni talab qiladi. Ko‘pgina brauzerlar HTTPS bo‘lmagan saytlarni ham "Xavfsiz emas" deb belgilaydi.


HTTPS bilan ishlashni boshlash

Modulni import qilish

Node.js ilovangizda HTTPS modulidan foydalanish uchun uni CommonJS yoki ES modullari sintaksisi yordamida import qilishingiz mumkin:

CommonJS (Node.js’da standart)

// Using require()
const https = require('https');

ES modullari (Node.js 14+)

// Using import (requires "type": "module" in package.json)
import https from 'https';

HTTPS va HTTP API

HTTPS moduli HTTP moduli bilan bir xil interfeysga ega, asosiy farqi shundaki, u TLS/SSL yordamida ulanishlarni yaratadi.

Bu HTTP modulida mavjud bo‘lgan barcha usullar va hodisalar HTTPS modulida ham mavjudligini anglatadi.

Eslatma: Foydalanishdagi asosiy farq shundaki, HTTPS SSL/TLS sertifikatlarini talab qiladi, HTTP esa talab qilmaydi.


SSL/TLS sertifikatlari

HTTPS xavfsiz ulanishlarni o‘rnatish uchun SSL/TLS sertifikatlarini talab qiladi. Sertifikatlarning bir nechta turlari mavjud:

Sertifikat turlari

  • O‘z-o‘zidan imzolangan sertifikatlar: Ishlab chiqish va sinovdan o‘tkazish uchun (brauzerlar tomonidan ishonchli emas)
  • Domain Validated (DV): Asosiy tekshirish, faqat domen egaligini tasdiqlaydi
  • Tashkilot tasdiqlangan (OV): Tashkilot tafsilotlarini tasdiqlaydi
  • Kengaytirilgan tekshirish (EV): tekshirishning eng yuqori darajasi brauzerda kompaniya nomini ko‘rsatadi
  • Wildcard sertifikatlari: Domenning barcha subdomenlarini himoya qiladi
  • Ko‘p domenli (SAN) sertifikatlari: Bitta sertifikat bilan bir nechta domenlarni himoya qiladi

O‘z-o‘zidan imzolangan sertifikatlarni yaratish

Rivojlanish uchun siz OpenSSL yordamida o‘z-o‘zidan imzolangan sertifikatlarni yaratishingiz mumkin:

O‘z-o‘zidan imzolangan asosiy sertifikat

# Generate a private key (RSA 2048-bit)
openssl genrsa -out key.pem 2048

# Generate a self-signed certificate (valid for 365 days)
openssl req -new -x509 -key key.pem -out cert.pem -days 365 -nodes

Eslatma: Agar key.pem fayli mavjud bo‘lmasa, yuqoridagi buyruqdagi “-key” o‘rniga “ -newkey” variantini ishlatishingiz kerak.

Subject Alternative Names (SAN) bilan

# Create a config file (san.cnf)
cat > san.cnf << EOF
[req]
distinguished_name = req_distinguished_name
x509_extensions = v3_req
prompt = no
[req_distinguished_name]
C = US
ST = State
L = City
O = Organization
OU = Organizational Unit
CN = localhost
[v3_req]
keyUsage = keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
DNS.1 = localhost
IP.1 = 127.0.0.1
EOF

# Generate key and certificate with SAN
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout key.pem -out cert.pem -config san.cnf -extensions 'v3_req'

Xavfsizlik eslatmasi: O‘z-o‘zidan imzolangan sertifikatlar brauzerlarda xavfsizlik ogohlantirishlarini ishga tushiradi, chunki ular ishonchli sertifikat organi tomonidan imzolanmagan.

Ulardan faqat ishlab chiqish va sinov maqsadlarida foydalaning.

Ishonchli sertifikatlarni olish

Ishlab chiqarish uchun ishonchli sertifikat idoralaridan (CA) sertifikatlar oling:

  • Pulli CAlar: DigiCert, GlobalSign, Comodo va boshqalar.
  • Bepul CA: Keling, shifrlaymiz, ZeroSSL, Cloudflare

Let’s Encrypt - ishonchli sertifikatlarni taqdim etadigan mashhur bepul, avtomatlashtirilgan va ochiq sertifikat markazi.


HTTPS serverini yaratish

SSL/TLS sertifikatlaringiz tayyor bo‘lgach, Node.js da HTTPS serverini yaratishingiz mumkin.

HTTPS server API’si HTTP server API’siga juda o‘xshaydi, asosiy farqi SSL/TLS konfiguratsiyasidir.

Asosiy HTTPS serveriga misol

Bu yerda asosiy HTTPS serverini qanday yaratish mumkin:

Asosiy xavfsiz server

const https = require('https');
const fs = require('fs');
const path = require('path');

// Path to your SSL/TLS certificate and key
const sslOptions = {
  key: fs.readFileSync(path.join(__dirname, 'key.pem')),
  cert: fs.readFileSync(path.join(__dirname, 'cert.pem')),
  // Enable all security features
  minVersion: 'TLSv1.2',
  // Recommended security settings
  secureOptions: require('constants').SSL_OP_NO_SSLv3 |
              require('constants').SSL_OP_NO_TLSv1 |
              require('constants').SSL_OP_NO_TLSv1_1
};

// Create the HTTPS server
const server = https.createServer(sslOptions, (req, res) => {
  // Security headers
  res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
  res.setHeader('X-Content-Type-Options', 'nosniff');
  res.setHeader('X-Frame-Options', 'SAMEORIGIN');
  res.setHeader('X-XSS-Protection', '1; mode=block');
  res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin');

  // Handle different routes
  if (req.url === '/') {
    res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
    res.end('<h1>Welcome to the Secure Server</h1><p>Your connection is encrypted!</p>');
  } else if (req.url === '/api/status') {
    res.writeHead(200, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({ status: 'ok', time: new Date().toISOString() }));
  } else {
    res.writeHead(404, { 'Content-Type': 'text/plain' });
    res.end('404 Not Found');
  }
});

// Handle server errors
server.on('error', (error) => {
  console.error('Server error:', error);
});

// Start the server on port 3000 (HTTPS default is 443 but requires root)
const PORT = process.env.PORT || 3000;
server.listen(PORT, '0.0.0.0', () => {
  console.log(`Server running at https://localhost:${PORT}`);
  console.log('Press Ctrl+C to stop the server');
});

Eslatma: Unix-ga o‘xshash tizimlarda 1024 dan past portlar root huquqlarini talab qiladi. Production muhitida Node.js ni yuqori portda (masalan, 3000, 8080) ishga tushirish va SSL terminatsiyasi uchun Nginx yoki Apache kabi teskari proksi-serverdan foydalanish odatiy holdir.

Kengaytirilgan server konfiguratsiyasi

Ishlab chiqarish muhitlari uchun sizga kengaytirilgan SSL/TLS konfiguratsiyasi kerak bo‘lishi mumkin:

OCSP stapling va seansni davom ettirish bilan kengaytirilgan HTTPS serveri

const https = require('https');
const fs = require('fs');
const path = require('path');
const tls = require('tls');

// Path to your SSL/TLS files
const sslOptions = {
  // Certificate and key
  key: fs.readFileSync(path.join(__dirname, 'privkey.pem')),
  cert: fs.readFileSync(path.join(__dirname, 'cert.pem')),
  ca: [
    fs.readFileSync(path.join(__dirname, 'chain.pem'))
  ],

  // Recommended security settings
  minVersion: 'TLSv1.2',
  maxVersion: 'TLSv1.3',
  ciphers: [
    'TLS_AES_256_GCM_SHA384',
    'TLS_CHACHA20_POLY1305_SHA256',
    'TLS_AES_128_GCM_SHA256',
    'ECDHE-ECDSA-AES256-GCM-SHA384',
    'ECDHE-RSA-AES256-GCM-SHA384',
    'ECDHE-ECDSA-CHACHA20-POLY1305',
    'ECDHE-RSA-CHACHA20-POLY1305',
    'ECDHE-ECDSA-AES128-GCM-SHA256',
    'ECDHE-RSA-AES128-GCM-SHA256'
  ].join(':'),
  honorCipherOrder: true,
 
  // Enable OCSP Stapling
  requestCert: true,
  rejectUnauthorized: true,
 
  // Enable session resumption
  sessionTimeout: 300, // 5 minutes
  sessionIdContext: 'my-secure-app',
 
  // Enable HSTS preload
  hsts: {
    maxAge: 63072000, // 2 years in seconds
    includeSubDomains: true,
    preload: true
  },
 
  // Enable secure renegotiation
  secureOptions: require('constants').SSL_OP_LEGACY_SERVER_CONNECT |
    require('constants').SSL_OP_NO_SSLv3 |
    require('constants').SSL_OP_NO_TLSv1 |
    require('constants').SSL_OP_NO_TLSv1_1 |
    require('constants').SSL_OP_CIPHER_SERVER_PREFERENCE
};

// Create the HTTPS server
const server = https.createServer(sslOptions, (req, res) => {
  // Security headers
  const securityHeaders = {
    'Strict-Transport-Security': 'max-age=63072000; includeSubDomains; preload',
    'X-Content-Type-Options': 'nosniff',
    'X-Frame-Options': 'DENY',
    'X-XSS-Protection': '1; mode=block',
    'Content-Security-Policy': "default-src 'self'",
    'Referrer-Policy': 'strict-origin-when-cross-origin',
    'Permissions-Policy': 'geolocation=(), microphone=(), camera=()',
  };
 
  Object.entries(securityHeaders).forEach(([key, value]) => {
    res.setHeader(key, value);
  });

  // Handle requests
  if (req.url === '/') {
    res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
    res.end('<h1>Secure Node.js Server</h1><p>Your connection is secure!</p>');
  } else {
    res.writeHead(404, { 'Content-Type': 'text/plain' });
    res.end('404 Not Found');
  }
});

// Handle server errors
server.on('error', (error) => {
  console.error('Server error:', error);
});

// Handle uncaught exceptions
process.on('uncaughtException', (error) => {
  console.error('Uncaught exception:', error);
  // Perform graceful shutdown
  server.close(() => process.exit(1));
});

// Handle unhandled promise rejections
process.on('unhandledRejection', (reason, promise) => {
  console.error('Unhandled Rejection at:', promise, 'reason:', reason);
});

// Handle graceful shutdown
const gracefulShutdown = () => {
  console.log('Shutting down gracefully...');
  server.close(() => {
    console.log('Server closed');
    process.exit(0);
  });

  // Force close server after 10 seconds
  setTimeout(() => {
    console.error('Forcing shutdown...');
    process.exit(1);
  }, 10000);
};

// Listen for shutdown signals
process.on('SIGTERM', gracefulShutdown);
process.on('SIGINT', gracefulShutdown);

// Start the server
const PORT = process.env.PORT || 3000;
const HOST = process.env.HOST || '0.0.0.0';

server.listen(PORT, HOST, () => {
  const { address, port } = server.address();
  console.log(`Server running at https://${address}:${port}`);

  // Output server information
  console.log('Node.js version:', process.version);
  console.log('Environment:', process.env.NODE_ENV || 'development');
  console.log('PID:', process.pid);
});

Xavfsizlik bo‘yicha eng yaxshi amaliyotlar:

  • Xavfsizlik yangilanishlari uchun har doim Node.js ning so‘nggi barqaror versiyasidan foydalaning
  • `npm audit` va `npm update` yordamida qaramliklaringizni yangilab turing
  • Maxfiy sozlamalar uchun muhit o‘zgaruvchilaridan foydalaning (maxfiy ma’lumotlarni hech qachon versiyalarni boshqarish tizimiga commit qilmang)
  • Suiiste’molning oldini olish uchun stavkani cheklashni amalga oshiring
  • SSL/TLS sertifikatlaringizni muntazam ravishda aylantiring
  • Xavfsizlik zaifliklari uchun serveringizni kuzatib boring
  • Qo‘shimcha xavfsizlik xususiyatlari uchun ishlab chiqarishda Nginx yoki Apache kabi teskari proksi-serverdan foydalaning

HTTPS serveringiz sinovdan o‘tkazilmoqda

HTTPS serveringizni sinab ko‘rish uchun siz curl yoki veb-brauzerdan foydalanishingiz mumkin:

cURL dan foydalanish

# Skip certificate verification (for self-signed certs)
curl -k https://localhost:3000

# With certificate verification (for trusted certs)
curl --cacert /path/to/ca.pem https://yourdomain.com

Veb-brauzerdan foydalanish

  1. Veb-brauzeringizni oching va https://localhost:3000 ga o‘ting
  2. Agar o‘z-o‘zidan imzolangan sertifikatdan foydalansangiz, xavfsizlik ogohlantirishini qabul qilishingiz kerak bo‘ladi
  3. Development jarayonida o‘zingiz imzolagan sertifikatni ishonchli ildiz (root) sertifikatlaringizga qo‘shishingiz mumkin


HTTPS so‘rovlarini yuborish

HTTPS moduli boshqa serverlarga xavfsiz HTTP so‘rovlarini yuborish imkonini beradi.

Bu xavfsiz API va veb-xizmatlar bilan ishlash uchun zarur.

Asosiy GET so‘rovi

HTTPS so‘nggi nuqtasiga oddiy GET so‘rovini qanday qilish mumkin:

Asosiy HTTPS GET so‘rovi

const https = require('https');
const { URL } = require('url');

// Parse the target URL
const apiUrl = new URL('https://api.example.com/data');

// Request options
const options = {
  hostname: apiUrl.hostname,
  port: 443,
  path: apiUrl.pathname + apiUrl.search,
  method: 'GET',
  headers: {
    'User-Agent': 'MySecureApp/1.0',
    'Accept': 'application/json',
    'Cache-Control': 'no-cache'
  },
  // Security settings
  rejectUnauthorized: true, // Verify the server certificate (default: true)
  // Timeout in milliseconds
  timeout: 10000, // 10 seconds
};

console.log(`Making request to: https://${options.hostname}${options.path}`);

// Make the HTTPS request
const req = https.request(options, (res) => {
  const { statusCode, statusMessage, headers } = res;
  const contentType = headers['content-type'] || '';

  console.log(`Status: ${statusCode} ${statusMessage}`);
  console.log('Headers:', headers);

  // Handle redirects
  if (statusCode >= 300 && statusCode < 400 && headers.location) {
    console.log(`Redirecting to: ${headers.location}`);
    // In a real app, you'd handle the redirect
    res.resume(); // Discard the response body
    return;
  }

  // Check for successful response
  let error;
  if (statusCode !== 200) {
    error = new Error(`Request Failed.\nStatus Code: ${statusCode}`);
  } else if (!/^application\/json/.test(contentType)) {
    error = new Error(`Invalid content-type.\nExpected application/json but received ${contentType}`);
  }
  if (error) {
    console.error(error.message);
    res.resume(); // Consume response data to free up memory
    return;
  }

  // Process the response
  let rawData = '';
  res.setEncoding('utf8');

  // Collect chunks of data
  res.on('data', (chunk) => {
    rawData += chunk;
  });

  // Process the complete response
  res.on('end', () => {
    try {
      const parsedData = JSON.parse(rawData);
      console.log('Response data:', parsedData);
    } catch (e) {
      console.error('Error parsing JSON:', e.message);
    }
  });
});

// Handle request errors
req.on('error', (e) => {
  console.error(`Request error: ${e.message}`);
if (e.code === 'ECONNRESET') {
  console.error('Connection was reset by the server');
} else if (e.code === 'ETIMEDOUT') {
  console.error('Request timed out');
}
});

// Set a timeout for the entire request (including DNS lookup, TCP connect, etc.)
req.setTimeout(15000, () => {
  req.destroy(new Error('Request timeout after 15 seconds'));
});

// Handle socket errors (network-level errors)
req.on('socket', (socket) => {
  socket.on('error', (error) => {
    console.error('Socket error:', error.message);
    req.destroy(error);
  });
  // Set a timeout for the socket connection
  socket.setTimeout(5000, () => {
    req.destroy(new Error('Socket timeout after 5 seconds'));
  });
});

// End the request (required to send it)
req.end();

Oddiy so‘rovlar uchun https.get()’dan foydalanish

Oddiy GET so‘rovlari uchun siz ixchamroq https.get() usulidan foydalanishingiz mumkin. Bu HTTP usulini avtomatik ravishda GET ga o‘rnatadigan va siz uchun req.end() chaqiradigan qulay usul.

https.get() yordamida oddiy GET so‘rovi

const https = require('https');
const { URL } = require('url');

// Parse the URL
const url = new URL('https://jsonplaceholder.typicode.com/posts/1');

// Request options
const options = {
  hostname: url.hostname,
  path: url.pathname,
  method: 'GET',
  headers: {
    'Accept': 'application/json',
    'User-Agent': 'MySecureApp/1.0'
  }
};

console.log(`Fetching data from: ${url}`);

// Make the GET request
const req = https.get(options, (res) => {
  const { statusCode } = res;
  const contentType = res.headers['content-type'];

  if (statusCode !== 200) {
    console.error(`Request failed with status code: ${statusCode}`);
    res.resume(); // Consume response data to free up memory
    return;
  }

  if (!/^application\/json/.test(contentType)) {
    console.error(`Expected JSON but got ${contentType}`);
    res.resume();
    return;
  }

  let rawData = '';
  res.setEncoding('utf8');

  // Collect data chunks
  res.on('data', (chunk) => {
    rawData += chunk;
  });

  // Process complete response
  res.on('end', () => {
    try {
      const parsedData = JSON.parse(rawData);
      console.log('Received data:', parsedData);
    } catch (e) {
      console.error('Error parsing JSON:', e.message);
    }
  });
});

// Handle errors
req.on('error', (e) => {
  console.error(`Error: ${e.message}`);
});

// Set a timeout
req.setTimeout(10000, () => {
  console.error('Request timeout');
  req.destroy();
});

POST so‘rovlarini amalga oshirish

Serverga ma’lumotlarni yuborish uchun siz POST so‘rovidan foydalanishingiz mumkin.

JSON ma’lumotlari bilan xavfsiz POST so‘rovini qanday qilish mumkin:

JSON bilan HTTPS POST so‘rovi

const https = require('https');
const { URL } = require('url');

// Request data
const postData = JSON.stringify({
  title: 'foo',
  body: 'bar',
  userId: 1
});

// Parse the URL
const url = new URL('https://jsonplaceholder.typicode.com/posts');

// Request options
const options = {
  hostname: url.hostname,
  port: 443,
  path: url.pathname,
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Content-Length': Buffer.byteLength(postData),
    'User-Agent': 'MySecureApp/1.0',
    'Accept': 'application/json'
  },
  timeout: 10000 // 10 seconds
};

console.log('Sending POST request to:', url.toString());

// Create the request
const req = https.request(options, (res) => {
  console.log(`Status Code: ${res.statusCode}`);
  console.log('Headers:', res.headers);

  let responseData = '';
  res.setEncoding('utf8');

  // Collect response data
  res.on('data', (chunk) => {
    responseData += chunk;
  });

  // Process complete response
  res.on('end', () => {
    try {
      const parsedData = JSON.parse(responseData);
      console.log('Response:', parsedData);
    } catch (e) {
      console.error('Error parsing response:', e.message);
    }
  });
});

// Handle errors
req.on('error', (e) => {
  console.error(`Request error: ${e.message}`);
});

// Set a timeout
req.setTimeout(15000, () => {
  req.destroy(new Error('Request timeout after 15 seconds'));
});

// Write data to request body
req.write(postData);

// End the request
req.end();

HTTPS so‘rovlari bilan Promiselardan foydalanish

HTTPS so‘rovlarini boshqarish mumkin bo‘lishi uchun ularni Promise bilan o‘rashingiz mumkin:

Promise-ga asoslangan HTTPS so‘rovi

const https = require('https');
const { URL } = require('url');

/**
* Makes an HTTPS request and returns a Promise
* @param {Object} options - Request options
* @param {string|Buffer} [data] - Request body (for POST, PUT, etc.)
* @returns {Promise<Object>} - Resolves with response data
*/
function httpsRequest(options, data = null) {
  return new Promise((resolve, reject) => {
    const req = https.request(options, (res) => {
      let responseData = '';

      // Collect response data
      res.on('data', (chunk) => {
        responseData += chunk;
      });

      // Process complete response
      res.on('end', () => {
        try {
          const contentType = res.headers['content-type'] || '';
          const isJSON = /^application\/json/.test(contentType);
         
          const response = {
            statusCode: res.statusCode,
            headers: res.headers,
            data: isJSON ? JSON.parse(responseData) : responseData
          };
         
          if (res.statusCode >= 200 && res.statusCode < 300) {
            resolve(response);
          } else {
            const error = new Error(`Request failed with status code ${res.statusCode}`);
            error.response = response;
            reject(error);
          }
        } catch (e) {
          e.response = { data: responseData };
          reject(e);
        }
      });
    });

    // Handle errors
    req.on('error', (e) => {
      reject(e);
    });

    // Set timeout
    req.setTimeout(options.timeout || 10000, () => {
      req.destroy(new Error('Request timeout'));
    });

    // Write data if provided
    if (data) {
      req.write(data);
    }

    // End the request
    req.end();
  });
}

// Example usage
async function fetchData() {
  try {
    const url = new URL('https://jsonplaceholder.typicode.com/posts/1');
   
    const options = {
      hostname: url.hostname,
      path: url.pathname,
      method: 'GET',
      headers: {
        'Accept': 'application/json'
      },
      timeout: 5000
    };

    const response = await httpsRequest(options);
    console.log('Response:', response.data);
  } catch (error) {
    console.error('Error:', error.message);
    if (error.response) {
      console.error('Response data:', error.response.data);
    }
  }
}

// Run the example
fetchData();

HTTPS so‘rovlari bo‘yicha eng yaxshi amaliyotlar:

  • Kirish ma’lumotlarini so‘rovga yuborishdan oldin har doim tasdiqlang va tozalang
  • API kalitlari kabi nozik ma’lumotlar uchun muhit o‘zgaruvchilaridan foydalaning
  • Xatolarni to‘g‘ri qayta ishlash va kutish vaqtini amalga oshiring
  • Set appropriate headers (Content-Type, Accept, User-Agent)
  • Handle redirects appropriately (3xx status codes)
  • Vaqtinchalik nosozliklar uchun qayta urinish mantiqini amalga oshiring
  • Murakkab stsenariylar uchun axios yoki node-fetch kabi kutubxonadan foydalanishni o‘ylab ko‘ring

Express.js bilan HTTPS serveri

Asosiy HTTPS modulidan to‘g‘ridan-to‘g‘ri foydalanishingiz mumkin bo‘lsa-da, Node.js ilovalarining aksariyati HTTP/HTTPS so‘rovlarini bajarish uchun Express.js kabi veb-ramkadan foydalanadi.

Bu yerda HTTPS qo‘llab-quvvatlashi bilan Express ilovasini qanday sozlash kerak.

Asosiy Express.js HTTPS serveri

HTTPS bilan ifodalang

const express = require('express');
const https = require('https');
const fs = require('fs');
const path = require('path');
const helmet = require('helmet'); // Security middleware

// Create Express app
const app = express();

// Security middleware
app.use(helmet());

// Parse JSON and URL-encoded bodies
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

// Serve static files from 'public' directory
app.use(express.static(path.join(__dirname, 'public'), {
  dotfiles: 'ignore',
  etag: true,
  extensions: ['html', 'htm'],
  index: 'index.html',
  maxAge: '1d',
  redirect: true
}));

// Routes
app.get('/', (req, res) => {
  res.send('<h1>Welcome to Secure Express Server</h1>');
});

app.get('/api/status', (req, res) => {
  res.json({
    status: 'operational',
    timestamp: new Date().toISOString(),
    environment: process.env.NODE_ENV || 'development',
    nodeVersion: process.version
  });
});

// Error handling middleware
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).json({ error: 'Something went wrong!' });
});

// 404 handler
app.use((req, res) => {
  res.status(404).json({ error: 'Not Found' });
});

// SSL/TLS options
const sslOptions = {
  key: fs.readFileSync(path.join(__dirname, 'key.pem')),
  cert: fs.readFileSync(path.join(__dirname, 'cert.pem')),
  // Enable HTTP/2 if available
  allowHTTP1: true,
  // Recommended security options
  minVersion: 'TLSv1.2',
  ciphers: [
    'TLS_AES_256_GCM_SHA384',
    'TLS_CHACHA20_POLY1305_SHA256',
    'TLS_AES_128_GCM_SHA256',
    'ECDHE-RSA-AES128-GCM-SHA256',
    '!DSS',
    '!aNULL',
    '!eNULL',
    '!EXPORT',
    '!DES',
    '!RC4',
    '!3DES',
    '!MD5',
    '!PSK'
  ].join(':'),
  honorCipherOrder: true
};

// Create HTTPS server
const PORT = process.env.PORT || 3000;
const server = https.createServer(sslOptions, app);

// Handle unhandled promise rejections
process.on('unhandledRejection', (reason, promise) => {
  console.error('Unhandled Rejection at:', promise, 'reason:', reason);
});

// Handle uncaught exceptions
process.on('uncaughtException', (error) => {
  console.error('Uncaught Exception:', error);
  // Perform cleanup and exit if needed
  process.exit(1);
});

// Graceful shutdown
const gracefulShutdown = (signal) => {
  console.log(`\nReceived ${signal}. Shutting down gracefully...`);

  server.close(() => {
    console.log('HTTP server closed.');
    // Close database connections, etc.
    process.exit(0);
  });

  // Force close server after 10 seconds
  setTimeout(() => {
    console.error('Forcing shutdown...');
    process.exit(1);
  }, 10000);
};

// Listen for shutdown signals
process.on('SIGTERM', gracefulShutdown);
process.on('SIGINT', gracefulShutdown);

// Start the server
const HOST = process.env.HOST || '0.0.0.0';
server.listen(PORT, HOST, () => {
  console.log(`Express server running at https://${HOST}:${PORT}`);
  console.log('Environment:', process.env.NODE_ENV || 'development');
  console.log('Press Ctrl+C to stop the server');
});

Muhit o‘zgaruvchilaridan foydalanish

Konfiguratsiya uchun muhit o‘zgaruvchilaridan foydalanish eng yaxshi amaliyotdir. .env fayl yarating:

.env fayli

NODE_ENV=development
PORT=3000
HOST=0.0.0.0
SSL_KEY_PATH=./key.pem
SSL_CERT_PATH=./cert.pem

Keyin ularni yuklash uchun dotenv paketidan foydalaning:

Muhit o‘zgaruvchilari yuklanmoqda

require('dotenv').config();

// Access environment variables
const PORT = process.env.PORT || 3000;
const HOST = process.env.HOST || '0.0.0.0';
const sslOptions = {
  key: fs.readFileSync(process.env.SSL_KEY_PATH),
  cert: fs.readFileSync(process.env.SSL_CERT_PATH)
  // ... other options
};

Ishlab chiqarishni joylashtirish

Ishlab chiqarishda Node.js ilovangiz oldida Nginx yoki Apache kabi teskari proksi-serverdan foydalanish tavsiya etiladi. Bu quyidagilarni ta’minlaydi:

  • SSL/TLSni tugatish
  • Yuklarni muvozanatlash
  • Statik fayllarga xizmat ko‘rsatish
  • Keshlashni so‘rash
  • So‘rovlarni cheklash (Rate limiting)
  • Yaxshiroq xavfsizlik sarlavhalari

Nginx konfiguratsiyasiga misol

server {
  listen 443 ssl http2;
  server_name yourdomain.com;

  # SSL configuration
  ssl_certificate /path/to/your/cert.pem;
  ssl_certificate_key /path/to/your/key.pem;

  # Security headers
  add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
  add_header X-Content-Type-Options "nosniff" always;
  add_header X-Frame-Options "SAMEORIGIN" always;
  add_header X-XSS-Protection "1; mode=block" always;

  # Proxy to Node.js app
  location / {
   proxy_pass http://localhost:3000;
   proxy_http_version 1.1;
   proxy_set_header Upgrade $http_upgrade;
   proxy_set_header Connection 'upgrade';
   proxy_set_header Host $host;
   proxy_cache_bypass $http_upgrade;
   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;
  }

  # Serve static files directly
  location /static/ {
   root /path/to/your/app/public;
   expires 30d;
   access_log off;
  }
}

# Redirect HTTP to HTTPS
server {
  listen 80;
  server_name yourdomain.com;
  return 301 https://$host$request_uri;
}

# Redirect HTTP to HTTPS
server {
  listen 80;
  server_name yourdomain.com;
  return 301 https://$host$request_uri;
}

HTTPS bilan Express.js uchun eng yaxshi amaliyotlar:

  • Xavfsizlik sarlavhalari uchun har doim helmet o‘rta dasturdan foydalaning
  • Xavfsiz sessiya parametrlarini o‘rnating (agar sessiyalardan foydalansangiz)
  • Konfiguratsiya uchun muhit o‘zgaruvchilaridan foydalaning
  • Xatolarni to‘g‘ri qayta ishlash va jurnalga yozishni amalga oshiring
  • Ishlab chiqarishda teskari proksi-serverdan foydalaning
  • O‘zingizning bog‘liqliklaringizni yangilab turing
  • Yaxshiroq ishlash uchun HTTP/2 dan foydalaning
  • Suiiste’molning oldini olish uchun stavkani cheklashni amalga oshiring
  • Agar API turli domenlardan foydalanilsa, CORS o‘rta dasturidan foydalaning

Node.js bilan HTTP/2

HTTP/2 HTTP protokolining asosiy qayta ko‘rib chiqilishi bo‘lib, HTTP/1.1 orqali ishlashning sezilarli yaxshilanishini ta’minlaydi. HTTPS bilan birlashganda, u zamonaviy veb-ilovalar uchun ham xavfsizlik, ham ishlash afzalliklarini taqdim etadi.

HTTP/2 ning afzalliklari

HTTP/2 ning asosiy xususiyatlari:

  • Multiplexing: Bitta ulanish orqali bir nechta so‘rovlar/javoblar parallel ravishda yuborilishi mumkin, bu esa asosiy blokirovkani bartaraf qiladi.
  • Sarlavhalarni siqish: HTTP sarlavhalarini siqish orqali yukni kamaytiradi (HPACK algoritmi)
  • Server Push: Server mijozga resurslarni so‘rashdan oldin faol ravishda yuborishi mumkin.
  • Ikkilik protokoli: HTTP/1.1 matnga asoslangan formatiga qaraganda tahlil qilish samaraliroq
  • Stream ustuvorligi: Avval muhimroq resurslarni yuklash mumkin
  • Ulanishni multiplekslash: Bir nechta streamlar bitta TCP ulanishini ulashishi mumkin

HTTP/2 Server misoli

Asosiy HTTP/2 serveri

const http2 = require('http2');
const fs = require('fs');
const path = require('path');

// SSL/TLS options
const serverOptions = {
  key: fs.readFileSync(path.join(__dirname, 'key.pem')),
  cert: fs.readFileSync(path.join(__dirname, 'cert.pem')),
  allowHTTP1: true, // Fallback to HTTP/1.1 if needed

  // Recommended security settings
  minVersion: 'TLSv1.2',
  ciphers: [
    'TLS_AES_256_GCM_SHA384',
    'TLS_CHACHA20_POLY1305_SHA256',
    'TLS_AES_128_GCM_SHA256',
    'ECDHE-ECDSA-AES256-GCM-SHA384',
    '!aNULL',
    '!eNULL',
    '!EXPORT',
    '!DES',
    '!RC4',
    '!3DES',
    '!MD5',
    '!PSK'
  ].join(':'),
  honorCipherOrder: true
};

// Create HTTP/2 server
const server = http2.createSecureServer(serverOptions);

// Handle incoming requests
server.on('stream', (stream, headers) => {
  const method = headers[':method'];
  const path = headers[':path'];
  const scheme = headers[':scheme'];
  const authority = headers[':authority'];

  console.log(`${method} ${path} (HTTP/2)`);

  // Handle different routes
  if (path === '/') {
  // Set response headers
    stream.respond({
      'content-type': 'text/html; charset=utf-8',
      ':status': 200,
      'x-powered-by': 'Node.js HTTP/2',
      'cache-control': 'public, max-age=3600'
    });

    // Send HTML response
    stream.end(`
      <!DOCTYPE html>
      <html>
      <head>
      <title>HTTP/2 Server</title>
      <link rel="stylesheet" href="/styles.css">
      </head>
      <body>
        <h1>Hello from HTTP/2 Server!</h1>
        <p>This page is served over HTTP/2.</p>
        <div id="data">Loading data...</div>
        <script src="/app.js"></script>
      </body>
      </html>
      `);
    }
    // API endpoint
    else if (path === '/api/data' && method === 'GET') {
      stream.respond({
        'content-type': 'application/json',
        ':status': 200,
        'cache-control': 'no-cache'
      });

      stream.end(JSON.stringify({
        message: 'Data from HTTP/2 API',
        timestamp: new Date().toISOString(),
        protocol: 'HTTP/2',
        server: 'Node.js HTTP/2 Server'
      }));
    }
    // Server Push example
    else if (path === '/push') {
      // Push additional resources
      stream.pushStream({ ':path': '/styles.css' }, (err, pushStream) => {
        if (err) {
          console.error('Push stream error:', err);
          return;
        }
        pushStream.respond({
          'content-type': 'text/css',
          ':status': 200
        });
        pushStream.end('body { font-family: Arial, sans-serif; margin: 2em; }');
      }
      stream.respond({
        'content-type': 'text/html; charset=utf-8',
        ':status': 200
      });
      stream.end('<h1>Server Push Example</h1><link rel="stylesheet" href="/styles.css">');
    }
    // 404 Not Found
  else {
    stream.respond({
      'content-type': 'text/plain',
      ':status': 404
    });
    stream.end('404 - Not Found');
  }
});

// Handle errors
server.on('error', (err) => {
  console.error('Server error:', err);
  process.exit(1);
});

// Start the server
const PORT = process.env.PORT || 8443;
server.listen(PORT, '0.0.0.0', () => {
  console.log(`HTTP/2 server running at https://localhost:${PORT}`);
  console.log('Environment:', process.env.NODE_ENV || 'development');
  console.log('Press Ctrl+C to stop the server');
});

// Graceful shutdown
const gracefulShutdown = (signal) => {
  console.log(`\nReceived ${signal}. Shutting down gracefully...`);
  server.close(() => {
    console.log('HTTP/2 server closed.');
    process.exit(0);
  });
 
  // Force close server after 10 seconds
  setTimeout(() => {
    console.error('Forcing shutdown...');
    process.exit(1);
  }, 10000);
};

// Listen for shutdown signals
process.on('SIGTERM', gracefulShutdown);
process.on('SIGINT', gracefulShutdown);

Express.js bilan HTTP/2

HTTP/2-dan Express.js bilan foydalanish uchun siz Express ilovalari uchun HTTP/2-ni qo‘llab-quvvatlaydigan spdy to‘plamidan foydalanishingiz mumkin:

HTTP/2 bilan Express.js

npm install spdy --save
const express = require('express');
const spdy = require('spdy');
const fs = require('fs');
const path = require('path');

const app = express();

// Your Express middleware and routes here
app.get('/', (req, res) => {
  res.send('Hello from Express over HTTP/2!');
});

// SSL/TLS options
const options = {
  key: fs.readFileSync(path.join(__dirname, 'key.pem')),
  cert: fs.readFileSync(path.join(__dirname, 'cert.pem')),
  spdy: {
    protocols: ['h2', 'http/1.1'], // Allow both HTTP/2 and HTTP/1.1
    plain: false, // Use TLS
    'x-forwarded-for': true
  }
};

// Create HTTP/2 server with Express
const PORT = process.env.PORT || 3000;
spdy.createServer(options, app).listen(PORT, () => {
  console.log(`Express server with HTTP/2 running on port ${PORT}`);
});

HTTP/2 qo‘llab-quvvatlash sinovi

Serveringiz HTTP/2 dan foydalanayotganini quyidagi usullar bilan tekshirishingiz mumkin:

cURL dan foydalanish

# Check if server supports HTTP/2
curl -I --http2 https://localhost:8443

# Force HTTP/2 with verbose output
curl -v --http2 https://localhost:8443

# Test with HTTP/2 prior knowledge (no upgrade)
curl --http2-prior-knowledge -I https://localhost:8443

Chrome DevTools-dan foydalanish

  1. Chrome DevTools-ni oching (F12 yoki o‘ng tugmasini bosing → Tekshirish)
  2. Tarmoq yorlig‘iga o‘ting
  3. Ustun sarlavhalarini o‘ng tugmasini bosing va "Protokol" ni yoqing.
  4. HTTP/2 so‘rovlari uchun Protokol ustunida "h2" ni qidiring
  5. Batafsil protokol ma’lumotlarini ko‘rish uchun so‘rov ustiga bosing

Eslatma: HTTP/2 brauzerlarda HTTPS-ni talab qiladi, ammo protokolning o‘zi shifrlashni talab qilmaydi. Barcha asosiy brauzerlar faqat TLS (HTTPS) orqali HTTP/2 ni qo‘llab-quvvatlaydi.

Muhim: HTTP/2 dan foydalanayotganda SSL/TLS konfiguratsiyasi yangilanganligiga va xavfsizlik bo‘yicha eng yaxshi amaliyotlarga rioya qiling, chunki ko‘p HTTP/2 funksiyalari xavfsiz ulanishga tayanadi.


HTTP va HTTPSni solishtirish

Xususiyat HTTP HTTPS
Ma’lumotlarni shifrlash No (plain text) Yes (encrypted)
Server autentifikatsiyasi Yo‘q Yes (via certificates)
Ma’lumotlar yaxlitligi Himoya yo‘q Protected (tampering detected)
Standart port 80 443
Ishlash Tezroq Biroz qo‘shimcha yuklama (lekin HTTP/2 bilan optimallashtirilgan)
SEO reytingi Pastroq Higher (Google prefers HTTPS)
O‘rnatishning murakkabligi Oddiyroq Murakkabroq (sertifikatlar talab qilinadi)

Xulosa va eng yaxshi amaliyotlar

Ushbu keng qamrovli qo‘llanmada biz Node.js HTTPS moduli va uning xavfsiz veb-ilovalarni yaratish imkoniyatlarini ko‘rib chiqdik. Mana asosiy fikrlar va eng yaxshi amaliyotlarning qisqacha mazmuni:

Asosiy xulosalar

  • HTTPS muhim: Zamonaviy veb-ishlab chiqish ma’lumotlar xavfsizligi, foydalanuvchi maxfiyligi va veb-standartlarga muvofiqligini ta’minlash uchun HTTPS-ni talab qiladi.
  • Sertifikatlarni boshqarish: SSL/TLS sertifikatlarini ishlab chiqish uchun o‘z-o‘zidan imzolangan sertifikatlar yoki ishlab chiqarish uchun CA ishonchli sertifikatlaridan foydalanishni to‘g‘ri boshqaring.
  • Birinchi navbatda xavfsizlik: To‘g‘ri TLS konfiguratsiyasi, xavfsiz sarlavhalar va kirish tekshiruvi kabi xavfsizlikning eng yaxshi amaliyotlarini qo‘llang.
  • Umumiylik masalalari: Multiplekslash, sarlavhalarni siqish va serverni surish kabi xususiyatlar orqali yaxshilangan ishlash uchun HTTP/2 dan foydalaning.
  • Ishlab chiqarishga tayyorlik: Yaxshiroq xavfsizlik, ishlash va ishonchlilik uchun ishlab chiqarishda teskari proksi-serverlardan (masalan, Nginx) foydalaning.

Xavfsizlik tekshiruvi ro‘yxati

HTTPS yoqilgan ilovangizni ishlab chiqarishga joylashtirishdan oldin quyidagilarni tekshiring:

  • TLS 1.2 yoki undan yuqori versiyadan foydalaning (1.3 tavsiya etiladi)
  • Implement HSTS (HTTP Strict Transport Security)
  • Xavfsiz shifr to‘plamlaridan foydalaning va zaiflarini o‘chiring
  • Node.js va bog‘liqliklaringizni yangilab turing
  • Xatolarni to‘g‘ri qayta ishlash va jurnalga yozishni amalga oshiring
  • Set secure cookie flags (Secure, HttpOnly, SameSite)
  • Content Security Policy (CSP) sarlavhalaridan foydalaning
  • Tarifni cheklash va so‘rovni tekshirishni amalga oshiring

Ishlashni optimallashtirish

  • Yaxshiroq ishlash uchun HTTP/2 ni yoqing
  • TLS bilan qo‘l siqish yukini kamaytirish uchun seansni davom ettirishni amalga oshiring
  • TLS qo‘l siqish unumdorlikni yaxshilash uchun OCSP zımbalamadan foydalaning
  • Sertifikatlar zanjirini optimallashtiring (uni qisqa va to‘liq saqlang)
  • Seansni davom ettirish bilan yaxshi ishlash uchun seans chiptalarini yoqing

Xavfsizlik doimiy jarayon ekanligini unutmang. Ilovangizni muntazam tekshirib turing, bog‘liqliklarni yangilab turing va eng so‘nggi xavfsizlik amaliyotlari va zaifliklar haqida xabardor bo‘ling.




W3Schools Pathfinder

Yutuqlaringizni kuzating – bu bepul!