Skip to content
DevRecall
← Roadmap
00

Networking Fundamentals

drafted

TCP/IP, DNS, HTTP/1.1/2/3, TLS, CDN, load balancer, proxy, VPN, WebSocket/SSE, CORS — nhìn từ góc backend production.

0/45 rated · mastery 0%

Bài học

10 bài · ~147 phút đọc. Học theo thứ tự, rồi làm câu hỏi.
  1. 01~18 phút· 4 câuverify

    Hành trình của một HTTPS request: tầng mạng, RTT, TCP vs UDP

    Mô hình tầng (IP, TCP/UDP, TLS, HTTP), đếm round-trip từ lúc gõ URL tới byte đầu tiên, vì sao latency do RTT quyết định chứ không phải băng thông, và cách điều tra 'API chậm' từ phía client.

  2. 02~14 phút· 5 câuverify

    TCP connection lifecycle: keep-alive, TIME_WAIT, slow start và ECONNRESET

    Vòng đời một TCP connection, vì sao tái sử dụng connection là tối ưu số một, TIME_WAIT và cạn ephemeral port, congestion control/slow start, và các lỗi idle connection bị middlebox cắt.

  3. 03~15 phút· 5 câuverify

    DNS cho backend: record, TTL, cache nhiều tầng và DNS trong Node.js

    Phân giải tên từ resolver tới authoritative, A/AAAA/CNAME/ALIAS và vì sao không CNAME ở apex, TTL và cache nhiều tầng, dns.lookup vs dns.resolve trong Node, IPv6 localhost, và cách migrate bằng DNS mà không bỏ rơi traffic.

  4. 04~16 phút· 5 câuverify

    TLS & HTTPS: handshake 1.3, certificate chain, SNI/ALPN, 0-RTT và nơi terminate TLS

    TLS thực sự bảo vệ gì, key exchange (EC)DHE và forward secrecy, certificate public key dùng để ký chứ không phải mã hoá dữ liệu, xác thực chain và các lỗi Node thường gặp, SNI/ALPN, rủi ro replay của 0-RTT, và terminate TLS ở đâu.

  5. 05~14 phút· 4 câuverify

    HTTP: ngữ nghĩa method, idempotency và HTTP/1.1 → HTTP/2 → HTTP/3

    Safe vs idempotent và vì sao nó quyết định retry, idempotency key, head-of-line blocking ở từng phiên bản HTTP, multiplexing của HTTP/2 và rủi ro ở scale (Rapid Reset, LB lệch tải), QUIC/HTTP/3 và cách rollout.

  6. 06~13 phút· 5 câuverify

    Same-Origin Policy & CORS: origin, preflight, credentials và vì sao CORS không chống CSRF

    Origin và site khác nhau thế nào, SOP chặn đọc chứ không chặn gửi, simple request vs preflight, cookie cross-origin với credentials và SameSite, lỗi echo Origin bằng regex, và cách chống CSRF đúng.

  7. 07~15 phút· 6 câuverify

    Proxy, load balancer và VPN: L4 vs L7, thuật toán cân bằng, X-Forwarded-For, health check

    Forward vs reverse proxy, VPN và zero-trust khác proxy ở đâu, L4 vs L7 load balancer và nơi TLS terminate, round-robin/least-connections/consistent hashing, lấy IP client đúng qua X-Forwarded-For, và thiết kế health check không gây cascading failure.

  8. 08~13 phút· 4 câuverify

    CDN & HTTP caching: Cache-Control, Vary, cache key và edge cho multi-tenant

    Freshness vs validation, các directive Cache-Control cho CDN trước API, ETag/304, Vary và cache key, stale-while-revalidate, lỗi rò dữ liệu giữa tenant qua cache, và thiết kế edge cho custom domain + HTTPS.

  9. 09~15 phút· 4 câuverify

    Timeout chain & 5xx sau proxy: 502/503/504, keep-alive race, Nginx upload và retry policy

    Đọc 502/503/504/499 để biết điều tra ở đâu, vì sao Node sau ALB trả 502 lẻ tẻ, các timeout của Node và Nginx, upload lớn qua proxy, và thiết kế timeout/retry nhất quán từ client tới DB bằng deadline propagation.

  10. 10~14 phút· 5 câuverify

    Realtime: polling, SSE, WebSocket, Socket.IO và scale kết nối lâu dài

    Chọn giữa short/long polling, Server-Sent Events và WebSocket, handshake WebSocket và những gì proxy cần, vì sao SSE bị dồn cục sau proxy, sticky session và pub/sub khi scale Socket.IO, và thiết kế fan-out cho hàng trăm nghìn kết nối.

