Chương 1 — Mạng máy tính (TCP/IP, OSI)
Tổng quan
Mở Wireshark lên mà không nắm cơ chế từng tầng thì cũng chỉ là nhìn một đống số chạy qua: gói này bị drop, nhưng drop ở đâu và vì cái gì thì chịu. Chương này bám theo đúng câu hỏi đó: một byte đi từ tiến trình ứng dụng ra tới dây mạng như thế nào, và ở mỗi chặng trên đường đi, kẻ tấn công có thể chen vào bằng cách nào — nghe lén, giả mạo, chặn bắt hay làm nghẽn.
Chương mở đầu bằng hai mô hình tham chiếu OSI và TCP/IP — khung để gọi tên từng tầng — rồi tới cơ chế encapsulation/decapsulation, nơi mỗi tầng gắn thêm một header mà cả công cụ phân tích lẫn kẻ tấn công đều đọc được. Từ đó mạch chương đi xuống dần: tầng 2 với Ethernet, MAC, VLAN, ARP và switch; tầng 3 với IP, ICMP, định tuyến và NAT; rồi tầng 4 với TCP/UDP và cổng dịch vụ — mỗi tầng mở ra một lớp bề mặt tấn công riêng. Phần cuối quay về những thứ chạm hằng ngày: các giao thức tầng ứng dụng như DNS, DHCP, HTTP, TLS, và bộ đôi phòng thủ/quan sát là tường lửa, DMZ cùng tcpdump/Wireshark.
Mỗi mục đi từ khái niệm tới cơ chế bit/byte rồi một ví dụ gõ lại được ngay — viết cho ai đang làm Blue Team, AppSec hay DevSecOps và cần đọc được gói tin chứ không chỉ thuộc định nghĩa.
1.1. Hai mô hình tham chiếu: OSI 7 tầng và TCP/IP
1.1.1. Vì sao cần mô hình phân tầng
Truyền dữ liệu qua mạng là một bài toán rất nhiều việc: biểu diễn bit trên dây đồng/sợi quang, định địa chỉ máy, định tuyến qua hàng chục router, đảm bảo độ tin cậy, mã hóa, biểu diễn dữ liệu ứng dụng. Gom tất cả vào một khối nguyên (monolith) thì gần như không thể bảo trì, cũng không thể thay từng phần công nghệ (đổi cáp đồng sang quang, đổi IPv4 sang IPv6) mà không phá vỡ toàn bộ.
Giải pháp là phân tầng (layering): mỗi tầng cung cấp dịch vụ cho tầng trên và sử dụng dịch vụ của tầng dưới, qua một interface cố định. Nguyên tắc cốt lõi:
- Encapsulation: dữ liệu của tầng trên được tầng dưới đối xử như payload mờ (opaque), bọc thêm header (và đôi khi trailer) của tầng dưới.
- Tách biệt mối quan tâm (separation of concerns): TCP không cần biết gói tin đi qua Ethernet hay Wi-Fi; IP không cần biết payload là TCP hay UDP.
- Khả năng thay thế (interchangeability): có thể thay tầng vật lý mà không đổi tầng IP.
1.1.2. Mô hình OSI (ISO/IEC 7498-1)
| Tầng | Tên | PDU | Chức năng cốt lõi | Ví dụ giao thức/thiết bị |
|---|---|---|---|---|
| 7 | Application | Data | Giao diện cho ứng dụng | HTTP, DNS, SMTP, FTP |
| 6 | Presentation | Data | Mã hóa, nén, biểu diễn dữ liệu | TLS, ASCII/UTF-8, JPEG |
| 5 | Session | Data | Thiết lập/duy trì/kết thúc phiên | RPC, NetBIOS, SOCKS |
| 4 | Transport | Segment (TCP) / Datagram (UDP) | Port, độ tin cậy, kiểm soát luồng | TCP, UDP, SCTP, QUIC |
| 3 | Network | Packet | Định địa chỉ logic, định tuyến | IPv4, IPv6, ICMP, IPsec |
| 2 | Data Link | Frame | Địa chỉ vật lý (MAC), truy nhập môi trường | Ethernet, 802.11, ARP, VLAN |
| 1 | Physical | Bit/Symbol | Biểu diễn bit thành tín hiệu | Cáp đồng, quang, RF, NIC PHY |
Lưu ý PDU — tầng 4 TCP gọi là segment, UDP gọi là datagram; tầng 3 là packet; tầng 2 là frame; tầng 1 là bit/symbol.
1.1.3. Mô hình TCP/IP (RFC 1122)
TCP/IP là mô hình thực tế (de facto) của Internet. RFC 1122 chia thành 4 tầng:
| Tầng TCP/IP | Ánh xạ OSI | Giao thức tiêu biểu |
|---|---|---|
| Application | 7 + 6 + 5 | HTTP, DNS, TLS (thường gộp ở đây), SMTP |
| Transport | 4 | TCP, UDP |
| Internet | 3 | IPv4, IPv6, ICMP, ARP (ranh giới mờ với L2) |
| Link / Network Access | 2 + 1 | Ethernet, Wi-Fi, PPP |
Vì sao có hai mô hình? OSI là mô hình lý thuyết (đặc tả 1984) đầy đủ và dùng để giảng dạy/chuẩn hóa thuật ngữ. TCP/IP ra đời từ ARPANET, đơn giản hơn, là cái thật sự chạy trên Internet. Kỹ sư bảo mật phải thông thạo cả hai vì công cụ và tài liệu trộn lẫn cách dùng (ví dụ "L7 firewall", "L2 attack", "L3/L4 ACL").
1.2. Encapsulation / Decapsulation byte-by-byte
1.2.1. Quá trình bọc dữ liệu khi gửi
Giả sử trình duyệt gửi một request HTTP GET / tới một web server trong cùng mạng LAN qua HTTP (không TLS để đơn giản hóa).
Tầng 7 (HTTP) : [ "GET / HTTP/1.1\r\nHost: x\r\n\r\n" ] <- App data (D)
Tầng 4 (TCP) : [ TCP header 20B | D ] <- Segment
Tầng 3 (IP) : [ IPv4 header 20B | TCP header 20B | D ] <- Packet
Tầng 2 (Eth) : [ Eth header 14B | IPv4 20B | TCP 20B | D | FCS 4B ] <- Frame
Tầng 1 (PHY) : [ Preamble 7B | SFD 1B | <Frame trên dây> ] <- Bit stream
Mỗi tầng chỉ thêm header của mình và coi tất cả những gì nhận từ tầng trên là payload mờ. Đây là lý do mỗi header phải có trường "protocol/next header" để bên nhận biết payload thuộc giao thức nào (xem EtherType, Protocol của IPv4, port của TCP).
1.2.2. Quá trình tháo dữ liệu khi nhận (decapsulation)
Bên nhận làm ngược lại, mỗi tầng đọc header của mình, kiểm tra (checksum/FCS), bóc ra, rồi đẩy payload lên tầng trên dựa vào trường "next protocol":
PHY : nhận bit -> dò Preamble/SFD đồng bộ clock -> lấy frame
L2 : kiểm FCS (CRC32). EtherType=0x0800 -> đẩy lên IPv4
L3 : kiểm IP checksum, kiểm Dst IP là của mình, Protocol=6 -> TCP
L4 : kiểm TCP checksum, dùng Dst Port=80 -> đẩy lên process nghe cổng 80
L7 : web server parse "GET / HTTP/1.1"
1.2.3. Ví dụ thực tế: xem từng tầng bằng tcpdump
# -X in hex+ASCII, -e in cả Ethernet header, -nn không phân giải tên/cổng
sudo tcpdump -i eth0 -e -nn -X 'tcp port 80 and host 192.0.2.10' -c 1
Output mẫu (rút gọn, đã chú thích):
14:02:11.123456 aa:bb:cc:11:22:33 > de:ad:be:ef:00:01, ethertype IPv4 (0x0800), length 74:
10.0.0.5.54321 > 192.0.2.10.80: Flags [S], seq 1001, win 64240,
options [mss 1460,sackOK,TS val 1 ecr 0,nop,wscale 7], length 0
0x0000: dead beef 0001 aabb cc11 2233 0800 4500 <- Eth(14) + IP bắt đầu (45=Ver4,IHL5)
0x0010: 003c 1c46 4000 4006 ... <- TotalLen 0x3c=60, Flags+FragOff, TTL=0x40=64, Proto=0x06=TCP
...
dead beef 0001= Dst MAC;aabb cc11 2233= Src MAC;0800= EtherType IPv4.45=0100 0101-> Version 4, IHL 5 (5×4=20 byte).40(ở offset TTL) = TTL 64;06= Protocol 6 = TCP.
1.3. Tầng 2 — Ethernet, MAC, VLAN, ARP, switch
1.3.1. Khung Ethernet II — layout từng trường
Ethernet II (DIX) là định dạng phổ biến nhất hiện nay (khác với IEEE 802.3 dùng trường Length thay EtherType).
| Trường | Kích thước | Offset (trong frame trên dây) | Ý nghĩa | Ví dụ |
|---|---|---|---|---|
| Preamble | 7 byte | 0 | 7 byte 0xAA (10101010…) đồng bộ clock |
AA AA AA AA AA AA AA |
| SFD (Start Frame Delimiter) | 1 byte | 7 | 0xAB (10101011), bit cuối =1 báo bắt đầu frame |
AB |
| Destination MAC | 6 byte | 8 | MAC đích | de:ad:be:ef:00:01 |
| Source MAC | 6 byte | 14 | MAC nguồn | aa:bb:cc:11:22:33 |
| EtherType / Length | 2 byte | 20 | ≥0x0600 = EtherType; <0x0600 = Length (802.3) | 0x0800 (IPv4) |
| Payload | 46–1500 byte | 22 | Dữ liệu tầng trên (IP packet) | … |
| FCS (Frame Check Sequence) | 4 byte | cuối | CRC-32 trên Dst..Payload | 0x1c2d3e4f |
Preamble + SFD (8 byte) không được tính vào frame khi bắt bằng tcpdump/Wireshark (NIC bóc trước). Chúng cũng không thuộc MTU.
EtherType phổ biến:
| EtherType | Giao thức |
|---|---|
| 0x0800 | IPv4 |
| 0x0806 | ARP |
| 0x86DD | IPv6 |
| 0x8100 | VLAN tag 802.1Q |
| 0x8847 | MPLS unicast |
MTU và kích thước: - MTU mặc định Ethernet = 1500 byte (payload tối đa). Frame tối đa (không tính preamble/SFD) = 14 (header) + 1500 + 4 (FCS) = 1518 byte. Với VLAN tag thêm 4 byte → 1522. - Payload tối thiểu 46 byte: nếu nhỏ hơn, phải padding thêm số 0 cho đủ. Vì sao? Để frame tối thiểu đạt 64 byte (đảm bảo phát hiện collision trong Ethernet half-duplex cũ — slot time). - Jumbo frame: MTU 9000 (không chuẩn IEEE nhưng phổ biến trong datacenter/SAN).
Cấu trúc địa chỉ MAC (48 bit):
AA:BB:CC:DD:EE:FF
└── OUI (24 bit) ──┘└── NIC-specific (24 bit) ──┘
Byte đầu (AA): bit 0 (I/G) = 1 -> multicast; =0 -> unicast
bit 1 (U/L) = 1 -> locally administered; =0 -> universal (OUI thật)
Broadcast = FF:FF:FF:FF:FF:FF
1.3.2. VLAN — IEEE 802.1Q tag (4 byte)
Khi cần phân tách logic nhiều mạng trên cùng hạ tầng vật lý, switch chèn tag 802.1Q 4 byte vào frame, ngay sau Source MAC.
[ Dst MAC 6B | Src MAC 6B | 802.1Q TAG 4B | EtherType 2B | Payload | FCS 4B ]
│
▼
┌──────────────────────────────────────────┐
│ TPID 16b | PCP 3b | DEI 1b | VID 12b │
└──────────────────────────────────────────┘
| Trường | Kích thước | Ý nghĩa | Ví dụ |
|---|---|---|---|
| TPID (Tag Protocol ID) | 16 bit | 0x8100 báo đây là 802.1Q |
0x8100 |
| PCP (Priority Code Point) | 3 bit | Ưu tiên QoS (0–7) | 5 (voice) |
| DEI (Drop Eligible Indicator) | 1 bit | Cho phép drop khi nghẽn | 0 |
| VID (VLAN ID) | 12 bit | ID VLAN (0–4095; 0 và 4095 dành riêng) | 100 |
- VID 12 bit → tối đa 4094 VLAN dùng được. Native VLAN: trên trunk port, VLAN không tag.
- Lưu ý: VLAN hopping.
- Double tagging: kẻ tấn công gắn 2 tag; switch bóc tag ngoài (native VLAN), forward sang trunk còn tag trong → frame nhảy sang VLAN khác. Phòng: đặt native VLAN là một VLAN "chết" không dùng, hoặc tag cả native VLAN (
vlan dot1q tag native). - Switch spoofing: kẻ tấn công giả DTP để biến port access thành trunk. Phòng: tắt DTP (
switchport mode access,switchport nonegotiate).
1.3.3. ARP — Address Resolution Protocol (RFC 826)
ARP ánh xạ địa chỉ IP (L3) sang địa chỉ MAC (L2) trong cùng broadcast domain. Trước khi gửi IP packet tới một host cùng subnet, máy phải biết MAC của host đó.
Layout gói ARP (28 byte cho IPv4-over-Ethernet), đặt trong payload Ethernet EtherType 0x0806:
| Trường | Kích thước | Ý nghĩa | Ví dụ |
|---|---|---|---|
| Hardware Type (HTYPE) | 2 byte | Loại L2; Ethernet = 1 | 0x0001 |
| Protocol Type (PTYPE) | 2 byte | Loại L3; IPv4 = 0x0800 | 0x0800 |
| Hardware Addr Len (HLEN) | 1 byte | Độ dài MAC = 6 | 0x06 |
| Protocol Addr Len (PLEN) | 1 byte | Độ dài IP = 4 | 0x04 |
| Operation (OPER) | 2 byte | 1=request, 2=reply | 0x0001 |
| Sender Hardware Addr (SHA) | 6 byte | MAC người gửi | aa:bb:cc:11:22:33 |
| Sender Protocol Addr (SPA) | 4 byte | IP người gửi | 10.0.0.5 |
| Target Hardware Addr (THA) | 6 byte | MAC đích (0 trong request) | 00:00:00:00:00:00 |
| Target Protocol Addr (TPA) | 4 byte | IP cần hỏi | 10.0.0.1 |
Quy trình request/reply:
1. Host A (10.0.0.5) muốn gửi tới 10.0.0.1, không có trong ARP cache.
2. A broadcast ARP request: Eth Dst = ff:ff:ff:ff:ff:ff, OPER=1, TPA=10.0.0.1, THA=0.
3. Mọi host trong broadcast domain nhận; chỉ 10.0.0.1 trả lời.
4. B unicast ARP reply về A: OPER=2, SHA = MAC của B, SPA=10.0.0.1.
5. A lưu cặp 10.0.0.1 → MAC_B vào ARP cache (timeout vài chục giây–vài phút).
Ví dụ thực tế:
ip neigh show # Xem ARP cache (Linux hiện đại)
# 10.0.0.1 dev eth0 lladdr de:ad:be:ef:00:01 REACHABLE
arping -I eth0 10.0.0.1 # Gửi ARP request thủ công
sudo tcpdump -i eth0 -nn arp # Bắt gói ARP
ARP spoofing/poisoning. Lưu ý: ARP không có xác thực. Kẻ tấn công gửi ARP reply giả (gratuitous ARP) liên tục: "IP gateway 10.0.0.1 có MAC = MAC_kẻ_tấn_công". Nạn nhân ghi đè cache → mọi traffic ra gateway đi qua máy attacker (Man-in-the-Middle).
# Minh họa (chỉ trong lab được phép):
sudo arpspoof -i eth0 -t 10.0.0.5 10.0.0.1 # nói với .5 rằng .1 là tôi
# Kết hợp bật ip_forward để traffic không đứt:
echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
Phòng thủ: Dynamic ARP Inspection (DAI) trên switch (kiểm ARP với DHCP snooping binding), static ARP cho gateway quan trọng, port security, giám sát thay đổi mapping (arpwatch).
1.3.4. Switch CAM table (MAC address table)
Switch học MAC bằng cách xem Source MAC của frame đến trên mỗi port, lưu vào bảng CAM: MAC → port. Khi forward, tra Dst MAC:
- Có trong CAM → gửi đúng port (unicast).
- Không có (unknown unicast) hoặc broadcast/multicast → flood ra tất cả port trừ port đến.
Bảo mật — CAM table overflow / MAC flooding: attacker bơm hàng nghìn frame với Source MAC ngẫu nhiên (macof) làm đầy CAM table. Khi đầy, switch flood mọi traffic như hub → attacker sniff được. Phòng: port security giới hạn số MAC/port.
Switch(config-if)# switchport port-security
Switch(config-if)# switchport port-security maximum 2
Switch(config-if)# switchport port-security violation shutdown
Switch(config-if)# switchport port-security mac-address sticky
1.4. Tầng 3 — IPv4, IPv6, ICMP, định tuyến, NAT
1.4.1. IPv4 header — layout 20 byte (không Options)
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Version| IHL |DSCP |ECN| Total Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Identification |Flags| Fragment Offset |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| TTL | Protocol | Header Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source IP Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Destination IP Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Options (nếu IHL>5) | Padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Trường | Kích thước | Offset (byte) | Ý nghĩa | Ví dụ |
|---|---|---|---|---|
| Version | 4 bit | 0 | Phiên bản IP = 4 | 4 |
| IHL (Internet Header Length) | 4 bit | 0 | Độ dài header theo đơn vị 4 byte; min 5 (=20B), max 15 (=60B) | 5 |
| DSCP | 6 bit | 1 | Differentiated Services (QoS) | 0 |
| ECN | 2 bit | 1 | Explicit Congestion Notification | 0 |
| Total Length | 16 bit | 2 | Tổng độ dài header+payload (byte); max 65535 | 60 |
| Identification | 16 bit | 4 | ID datagram, dùng ráp mảnh | 0x1c46 |
| Flags | 3 bit | 6 | bit0=reserved(0), bit1=DF (Don't Fragment), bit2=MF (More Fragments) | 010 (DF) |
| Fragment Offset | 13 bit | 6 | Vị trí mảnh (đơn vị 8 byte) | 0 |
| TTL (Time To Live) | 8 bit | 8 | Số hop còn lại; mỗi router −1; =0 thì drop + ICMP | 64 |
| Protocol | 8 bit | 9 | Giao thức payload: 1=ICMP,6=TCP,17=UDP | 6 |
| Header Checksum | 16 bit | 10 | Checksum chỉ của header | 0xb1e6 |
| Source IP | 32 bit | 12 | IP nguồn | 10.0.0.5 |
| Destination IP | 32 bit | 16 | IP đích | 192.0.2.10 |
| Options | 0–40 byte | 20 | Tùy chọn (record route, timestamp…) | — |
Vì sao TTL? Ngăn packet quay vòng vô hạn khi routing loop. traceroute lợi dụng TTL: gửi gói TTL=1,2,3… mỗi router làm TTL=0 sẽ trả về ICMP Time Exceeded, lộ IP của nó.
Header Checksum dùng one's complement sum của các half-word 16 bit của header. Vì TTL đổi mỗi hop nên router phải tính lại checksum mỗi hop (lý do IPv6 bỏ checksum này để giảm tải).
1.4.2. Fragmentation (phân mảnh IPv4)
Khi packet lớn hơn MTU của link kế tiếp và không có cờ DF, router chia thành nhiều mảnh.
Ví dụ: datagram payload 4000 byte qua link MTU 1500 (payload IP tối đa = 1500−20 = 1480, phải bội số 8 → dùng 1480).
| Mảnh | Bytes data | Fragment Offset (đơn vị 8B) | MF | Total Length |
|---|---|---|---|---|
| 1 | 0–1479 | 0 | 1 | 1500 |
| 2 | 1480–2959 | 185 (=1480/8) | 1 | 1500 |
| 3 | 2960–3999 | 370 (=2960/8) | 0 | 1060 |
Tất cả mảnh dùng cùng Identification. Bên nhận ráp lại theo offset. Bảo mật: tấn công overlapping fragment (Teardrop), tiny fragment vượt firewall, fragment-based IDS evasion. Phòng: firewall ráp mảnh trước khi inspect (virtual reassembly).
1.4.3. IPv6 header — layout 40 byte cố định
0 1 2 3
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Version| Traffic Class | Flow Label |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Payload Length | Next Header | Hop Limit |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
+ Source Address (128 bit) +
| ... (16 byte) ... |
+ +
| |
+ Destination Address (128 bit) +
| ... (16 byte) ... |
+ +
| Trường | Kích thước | Ý nghĩa | Ví dụ |
|---|---|---|---|
| Version | 4 bit | = 6 | 6 |
| Traffic Class | 8 bit | DSCP+ECN tương tự IPv4 | 0 |
| Flow Label | 20 bit | Đánh dấu luồng cho QoS | 0x12345 |
| Payload Length | 16 bit | Độ dài payload (không gồm 40B header) | 1280 |
| Next Header | 8 bit | Như Protocol IPv4; cũng trỏ extension header | 6 (TCP) |
| Hop Limit | 8 bit | Như TTL | 64 |
| Source Address | 128 bit | IPv6 nguồn | 2001:db8::1 |
| Destination Address | 128 bit | IPv6 đích | 2001:db8::2 |
Khác biệt thiết kế quan trọng: header cố định 40B (không IHL/Options trong header chính — dùng extension headers nối chuỗi qua Next Header); không checksum (giao cho L2 FCS và L4 checksum); router không phân mảnh (host tự dùng Path MTU Discovery); MTU tối thiểu 1280B. IPv6 không dùng ARP mà dùng NDP (Neighbor Discovery Protocol) qua ICMPv6.
1.4.4. ICMP (RFC 792)
Đặt trong payload IP với Protocol=1. Header chung 8 byte:
| Trường | Kích thước | Ý nghĩa | Ví dụ |
|---|---|---|---|
| Type | 1 byte | Loại thông điệp | 8 (Echo Request) |
| Code | 1 byte | Mã con | 0 |
| Checksum | 2 byte | Checksum ICMP | 0xf7ff |
| Rest of Header | 4 byte | Tùy Type (Echo: Identifier 2B + Sequence 2B) | id=0x1234 seq=1 |
Type/Code quan trọng:
| Type | Code | Ý nghĩa |
|---|---|---|
| 0 | 0 | Echo Reply (ping trả lời) |
| 3 | 0–15 | Destination Unreachable (3=port unreachable, 4=frag needed+DF) |
| 5 | 0–3 | Redirect |
| 8 | 0 | Echo Request (ping) |
| 11 | 0 | Time Exceeded (TTL=0, dùng cho traceroute) |
ping -c 3 8.8.8.8
sudo tcpdump -i eth0 -nn icmp
# ICMP type 8 = request; type 0 = reply; type 11 = traceroute hops
Bảo mật: ICMP tunneling (đẩy data trong payload Echo để bypass firewall — ptunnel), ICMP redirect spoofing, smurf attack (broadcast amplification). Nhiều nơi rate-limit/filter ICMP nhưng KHÔNG nên chặn Type 3 Code 4 vì sẽ phá PMTUD.
1.4.5. RFC 1918, CIDR và chia subnet thủ công
RFC 1918 — dải IP riêng (private):
| Dải | CIDR | Số địa chỉ |
|---|---|---|
| 10.0.0.0 – 10.255.255.255 | 10.0.0.0/8 | 16.777.216 |
| 172.16.0.0 – 172.31.255.255 | 172.16.0.0/12 | 1.048.576 |
| 192.168.0.0 – 192.168.255.255 | 192.168.0.0/16 | 65.536 |
Khác: 127.0.0.0/8 loopback; 169.254.0.0/16 link-local (APIPA); 100.64.0.0/10 CGNAT (RFC 6598).
CIDR (Classless Inter-Domain Routing): ký hiệu /n = n bit đầu là phần network (netmask). Ví dụ /24 → mask 255.255.255.0, 8 bit host → 2^8 = 256 địa chỉ, dùng được 256 − 2 = 254 host (trừ network address và broadcast).
Chia subnet thủ công — ví dụ từng bước: chia 192.168.1.0/24 thành 4 subnet đều nhau.
- Cần 4 subnet → cần
log2(4) = 2bit mượn từ phần host. Prefix mới:/24 + 2 = /26. - Mask
/26=255.255.255.192(byte cuối11000000= 192). - Block size (bước nhảy) =
256 − 192 = 64. - Liệt kê:
| Subnet | Network | Dải host dùng được | Broadcast |
|---|---|---|---|
| 1 | 192.168.1.0/26 | .1 – .62 | 192.168.1.63 |
| 2 | 192.168.1.64/26 | .65 – .126 | 192.168.1.127 |
| 3 | 192.168.1.128/26 | .129 – .190 | 192.168.1.191 |
| 4 | 192.168.1.192/26 | .193 – .254 | 192.168.1.255 |
Mỗi subnet: 2^(32−26) = 64 địa chỉ, dùng được 64 − 2 = 62 host.
Xác định IP có thuộc subnet không (AND bitwise): IP 192.168.1.130 với mask /26:
IP: 11000000.10101000.00000001.10000010
Mask: 11111111.11111111.11111111.11000000
AND: 11000000.10101000.00000001.10000000 = 192.168.1.128 -> Subnet 3
ipcalc 192.168.1.130/26 # công cụ tính nhanh
sipcalc 192.168.1.0/24 -s 26
1.4.6. NAT / PAT / SNAT / DNAT
NAT (Network Address Translation): dịch IP (và port) khi packet đi qua router biên. Lý do tồn tại: IPv4 cạn kiệt; nhiều host private chia sẻ một public IP.
| Loại | Dịch gì | Dùng cho |
|---|---|---|
| Static NAT (1:1) | 1 private ↔ 1 public cố định | Server cần địa chỉ public ổn định |
| Dynamic NAT | private ↔ public từ pool | Nhiều host, pool public |
| PAT / NAPT / Overload | nhiều private → 1 public, phân biệt bằng port | Trường hợp phổ biến nhất ở nhà/cty |
| SNAT (Source NAT) | đổi Source IP (outbound) | LAN → Internet |
| DNAT (Destination NAT) | đổi Dst IP (inbound) | Port forwarding tới server nội bộ |
Bảng dịch PAT (translation table):
| Inside Local | Inside Global | Outside | Protocol |
|---|---|---|---|
| 10.0.0.5:54321 | 203.0.113.10:40001 | 192.0.2.10:80 | TCP |
| 10.0.0.6:51000 | 203.0.113.10:40002 | 1.1.1.1:443 | TCP |
Router thay Source 10.0.0.5:54321 → 203.0.113.10:40001 khi ra, và làm ngược khi gói trả về dựa vào port 40001.
Ví dụ thực tế — iptables/nftables:
# SNAT/MASQUERADE: LAN 10.0.0.0/24 ra ngoài qua eth0
sudo iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o eth0 -j MASQUERADE
# DNAT: forward public:8080 -> server nội bộ 10.0.0.50:80
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 8080 \
-j DNAT --to-destination 10.0.0.50:80
sudo iptables -A FORWARD -p tcp -d 10.0.0.50 --dport 80 -j ACCEPT
# Xem bảng NAT đang hoạt động
sudo conntrack -L
Bảo mật: NAT không phải firewall (nhiều người nhầm). NAT slipstreaming, hairpin NAT, và việc DNAT mở cổng ra Internet là bề mặt tấn công lớn.
1.4.7. Định tuyến (routing) cơ bản
Router quyết định next-hop bằng longest prefix match trong routing table.
ip route show
# default via 10.0.0.1 dev eth0
# 10.0.0.0/24 dev eth0 proto kernel scope link src 10.0.0.5
ip route get 8.8.8.8 # xem packet sẽ đi route nào
Default route 0.0.0.0/0 là "khớp mọi đích" với prefix ngắn nhất (chỉ dùng khi không có route cụ thể hơn).
1.5. Tầng 4 — TCP và UDP
1.5.1. UDP header — layout 8 byte (RFC 768)
| Trường | Kích thước | Offset | Ý nghĩa | Ví dụ |
|---|---|---|---|---|
| Source Port | 16 bit | 0 | Cổng nguồn | 54321 |
| Destination Port | 16 bit | 2 | Cổng đích | 53 |
| Length | 16 bit | 4 | Độ dài header+data (≥8) | 40 |
| Checksum | 16 bit | 6 | Checksum (tùy chọn IPv4, bắt buộc IPv6) | 0x1a2b |
UDP không bắt tay, không đảm bảo thứ tự/độ tin cậy, không kiểm soát luồng. Dùng cho DNS, DHCP, VoIP, QUIC. Checksum của UDP/TCP tính trên một pseudo-header gồm Src IP, Dst IP, Protocol, Length của tầng IP — để phát hiện packet bị giao nhầm địa chỉ.
1.5.2. TCP header — layout 20 byte (không Options), RFC 9293
0 1 2 3
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Port | Destination Port |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Sequence Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Acknowledgment Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| DOff |Rsv|N|C|E|U|A|P|R|S|F| Window Size |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Checksum | Urgent Pointer |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Options (nếu DOff>5) | Padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Trường | Kích thước | Offset | Ý nghĩa | Ví dụ |
|---|---|---|---|---|
| Source Port | 16 bit | 0 | Cổng nguồn | 54321 |
| Destination Port | 16 bit | 2 | Cổng đích | 443 |
| Sequence Number | 32 bit | 4 | Số thứ tự byte đầu của segment (hoặc ISN khi SYN) | 1001 |
| Acknowledgment Number | 32 bit | 8 | Số byte kế tiếp mong nhận (hợp lệ khi ACK=1) | 2001 |
| Data Offset (DOff) | 4 bit | 12 | Độ dài header TCP theo đơn vị 4 byte (min 5=20B) | 5 |
| Reserved | 3 bit | 12 | =0 | 0 |
| Flags (9 bit) | 9 bit | 12–13 | Xem dưới | — |
| Window Size | 16 bit | 14 | Số byte cửa sổ nhận (receive window) | 64240 |
| Checksum | 16 bit | 16 | Checksum (gồm pseudo-header) | 0x4a8c |
| Urgent Pointer | 16 bit | 18 | Offset dữ liệu khẩn (khi URG=1) | 0 |
9 cờ TCP (từ bit cao xuống thấp):
| Cờ | Tên | Ý nghĩa |
|---|---|---|
| NS | Nonce Sum | ECN nonce (RFC 3540, hiếm dùng) |
| CWR | Congestion Window Reduced | Báo đã giảm cwnd do nghẽn |
| ECE | ECN-Echo | Báo nhận được dấu hiệu nghẽn |
| URG | Urgent | Urgent Pointer hợp lệ |
| ACK | Acknowledgment | Ack Number hợp lệ |
| PSH | Push | Đẩy data lên app ngay, không buffer |
| RST | Reset | Hủy kết nối đột ngột |
| SYN | Synchronize | Khởi tạo kết nối, đồng bộ seq |
| FIN | Finish | Kết thúc gửi dữ liệu một chiều |
TCP Options thường gặp (trong vùng Options):
| Option | Kind | Độ dài | Ý nghĩa |
|---|---|---|---|
| End of Option List | 0 | 1B | Kết thúc options |
| No-Operation (NOP) | 1 | 1B | Padding căn 4 byte |
| MSS (Maximum Segment Size) | 2 | 4B | Kích thước segment tối đa, thường 1460 (1500−40) |
| Window Scale | 3 | 3B | Nhân hệ số window (dịch trái), tối đa ×2^14 |
| SACK Permitted | 4 | 2B | Cho phép Selective ACK |
| SACK | 5 | thay đổi | Báo các block đã nhận rời rạc |
| Timestamps | 8 | 10B | TSval/TSecr đo RTT, chống wrap (PAWS) |
1.5.3. Bắt tay 3 bước (3-way handshake) — giá trị seq/ack từng bước
Client (10.0.0.5) Server (1.2.3.4:443)
| |
| 1. SYN seq=x (ISN_c=1000), ack=0 |
|------------------------------------------------->| Flags=[S]
| |
| 2. SYN-ACK seq=y (ISN_s=5000), ack=x+1=1001 |
|<-------------------------------------------------| Flags=[S.]
| |
| 3. ACK seq=x+1=1001, ack=y+1=5001 |
|------------------------------------------------->| Flags=[.]
| |
(kết nối ESTABLISHED, data bắt đầu từ seq=1001/5001)
Giải thích chi tiết: 1. Client chọn ISN (Initial Sequence Number) ngẫu nhiên (=1000), gửi SYN với seq=1000. SYN tiêu tốn 1 số seq (dù không chở data). 2. Server chọn ISN riêng (=5000), gửi SYN-ACK: seq=5000, ack=1001 (xác nhận đã nhận seq 1000, mong byte tiếp theo là 1001). 3. Client gửi ACK: seq=1001, ack=5001. Kết nối thành ESTABLISHED.
Vì sao ISN ngẫu nhiên? Chống TCP sequence prediction attack (kẻ ngoài đoán seq để chèn/spoof). RFC 6528 yêu cầu ISN = hàm băm bí mật.
Bảo mật — SYN flood: attacker gửi loạt SYN với Source IP giả, không gửi ACK bước 3. Server giữ nhiều half-open connection trong backlog queue → cạn tài nguyên. Phòng: SYN cookies (server mã hóa state vào ISN, không lưu queue cho tới khi nhận ACK hợp lệ).
sysctl net.ipv4.tcp_syncookies=1
sysctl net.ipv4.tcp_max_syn_backlog=4096
1.5.4. Đóng kết nối 4 bước (4-way close)
Client Server
| FIN seq=u | (Client hết data gửi)
|------------------------------------>|
| ACK ack=u+1 |
|<------------------------------------|
| ... (server có thể còn gửi data) ...
| FIN seq=v |
|<------------------------------------|
| ACK ack=v+1 |
|------------------------------------>|
| (Client vào TIME_WAIT ~2*MSL) |
TCP là full-duplex nên mỗi chiều đóng độc lập (half-close). TIME_WAIT (2×MSL, MSL thường 30–120s tùy OS) đảm bảo: (1) ACK cuối tới được server, (2) các segment cũ trễ trong mạng hết hạn trước khi tái dùng cặp port. Quá nhiều TIME_WAIT trên server tải cao là vấn đề thực tế (tinh chỉnh tcp_tw_reuse).
1.5.5. State machine TCP đầy đủ (RFC 9293)
CLOSED
| (passive open: LISTEN) | (active open: gửi SYN)
v v
LISTEN SYN_SENT
recv SYN | | recv SYN-ACK / send ACK
send SYN-ACK v
v ESTABLISHED
SYN_RCVD --recv ACK------> |
| (close: send FIN)
┌──────────────────────────────┤
recv FIN/send ACK│ │ send FIN
v v
CLOSE_WAIT FIN_WAIT_1
| app close/send FIN recv ACK | recv FIN+ACK
v v \
LAST_ACK FIN_WAIT_2 CLOSING
| recv ACK | recv FIN | recv ACK
v v send ACK v
CLOSED TIME_WAIT <----------
| (2*MSL timeout)
v
CLOSED
| State | Ý nghĩa |
|---|---|
| LISTEN | Server chờ kết nối |
| SYN_SENT | Client đã gửi SYN |
| SYN_RCVD | Đã nhận SYN, gửi SYN-ACK |
| ESTABLISHED | Kết nối hoạt động, truyền data |
| FIN_WAIT_1/2 | Phía chủ động đóng đã gửi FIN |
| CLOSE_WAIT | Phía bị động nhận FIN, app chưa đóng |
| LAST_ACK | Phía bị động đã gửi FIN, chờ ACK cuối |
| TIME_WAIT | Chờ 2×MSL trước khi đóng hẳn |
ss -tan # xem state TCP (ESTAB, TIME-WAIT, CLOSE-WAIT...)
ss -tanp state syn-recv # phát hiện SYN flood
Bảo mật quét cổng (nmap) dựa vào state machine:
- SYN scan (-sS): gửi SYN; nhận SYN-ACK → open (rồi gửi RST hủy); nhận RST → closed.
- NULL/FIN/Xmas scan: gửi cờ bất thường; theo RFC, port closed trả RST, open im lặng → suy ra trạng thái (bypass một số firewall stateless).
1.5.6. Sliding window, flow control, congestion control
Flow control (kiểm soát luồng): bên nhận quảng bá Window Size (kết hợp Window Scale) = lượng byte còn chỗ trong buffer. Bên gửi không gửi quá Window. Nếu buffer đầy → quảng bá window=0 → bên gửi dừng, định kỳ gửi window probe.
Sliding window: byte stream chia 4 vùng: (1) đã gửi & ack, (2) đã gửi chưa ack, (3) chưa gửi nhưng trong window, (4) ngoài window. Khi ack tới, "cửa sổ" trượt sang phải.
Congestion control (kiểm soát tắc nghẽn) — thuật toán cổ điển:
- Slow start: cwnd bắt đầu = 1–10 MSS, tăng gấp đôi mỗi RTT cho tới ssthresh.
- Congestion avoidance: sau ssthresh, tăng tuyến tính (+1 MSS/RTT).
- Fast retransmit: nhận 3 duplicate ACK → gửi lại ngay không chờ timeout.
- Fast recovery: giảm cwnd nửa thay vì về 1.
- Hiện đại: CUBIC (mặc định Linux), BBR (Google, đo bandwidth×RTT).
sysctl net.ipv4.tcp_congestion_control # xem thuật toán
ss -ti # xem cwnd, rtt, retrans per-socket
Retransmission: dựa RTO (Retransmission Timeout) tính từ RTT đo được (Jacobson/Karels: RTO = SRTT + 4*RTTVAR). Hết RTO mà chưa ack → gửi lại, RTO nhân đôi (exponential backoff).
1.6. Cổng (port) phổ biến
| Port | Protocol | Dịch vụ | Ghi chú bảo mật |
|---|---|---|---|
| 20/21 | TCP | FTP data/control | Plaintext, dùng FTPS/SFTP |
| 22 | TCP | SSH | Quản trị từ xa mã hóa |
| 23 | TCP | Telnet | Plaintext — không dùng |
| 25 | TCP | SMTP | Mail, kiểm relay mở |
| 53 | TCP/UDP | DNS | UDP cho query, TCP cho zone transfer/lớn |
| 67/68 | UDP | DHCP server/client | DORA |
| 80 | TCP | HTTP | Plaintext |
| 110/143 | TCP | POP3/IMAP | Mail client |
| 123 | UDP | NTP | Amplification DDoS |
| 161/162 | UDP | SNMP | Community string mặc định nguy hiểm |
| 389/636 | TCP | LDAP/LDAPS | Directory |
| 443 | TCP/UDP | HTTPS / QUIC(UDP) | TLS |
| 445 | TCP | SMB | EternalBlue, không expose ra Internet |
| 3306 | TCP | MySQL | DB không nên public |
| 3389 | TCP | RDP | Brute-force, BlueKeep |
| 5432 | TCP | PostgreSQL | DB |
| 6379 | TCP | Redis | Không auth mặc định — nguy hiểm |
Dải port: 0–1023 well-known (cần quyền root để bind trên Linux), 1024–49151 registered, 49152–65535 ephemeral/dynamic (client tự cấp).
1.7. Tầng 7 — DNS, DHCP, HTTP, TLS
1.7.1. DNS — Domain Name System (RFC 1035)
Message header DNS — 12 byte:
| Trường | Kích thước | Ý nghĩa | Ví dụ |
|---|---|---|---|
| Transaction ID | 16 bit | Khớp query/response | 0x1a2b |
| Flags | 16 bit | QR(1b),Opcode(4b),AA,TC,RD,RA,Z,RCODE(4b) | xem dưới |
| QDCOUNT | 16 bit | Số câu hỏi | 1 |
| ANCOUNT | 16 bit | Số bản ghi answer | 2 |
| NSCOUNT | 16 bit | Số bản ghi authority | 0 |
| ARCOUNT | 16 bit | Số bản ghi additional | 0 |
Trường Flags (16 bit) chi tiết:
| Bit | Tên | Ý nghĩa |
|---|---|---|
| QR (1) | Query/Response | 0=query, 1=response |
| Opcode (4) | 0=standard query | |
| AA (1) | Authoritative Answer | server có thẩm quyền |
| TC (1) | Truncated | response bị cắt (chuyển TCP) |
| RD (1) | Recursion Desired | client muốn đệ quy |
| RA (1) | Recursion Available | server hỗ trợ đệ quy |
| Z (3) | reserved/AD/CD | trong DNSSEC: AD=Authenticated Data, CD=Checking Disabled |
| RCODE (4) | Response code | 0=NOERROR,2=SERVFAIL,3=NXDOMAIN |
Question section: QNAME (chuỗi label dạng [len][label]...0, ví dụ 3www7example3com0), QTYPE (2B, A=1, AAAA=28, MX=15, CNAME=5, NS=2, TXT=16, SOA=6, PTR=12), QCLASS (2B, IN=1).
Resource Record (answer): NAME(thường con trỏ nén 2B 0xc00c), TYPE(2B), CLASS(2B), TTL(4B), RDLENGTH(2B), RDATA(thay đổi — với A là 4 byte IPv4).
Recursive vs iterative:
- Recursive resolver (8.8.8.8): client hỏi một lần, resolver tự đi hỏi hộ và trả kết quả cuối.
- Iterative: resolver hỏi root → TLD (.com) → authoritative, mỗi bước nhận referral tới server tiếp theo.
dig +trace example.com A # xem toàn bộ chuỗi iterative từ root
dig @1.1.1.1 example.com MX
dig -x 192.0.2.10 # reverse (PTR)
sudo tcpdump -i eth0 -nn 'udp port 53'
Output dig mẫu (đã chú thích):
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 6789
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; ANSWER SECTION:
example.com. 3600 IN A 192.0.2.10
DNSSEC: thêm bản ghi RRSIG (chữ ký), DNSKEY (khóa công khai), DS (delegation signer), NSEC/NSEC3 (chứng minh không tồn tại). Bit AD (Authenticated Data) trong flags báo resolver đã xác thực chữ ký. Mục tiêu: chống cache poisoning/spoofing bằng chữ ký số (không mã hóa nội dung).
Bảo mật — DNS tunneling: mã hóa dữ liệu exfil vào QNAME (base64data.attacker.com) hoặc TXT records → vượt firewall vì DNS hiếm khi bị chặn. Phát hiện: QNAME bất thường dài/entropy cao, lượng query TXT lớn.
Cache poisoning (Kaminsky): đoán Transaction ID (16 bit) + source port để chèn answer giả trước answer thật. Phòng: random source port (entropy lớn hơn), DNSSEC, DNS-over-TLS/HTTPS.
1.7.2. DHCP — DORA (RFC 2131)
Bốn bước cấp IP động (UDP, server 67, client 68):
Client (0.0.0.0) DHCP Server
| 1. DISCOVER (broadcast ff:ff..) | "Có server nào không?"
|--------------------------------------->|
| 2. OFFER (đề nghị IP, lease, gateway) |
|<---------------------------------------|
| 3. REQUEST (xin chính IP được offer) |
|--------------------------------------->|
| 4. ACK (xác nhận, đóng dấu lease) |
|<---------------------------------------|
| Bước | Loại | Src IP | Dst IP | Mục đích |
|---|---|---|---|---|
| D | DISCOVER | 0.0.0.0 | 255.255.255.255 | Client tìm server (chưa có IP) |
| O | OFFER | server IP | broadcast/unicast | Server đề nghị IP |
| R | REQUEST | 0.0.0.0 | 255.255.255.255 | Client chấp nhận (broadcast để các server khác biết) |
| A | ACK | server IP | client | Xác nhận, cấp lease + options (DNS, gateway, mask) |
Các option quan trọng (DHCP options trong packet BOOTP): Option 53 (message type), 51 (lease time), 1 (subnet mask), 3 (router/gateway), 6 (DNS), 50 (requested IP).
sudo dhclient -v eth0
sudo tcpdump -i eth0 -nn 'udp port 67 or udp port 68'
Bảo mật: Rogue DHCP server cấp gateway/DNS giả → MITM. DHCP starvation (yersinia) bơm DISCOVER cạn pool. Phòng: DHCP snooping trên switch (chỉ trust port nối server hợp lệ).
1.7.3. HTTP — request/response raw
Request (HTTP/1.1):
GET /index.html HTTP/1.1\r\n
Host: example.com\r\n
User-Agent: curl/8.0\r\n
Accept: */*\r\n
\r\n
Cấu trúc: Method SP Request-URI SP HTTP-Version CRLF, sau đó các header Name: Value CRLF, một dòng trống CRLF, rồi body (nếu có). CRLF = \r\n (0x0D 0x0A).
Response:
HTTP/1.1 200 OK\r\n
Content-Type: text/html; charset=UTF-8\r\n
Content-Length: 138\r\n
Connection: keep-alive\r\n
\r\n
<html>...</html>
Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase. Mã: 1xx info, 2xx success, 3xx redirect, 4xx client error, 5xx server error.
# Gửi raw request không che giấu chi tiết:
printf 'GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n' \
| ncat example.com 80
curl -v http://example.com/ # -v in cả request/response headers
Bảo mật: header an toàn — Strict-Transport-Security, Content-Security-Policy, X-Content-Type-Options: nosniff. Tấn công: request smuggling (mâu thuẫn Content-Length vs Transfer-Encoding), host header injection.
1.7.4. TLS — 1.2 và 1.3
Phần nền tảng mật mã đứng sau TLS/PKI (trao đổi khóa, AEAD, chứng chỉ X.509) được trình bày tại Chương 4 — Mật mã & Nền tảng bảo mật.
TLS Record layer — header 5 byte (bọc mọi message TLS):
| Trường | Kích thước | Ý nghĩa | Ví dụ |
|---|---|---|---|
| Content Type | 1 byte | 20=ChangeCipherSpec,21=Alert,22=Handshake,23=Application Data | 22 |
| Version | 2 byte | 0x0303=TLS1.2 (1.3 giả là 1.2 ở record để tương thích) |
0x0303 |
| Length | 2 byte | Độ dài payload (≤16384) | 0x0200 |
TLS 1.2 handshake — từng message:
Client Server
| 1. ClientHello (random_c, cipher list, SNI, sessionID)
|------------------------------------------------->|
| 2. ServerHello (random_s, cipher chosen) |
| Certificate (chuỗi X.509) |
| ServerKeyExchange (params ECDHE) |
| ServerHelloDone |
|<-------------------------------------------------|
| 3. ClientKeyExchange (ECDHE public) |
| ChangeCipherSpec |
| Finished (mã hóa) |
|------------------------------------------------->|
| 4. ChangeCipherSpec |
| Finished (mã hóa) |
|<-------------------------------------------------|
(2 RTT trước khi gửi application data)
TLS 1.3 handshake — rút gọn còn 1 RTT (RFC 8446):
Client Server
| ClientHello (+ key_share, supported_versions, SNI)
|------------------------------------------------->|
| ServerHello (+ key_share) |
| {EncryptedExtensions} |
| {Certificate}{CertificateVerify} |
| {Finished} |
|<-------------------------------------------------|
| {Finished} |
|------------------------------------------------->|
(1 RTT; 0-RTT nếu dùng PSK/resumption)
Khác biệt TLS 1.3: bỏ ciphersuite yếu (RSA key exchange tĩnh, RC4, CBC, SHA-1), bắt buộc forward secrecy (ECDHE), mã hóa cả phần lớn handshake (Certificate được mã hóa), chỉ còn các ciphersuite AEAD (vd TLS_AES_128_GCM_SHA256).
X.509 certificate — các trường chính:
| Trường | Ý nghĩa | Ví dụ |
|---|---|---|
| Version | v3 | 2 (=v3) |
| Serial Number | định danh duy nhất từ CA | 0x0a1b... |
| Signature Algorithm | thuật toán ký | sha256WithRSAEncryption |
| Issuer | DN của CA cấp | CN=R11, O=Let's Encrypt |
| Validity | notBefore / notAfter | 2026-01-01 .. 2026-04-01 |
| Subject | DN chủ thể | CN=example.com |
| Subject Public Key Info | thuật toán + khóa công khai | RSA 2048 / EC P-256 |
| Extensions | SAN, Key Usage, EKU, Basic Constraints, AIA, CRL/OCSP | SAN: example.com, www.example.com |
| Signature | chữ ký của CA trên TBS | … |
# Xem handshake và cert thật:
openssl s_client -connect example.com:443 -servername example.com -showcerts </dev/null
echo | openssl s_client -connect example.com:443 2>/dev/null \
| openssl x509 -noout -text -dates -subject -issuer -ext subjectAltName
# Wireshark filter cho handshake:
# tls.handshake.type == 1 (ClientHello)
# tls.handshake.type == 2 (ServerHello)
# tls.handshake.extensions_server_name == "example.com"
Bảo mật: SNI (Server Name Indication) lộ tên miền dù mã hóa → ECH (Encrypted Client Hello) khắc phục. Kiểm chain trust, revocation (OCSP stapling), cipher downgrade, Heartbleed (CVE-2014-0160 — đọc bộ nhớ qua heartbeat).
1.8. Firewall, DMZ, công cụ phân tích gói
1.8.1. Firewall stateless vs stateful
| Tiêu chí | Stateless (packet filter) | Stateful |
|---|---|---|
| Quyết định dựa trên | Từng packet riêng lẻ (IP/port/flags) | Trạng thái kết nối (conntrack) |
| Cho phép gói trả về | Phải mở rule cả hai chiều thủ công | Tự động (RELATED,ESTABLISHED) |
| Chống spoof flags | Yếu | Tốt (chỉ chấp nhận packet hợp state) |
| Tải bộ nhớ | Thấp | Cao (giữ bảng kết nối) |
Ví dụ stateful với iptables:
# Mặc định DROP, chỉ cho SSH inbound và mọi outbound đã thiết lập
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT
iptables -P OUTPUT ACCEPT
-m conntrack --ctstate ESTABLISHED,RELATED chính là điểm "stateful": kernel theo dõi kết nối nên gói trả về (vd response của SSH) tự được chấp nhận mà không cần rule riêng.
1.8.2. DMZ (Demilitarized Zone)
DMZ là vùng mạng đệm giữa Internet và LAN nội bộ, chứa server cần truy cập từ ngoài (web, mail). Kiến trúc hai firewall:
Internet --[FW ngoài]-- DMZ (web, mail) --[FW trong]-- LAN nội bộ
Nguyên tắc: Internet → DMZ được phép (cổng cụ thể); DMZ → LAN bị hạn chế tối đa; nếu server DMZ bị chiếm, attacker vẫn khó pivot vào LAN.
1.8.3. tcpdump / Wireshark — bộ lọc thực tế
tcpdump (BPF filter — capture filter):
# Bắt SYN-only (phát hiện scan): cờ SYN bật, ACK tắt
sudo tcpdump -i eth0 'tcp[tcpflags] & (tcp-syn|tcp-ack) == tcp-syn'
# Bắt HTTP GET (byte đầu payload = 'G','E','T',' ')
sudo tcpdump -i eth0 'tcp port 80 and tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x47455420'
# DNS query tới một domain, ghi ra file pcap để mở bằng Wireshark
sudo tcpdump -i eth0 -nn -w /tmp/dns.pcap 'udp port 53'
# Một host, không phân giải tên, in payload hex/ascii, 100 gói
sudo tcpdump -i eth0 -nn -X host 10.0.0.50 -c 100
Tham số: -i interface, -nn không phân giải tên/cổng, -e in L2 header, -X hex+ascii, -w ghi pcap, -c số gói, -s 0 capture full packet.
Wireshark (display filter — khác cú pháp BPF):
ip.addr == 10.0.0.50
tcp.flags.syn == 1 && tcp.flags.ack == 0 # SYN scan
tcp.analysis.retransmission # phát hiện mất gói
http.request.method == "POST"
dns.qry.name contains "example"
tls.handshake.type == 1 # ClientHello
tcp.port == 443 && tls.record.content_type == 23 # app data đã mã hóa
ip.ttl < 5 # traceroute / hop thấp bất thường
Quy trình điều tra điển hình: bắt bằng tcpdump trên server không có GUI (-w file.pcap), chuyển về máy phân tích, mở Wireshark, dùng "Follow TCP Stream" để ráp lại phiên, "Statistics → Conversations" để thấy top talker.
1.9. Tổng kết các con số cần thuộc
| Hạng mục | Giá trị |
|---|---|
| Ethernet header / FCS / MTU / frame max | 14B / 4B / 1500B / 1518B (1522 với VLAN) |
| Payload Ethernet min/max | 46B / 1500B |
| 802.1Q tag | 4B (TPID 16b + PCP 3b + DEI 1b + VID 12b) |
| ARP packet (IPv4) | 28B |
| IPv4 header min/max | 20B / 60B |
| IPv6 header | 40B cố định, MTU min 1280B |
| TCP header min / UDP header | 20B / 8B |
| ICMP header | 8B |
| DNS header | 12B |
| TLS record header | 5B |
| IPv4 Total Length max | 65535B |
| Port ranges | 0–1023 / 1024–49151 / 49152–65535 |
Các con số RFC trên là chuẩn ổn định. Với các chi tiết phụ thuộc cài đặt (MSL, kích thước backlog, thuật toán congestion mặc định) hãy kiểm chứng trên hệ thống cụ thể bằng
sysctl/ssvì giá trị thay đổi theo OS và phiên bản kernel.
Ghi chú của mình
Khu vực ghi chú cá nhân: những điểm từng hiểu sai, phần còn đang tìm hiểu, hoặc kinh nghiệm rút ra khi thực hành — cập nhật dần.
- Đọc access log là cách nhanh nhất nhận diện scanner. Chỉ cần lướt access.log của một máy web phơi Internet là thấy chân dung một con scanner tự động: hàng trăm request/vài phút từ một IP, path toàn
/.env,/.git/config,/wp-login.php,/.ssh/id_rsa, kèm biến thể path traversal../,....//, và cả%252e%252e(double-encoding — nó encode dấu.hai lần để né bộ lọc naïve). User-agent xoay liên tục, thỉnh thoảng giả referer của Bing/Google cho giống bot hợp lệ. Traffic người thật gần như không bao giờ có hình dạng này. - Nhìn status code để biết "thủng hay chưa". Mẹo thực dụng mình hay dùng: lọc log lấy đúng những request của IP nghi ngờ mà server trả 2xx — nếu toàn
301/400/404thì bị quét nhưng chưa lấy được gì; xuất hiện200ở một path nhạy cảm mới là lúc phải báo động. Số lượng request lớn tự nó chưa phải sự cố; kết quả mới là. - Một điểm từng hiểu nhầm: mình từng tưởng chặn pattern
../ngay ở reverse proxy là đủ chống traversal. Thực tế nginx chuẩn hoá URI trước khi match location, nên chặn theo chuỗi..//%2e%2ekhông đáng tin; chặn theo tên tệp nhạy cảm (\.env,id_rsa,\.git) mới bắt được đa số scan, còn traversal triệt để thì cần WAF (ModSecurity + OWASP CRS). Chi tiết vận hành phần này mình để ở chương về hạ tầng/hardening.