Tóm tắt & cheat sheet của track

TL;DR

  • Mỗi HTTP request đi qua chuỗi DNS → TCP (hoặc QUIC) → TLS → HTTP; latency thật nằm ở số round-trip (RTT), không phải băng thông.
  • Senior interview hỏi networking qua triệu chứng production: 502 lẻ tẻ sau load balancer, ECONNRESET, DNS đổi mà client vẫn gọi IP cũ, CORS preflight làm chậm, WebSocket rớt khi scale.
  • Nắm 5 trục: connection lifecycle & keep-alive, HTTP versions & head-of-line blocking, TLS handshake & certificate, DNS caching/TTL, proxy/LB/CDN (header nào bị đổi, timeout nào đứng trước timeout nào).
  • CORS là cơ chế browser nới lỏng Same-Origin Policy để JS được đọc response cross-origin — nó không phải cơ chế chống CSRF.

Khái niệm cốt lõi

Khái niệmMột câuVí dụ ngắn
TCPStream tin cậy, có thứ tự, có congestion control; mở bằng 3-way handshakeSYN → SYN-ACK → ACK = 1 RTT trước khi gửi byte đầu tiên
UDPDatagram không kết nối, không đảm bảo thứ tự/đến nơiDNS query, QUIC, video call
DNSHệ thống phân giải tên → record (A, AAAA, CNAME, MX, TXT...) có TTLapi.example.com A 203.0.113.10 TTL 60
TLSMã hoá + xác thực server (certificate) + toàn vẹn dữ liệu trên TCPTLS 1.3 handshake = 1 RTT
HTTP/1.1Text protocol, 1 request "đang bay" mỗi connectionBrowser mở ~6 connection/origin để song song
HTTP/2Binary framing, multiplex nhiều stream trên 1 TCP connection, HPACK100 request nhỏ chung 1 connection
HTTP/3HTTP trên QUIC (UDP); loại bỏ TCP head-of-line blocking, 0-RTT/1-RTTMạng di động đổi IP vẫn giữ connection (connection ID)
Reverse proxy / LBĐứng trước server, terminate TLS, phân phối tải, thêm X-Forwarded-*Nginx, ALB, Envoy
CDNCache ở edge gần user theo Cache-Control/VaryCache-Control: public, s-maxage=300
CORSServer khai báo origin nào được đọc response qua header Access-Control-*Preflight OPTIONS cho Content-Type: application/json
WebSocketKênh full-duplex nâng cấp từ HTTP (101 Switching Protocols)Chat, realtime dashboard
SSEStream một chiều server → client qua HTTP thường (text/event-stream)Notification, progress bar

Cơ chế hoạt động

Từ URL tới response

TLS 1.3 handshake (rút gọn)

  • Key exchange dùng (EC)DHE → forward secrecy; public key trong certificate dùng để ký (CertificateVerify), không phải để "mã hoá dữ liệu". RSA key exchange đã bị loại khỏi TLS 1.3.
  • Dữ liệu thật được mã hoá bằng symmetric key (AES-GCM / ChaCha20-Poly1305) suy ra từ shared secret.

Timeout chain qua proxy

Quy tắc vàng: upstream (app) phải giữ connection idle lâu hơn downstream (LB); nếu app đóng trước, LB có thể gửi request vào socket vừa bị đóng → 502 lẻ tẻ.

Trade-offs

Lựa chọnƯuNhượcKhi nào dùng
HTTP/1.1Đơn giản, debug dễ, mọi proxy hỗ trợHOL blocking theo connection, nhiều connectionService nội bộ đơn giản
HTTP/2Multiplex, header compression, 1 connectionTCP HOL khi mất gói; một connection = một điểm nghẽn/LB kém đềuBrowser ↔ edge, gRPC
HTTP/3 (QUIC)Không TCP HOL, handshake nhanh, connection migrationUDP có thể bị firewall chặn, CPU cao hơn, tooling kém hơnMobile, mạng loss cao, edge/CDN
L4 LBNhanh, không hiểu HTTP, pass-through TLSKhông route theo path/headerTCP/gRPC throughput cao
L7 LBRoute theo host/path, retry, header, TLS terminationTốn CPU, thêm hop, phải cấu hình timeoutAPI gateway, web app
PollingDễ, cache được, statelessTrễ + lãng phí requestCập nhật hiếm
SSEHTTP thường, auto-reconnect, qua proxy dễMột chiều, text onlyNotification, stream log
WebSocketHai chiều, latency thấpStateful, sticky/pub-sub khi scale, proxy phải hỗ trợ UpgradeChat, collaboration, game

Pitfalls

  • Nghĩ CORS chặn request: browser vẫn gửi simple request (kể cả cookie nếu SameSite cho phép); CORS chỉ quyết định JS có đọc được response không.
  • Access-Control-Allow-Origin: * cùng credentials: 'include' → browser từ chối. Echo origin động thì phải whitelist và thêm Vary: Origin.
  • Node keepAliveTimeout (mặc định 5s) nhỏ hơn idle timeout của LB (ALB mặc định 60s) → 502 ngẫu nhiên.
  • Hạ TTL DNS ngay lúc migrate là muộn — phải hạ trước ít nhất một chu kỳ TTL cũ.
  • Tin X-Forwarded-For từ client mà không cấu hình trust proxy đúng số hop → IP spoofing, rate limit sai.
  • Retry tự động request không idempotent (POST) khi timeout → tạo đơn trùng.
  • HTTP/2 Server Push đã bị các browser lớn bỏ — đừng thiết kế dựa vào nó; dùng 103 Early Hints / preload.

Cheat sheet

  • RTT cold HTTPS (TCP + TLS 1.3): ~2 RTT trước byte response đầu; TLS 1.2 full handshake: ~3 RTT; HTTP/3: ~1 RTT (0-RTT khi resume, có rủi ro replay).
  • 502 = proxy nhận response lỗi/connection bị đóng từ upstream · 504 = upstream không trả lời kịp · 499 (nginx) = client tự đóng.
  • Idempotent: GET, HEAD, PUT, DELETE, OPTIONS; không idempotent: POST, PATCH (thường).
  • Simple CORS request: method GET/HEAD/POST + chỉ CORS-safelisted headers + Content-Type ∈ text/plain, multipart/form-data, application/x-www-form-urlencoded.
  • TIME_WAIT nằm ở phía chủ động đóng connection; nhiều connection ngắn → cạn ephemeral port.
  • DNS: CNAME không đặt được ở zone apex → dùng ALIAS/ANAME/CNAME flattening của provider.
  • WebSocket: Upgrade: websocket + 101; proxy phải forward Upgrade/Connection headers và có idle timeout đủ dài / ping.

Personal notes (Notion)

Ghi chú cá nhân — có thể sai hoặc lỗi thời, dùng để tham khảo.

Interview Questions

Showing 45 / 45

// API: https://api.staging.example.com (Express)
app.use(cors({ origin: '*', credentials: true }));
res.cookie('sid', token, { httpOnly: true });

// SPA: https://app.staging.example.io
await fetch('https://api.staging.example.com/me');
<!-- attacker.com -->
<form action="https://shop.example.com/api/address/delete" method="POST">
  <input name="id" value="123" />
</form>
<script>document.forms[0].submit()</script>
// ALB → Nginx → Node: two proxies we control
app.set('trust proxy', 2);
app.get('/whoami', (req, res) => res.json({ ip: req.ip, ips: req.ips }));
server.listen(3000, '127.0.0.1');        // IPv4 only
await fetch('http://localhost:3000/health'); // may try ::1 first
const server = app.listen(3000);
server.keepAliveTimeout = 65_000; // > ALB idle timeout (60s)
server.headersTimeout = 66_000;   // must exceed keepAliveTimeout
server {
  listen 443 ssl;
  client_max_body_size 0;          # "fix": unlimited
  proxy_read_timeout 3600s;
  proxy_request_buffering on;
  location /upload {
    proxy_pass http://node_upstream;
  }
}
import https from 'node:https';

export function callPricing(sku: string) {
  return new Promise((resolve, reject) => {
    const req = https.request(
      { host: 'pricing.internal', path: `/p/${sku}`, agent: new https.Agent({ keepAlive: true }) },
      (res) => { let b = ''; res.on('data', (c) => (b += c)); res.on('end', () => resolve(JSON.parse(b))); },
    );
    req.on('error', reject);
    req.end();
  });
}
app.use((req, res, next) => {
  const origin = req.headers.origin ?? '';
  if (/example\.com$/.test(origin)) {
    res.setHeader('Access-Control-Allow-Origin', origin);
    res.setHeader('Access-Control-Allow-Credentials', 'true');
  }
  next();
});
res.writeHead(200, {
  'Content-Type': 'text/event-stream',
  'Cache-Control': 'no-cache',
  'X-Accel-Buffering': 'no',
});
const t = setInterval(() => res.write(': ping\n\n'), 15_000);
req.on('close', () => clearInterval(t));
app.get('/health', async (_req, res) => {
  await db.query('SELECT 1');
  await redis.ping();
  await fetch('https://payments.partner.com/status');
  res.send('ok');
});
// LB: interval 5s, timeout 2s, unhealthy threshold 2