Hành trình một lần mở trang: từ HTTP chữ rõ đến HTTPS
Câu hỏi xuyên suốt: một thành viên mở trang đóng lệ phí của câu lạc bộ. Trên đường từ trình duyệt đến máy chủ, ai nhìn thấy được gì, ai có thể sửa gì, và ta chặn bằng cách nào?
Thời lượng: khoảng 2 giờ 20 phút (giảng và thực hành xen kẽ; nên chia hai buổi: phần A–B rồi phần C–D; 11 bài tập, bài cuối làm ở nhà)
Mạch bài: một câu hỏi, bốn phần
5 phútBài 5 cho biết mỗi kết nối có IP và port ở hai đầu. Bài này đi tiếp với một tình huống cụ thể:
Để trả lời, bài đi theo thứ tự "nhìn vấn đề trước, tìm cách chặn sau":
| Phần | Việc làm | Trả lời câu hỏi nào | Thời gian |
|---|---|---|---|
| A. Nội dung | Đọc HTTP, tự dựng server và bắt gói trong máy | Dữ liệu gửi đi trông thế nào? (kết quả: chữ rõ, ai thấy cũng đọc được) | 40 phút |
| B. Đường đi | DNS, router và NAT, firewall, TCP, quét mạng nhà | Dữ liệu đi qua những điểm nào, mỗi điểm thấy gì và có thể làm gì? | 45 phút |
| C. Bảo vệ | TLS và HTTPS, chứng chỉ, tự chạy server HTTPS | Làm sao biến chữ rõ thành chữ mã và chắc rằng đang nói đúng máy chủ? | 35 phút |
| D. Chẩn đoán | Tìm lớp bị lỗi, rà soát website | Khi hỏng, lỗi ở lớp nào? Website của mình đã đủ các lớp chưa? | 15 phút |
Cần chuẩn bị
- Python 3.8 trở lên (chạy web server thử), trình duyệt, terminal.
- Wireshark đã cài và cấp quyền bắt gói. Nếu chưa có, vẫn làm được phần lớn bài tập bằng cách đọc dữ liệu mẫu.
curl(có sẵn trên macOS, Linux; Windows dùngcurl.exe).openssl(Lab 2, tạo chứng chỉ thử; có sẵn trên macOS, Linux; Windows dùng bản đi kèm Git for Windows).
example.com.A1. HTTP: nội dung mà trình duyệt gửi đi
8 phútlà ngôn ngữ giữa trình duyệt và website. Trình duyệt gửi một , server trả một . Khi Lan bấm "Đóng phí", trình duyệt gửi khoảng như sau (đã trình bày lại cho dễ đọc):
POST /dong-phi HTTP/1.1
Host: clb.example
Cookie: phien=a1b2c3d4
Content-Type: application/x-www-form-urlencoded
Content-Length: 29
ten=Lan&so_tien=200000&ghi=ok- Dòng đầu: (
POST= gửi dữ liệu lên;GET= lấy tài nguyên; cònPUT,DELETE), đường dẫn/dong-phitrên server, và phiên bản giao thức. - Các dòng
Tên: giá trịlà .Hostlà tên đích.Cookiemang mã phiên đăng nhập (bài 3).Content-Lengthlà số byte của body. - Dòng trống kết thúc header. Phần sau đó là body: dữ liệu Lan nhập.
Server trả lời bằng một response:
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 14
<h1>Hello</h1>Dòng đầu có . Bảng mã thường gặp:
| Mã | Nghĩa | Không được suy ra |
|---|---|---|
| 200 | Thành công | Dữ liệu chắc chắn đúng |
| 301 / 302 | Chuyển hướng sang URL khác | URL mới là đáng tin |
| 403 | Từ chối vì không đủ quyền | Mật khẩu sai |
| 404 | Không tìm thấy tài nguyên | Mạng hỏng |
| 500 | Lỗi bên trong server | Bị tấn công |
Một response chứa số tài khoản sai vẫn là 200: HTTP chỉ nói giao thức chạy ổn, tính đúng của dữ liệu là chuyện toàn vẹn (bài 1).
BÀI TẬP 1 · 5 PHÚT
Đọc một request
Dùng request POST ở trên và trả lời:
- Method và đường dẫn là gì?
- Phần nào là dữ liệu Lan nhập, phần nào là bằng chứng "đã đăng nhập"?
Content-Length: 29đếm cái gì? Hãy đếm thử chuỗiten=Lan&so_tien=200000&ghi=ok.- Nếu request này đi qua HTTP, người ở router nhà Lan đọc được những gì và làm gì được với cookie?
Xem đáp án
- Method
POST, đường dẫn/dong-phi. - Dữ liệu nhập là body (
ten,so_tien,ghi). Bằng chứng đăng nhập là headerCookie: phien=a1b2c3d4. - Số byte của body. Chuỗi có đúng 29 ký tự ASCII (7 + 1 + 14 + 1 + 6) nên 29 byte.
- Đọc được toàn bộ: tên, số tiền, cookie. Với cookie còn hiệu lực, người đó gửi request giả danh Lan mà không cần mật khẩu hay MFA. Đây là đánh cắp phiên (session hijacking) đã học ở bài 3.
A2. Lab 1: tự bắt gói HTTP trong máy mình
30 phútBài giảng đến đây đã nói HTTP là chữ rõ. Lab này để bạn tự chứng minh điều đó trên máy mình: tự tạo một trang web, tự chạy web server, tự gửi request, rồi tự bắt gói bằng Wireshark để đọc nguyên văn nội dung. Mọi thứ chạy trong máy bạn, không đụng đến mạng ngoài. Địa chỉ 127.0.0.1 luôn trỏ về chính máy, nên gói không rời khỏi máy; dùng của Wireshark để xem các gói đó.
network-lab với file index.html; (2) một web server chạy ở port 8000; (3) một lần mở trang bằng trình duyệt và bằng curl; (4) một bản bắt gói trong đó đọc được cookie và dữ liệu form dưới dạng chữ rõ.Bước 0. Kiểm tra máy đã có đủ công cụ chưa
Bạn cần ba thứ: terminal (cửa sổ gõ lệnh), Python 3 (để chạy web server) và curl (để gửi request từ dòng lệnh). Mở terminal như sau:
| Hệ điều hành | Mở terminal |
|---|---|
| macOS | Nhấn ⌘ + Space, gõ Terminal, nhấn Enter |
| Windows | Bấm Start, gõ PowerShell, chọn Windows PowerShell |
| Linux | Nhấn Ctrl + Alt + T (hoặc tìm Terminal trong menu ứng dụng) |
Gõ lệnh kiểm tra rồi nhấn Enter:
python3 --version
curl --versionpy --version
curl.exe --versionpython3 --version
curl --version| Phần | Ý nghĩa |
|---|---|
python3 --version | Hỏi máy xem Python 3 có không và phiên bản nào. macOS và Linux dùng tên python3. |
py --version | Trên Windows, py là trình khởi chạy Python do bộ cài python.org cung cấp. Dùng py thay cho python3. |
curl.exe --version | Trên Windows luôn gõ cả .exe. PowerShell có sẵn tên curl nhưng trỏ tới lệnh khác nên cho kết quả không như mong đợi. |
Python 3.9.6
curl 8.7.1 (x86_64-apple-darwin26.0) ...Python từ 3.8 trở lên là đủ. Nếu báo "command not found" hoặc "not recognized": macOS chạy xcode-select --install hoặc tải Python tại python.org; Windows tải bộ cài tại python.org và tick ô Add python.exe to PATH trước khi cài; Linux chạy sudo apt install python3 curl. Cài xong, đóng và mở lại terminal rồi kiểm tra lại.
Wireshark tải tại wireshark.org. Lúc cài: macOS cài xong thường còn phải cài thêm ChmodBPF để được phép bắt gói (hướng dẫn ở bước 3, mục 3a); Windows giữ tùy chọn cài Npcap và tick hỗ trợ loopback; Linux cho phép người dùng thường bắt gói khi được hỏi, hoặc chạy Wireshark bằng sudo.
Bước 1. Tạo thư mục làm việc và file index.html
Web server phục vụ file ở thư mục mà bạn chạy lệnh, và cho phép đọc mọi file trong đó. Vì vậy hãy tạo một thư mục trống riêng, đừng chạy server ở thư mục Home hay Documents (nơi có dữ liệu cá nhân). Trong terminal:
mkdir ~/network-lab
cd ~/network-lab
pwdmkdir $HOME\network-lab
cd $HOME\network-lab
pwdmkdir ~/network-lab
cd ~/network-lab
pwd| Phần | Ý nghĩa |
|---|---|
mkdir | Tạo thư mục mới (make directory). Tên thư mục là network-lab. |
~ hoặc $HOME | Thư mục cá nhân của bạn. Vậy thư mục mới nằm ngay trong thư mục cá nhân. |
cd | Đi vào một thư mục (change directory). Từ lúc này mọi lệnh chạy "tại" network-lab. |
pwd | In ra đường dẫn thư mục hiện tại. Kết quả phải kết thúc bằng network-lab, ví dụ /Users/ten-ban/network-lab. |
Tiếp theo tạo file index.html, một trang web chỉ có một dòng tiêu đề (không dấu để tránh lỗi font khi xem gói):
echo '<h1>Cau lac bo - Lich sinh hoat</h1>' > index.html
ls -l
cat index.htmlSet-Content -Path index.html -Value '<h1>Cau lac bo - Lich sinh hoat</h1>' -Encoding ascii
dir
type index.htmlecho '<h1>Cau lac bo - Lich sinh hoat</h1>' > index.html
ls -l
cat index.html| Phần | Ý nghĩa |
|---|---|
echo '...' > index.html | echo in chuỗi ra; dấu > chuyển phần in ra đó vào file index.html thay vì màn hình. File chưa có thì được tạo. |
Set-Content -Path ... -Value ... | Lệnh PowerShell ghi giá trị vào file. -Encoding ascii giữ file là chữ thường, không có ký tự lạ ở đầu file. |
ls -l / dir | Liệt kê file trong thư mục. Phải thấy index.html, cỡ 37 byte. |
cat / type | In nội dung file ra màn hình, để chắc rằng file đúng như ý. |
<h1>Cau lac bo - Lich sinh hoat</h1>index.html.txt và server báo 404; bật File name extensions trong Explorer (View → Show) để nhìn thấy đuôi thật. (2) macOS TextEdit mặc định lưu dạng RTF; vào Format → Make Plain Text (⇧⌘T) trước khi lưu. (3) Lưu file vào đúng thư mục network-lab.Bước 2. Chạy web server và mở trang
Python có sẵn một web server nhỏ. Gõ lệnh sau trong thư mục network-lab (vẫn cửa sổ terminal vừa dùng; gọi nó là Terminal A):
python3 -m http.server 8000 --bind 127.0.0.1py -m http.server 8000 --bind 127.0.0.1python3 -m http.server 8000 --bind 127.0.0.1| Phần | Ý nghĩa |
|---|---|
python3 -m http.server | -m nghĩa là chạy một module có sẵn của Python. http.server là module web server tĩnh: nó trả file trong thư mục hiện hành cho ai hỏi. |
8000 | Port mà server lắng nghe (bài 5). Chọn 8000 vì port dưới 1024 cần quyền quản trị. |
--bind 127.0.0.1 | Chỉ nghe trên địa chỉ loopback, nghĩa là chỉ máy này truy cập được. Không có tham số này server nghe ở mọi địa chỉ và máy khác cùng Wi-Fi cũng vào được. Thói quen tốt cho dịch vụ thử nghiệm. |
Serving HTTP on 127.0.0.1 port 8000 (http://127.0.0.1:8000/) ...Terminal A đứng yên, không trả về dấu nhắc lệnh. Đó là bình thường: server đang chạy và chờ kết nối. Đừng đóng cửa sổ này; muốn dừng thì nhấn Ctrl + C. Từ giờ, mọi lệnh khác gõ ở một cửa sổ mới (Terminal B): macOS nhấn ⌘ + T để mở tab mới, Windows mở thêm một PowerShell, Linux nhấn Ctrl + Shift + T. Nhớ cd vào network-lab (với macOS/Linux là cd ~/network-lab) ở cửa sổ mới.
Mở trình duyệt, vào http://127.0.0.1:8000/. Bạn thấy dòng tiêu đề "Cau lac bo - Lich sinh hoat". Quay lại Terminal A, server đã in nhật ký của lần truy cập:
127.0.0.1 - - [19/Oct/2026 20:05:38] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [19/Oct/2026 20:05:38] code 404, message File not found
127.0.0.1 - - [19/Oct/2026 20:05:38] "GET /favicon.ico HTTP/1.1" 404 -| Phần | Ý nghĩa |
|---|---|
127.0.0.1 | Địa chỉ của client (ở đây là chính máy bạn). |
[19/Oct/2026 ...] | Thời điểm server nhận request. |
"GET / HTTP/1.1" | Dòng đầu của request (phần A1): method GET, đường dẫn / và phiên bản giao thức. |
200 | Mã trạng thái: server trả trang thành công. |
/favicon.ico ... 404 | Trình duyệt tự xin thêm icon của tab; thư mục không có file đó nên server trả 404. Không phải lỗi của bạn. |
Bây giờ gửi cùng request đó bằng curl ở Terminal B, thêm -i để in cả phần header của response:
curl -i http://127.0.0.1:8000/HTTP/1.0 200 OK
Server: SimpleHTTP/0.6 Python/3.9.6
Content-type: text/html
Content-Length: 37
<h1>Cau lac bo - Lich sinh hoat</h1>Đây chính là response ở phần A1: dòng trạng thái, các header, dòng trống, rồi body. Server Python này trả HTTP/1.0 dù curl gửi HTTP/1.1; hai bên chỉ cần tương thích.
Gặp lỗi?
| Dấu hiệu | Nguyên nhân thường gặp | Cách sửa |
|---|---|---|
command not found hoặc not recognized | Chưa cài Python hoặc gõ sai tên lệnh | Làm lại bước 0. Windows dùng py, macOS/Linux dùng python3 |
Address already in use | Port 8000 đang bị chương trình khác (hoặc server cũ) giữ | Tắt server cũ bằng Ctrl+C, hoặc đổi sang port khác, ví dụ 8001, và sửa URL cho khớp |
| Trình duyệt báo "Can't connect" / "refused" | Server chưa chạy, đã bị tắt, hoặc sai port | Nhìn Terminal A xem còn dòng "Serving HTTP" không; kiểm tra URL có đúng :8000 |
| Trang hiện "Directory listing" thay vì tiêu đề | Chạy server sai thư mục, hoặc file tên khác index.html | Ctrl+C, cd đúng vào network-lab, kiểm tra tên file bằng ls/dir |
| Trang báo 404 Not Found | Thư mục có file nhưng sai tên, thường là index.html.txt | Đổi tên file, xem lại ghi chú về Notepad ở bước 1 |
Bước 3. Làm quen với Wireshark (làm một lần, dùng cho cả hai lab)
Wireshark là chương trình nghe lén có phép trên máy của chính bạn: nó chép lại mọi gói tin đi qua một giao diện mạng và trình bày chúng thành bảng để đọc. Phần này chỉ để bạn biết bấm cái gì, gõ vào đâu, nút nào làm gì; các thao tác bắt gói thật nằm ở bước 4. Nội dung theo Wireshark 4.x trên macOS; Windows và Linux gần như giống (phím Ctrl thay cho ⌘).
3a. Cấp quyền bắt gói (lỗi "You don't have permission to capture")
Lần đầu mở Wireshark trên macOS, bạn có thể thấy khung vàng nâu ở màn hình chào: "You don't have permission to capture on local interfaces. You can fix this by installing ChmodBPF." Lý do: macOS chỉ cho người quản trị đọc thiết bị bắt gói (/dev/bpf*). ChmodBPF là một thành phần nhỏ đi kèm Wireshark, cho phép tài khoản của bạn đọc thiết bị đó mà không phải chạy Wireshark bằng quyền root (chạy cả chương trình bằng root là thói quen không an toàn). Cách làm:
- Bấm vào liên kết installing ChmodBPF trong khung vàng. Nếu không thấy liên kết, mở Finder, vào
/Applications/Wireshark.app/Contents/Resources/Extras/(chuột phải Wireshark → Show Package Contents để đi vào) và nhấp đúpInstall ChmodBPF.pkg. - Trong bộ cài bấm Continue → Install, nhập mật khẩu máy khi macOS hỏi, đợi báo "The installation was successful".
- Thoát hẳn Wireshark (
⌘ + Q, không chỉ đóng cửa sổ) rồi mở lại. Khung vàng biến mất, mỗi giao diện trong danh sách có thêm đường sóng nhỏ. Nếu vẫn báo lỗi: đăng xuất rồi đăng nhập lại, hoặc khởi động lại máy, vì quyền nhóm mới chỉ có hiệu lực cho phiên đăng nhập mới.
| Hệ điều hành | Cách cấp quyền |
|---|---|
| macOS | ChmodBPF như trên |
| Windows | Bộ cài Npcap đã lo việc này. Gặp lỗi thì cài lại Npcap, tick tùy chọn hỗ trợ loopback, rồi chạy Wireshark lần đầu bằng "Run as administrator" để kiểm tra |
| Linux (Ubuntu/Debian) | sudo dpkg-reconfigure wireshark-common chọn Yes, rồi sudo usermod -aG wireshark $USER, sau đó đăng xuất và đăng nhập lại |
3b. Màn hình chào: chọn giao diện để bắt
Khi mở Wireshark bạn thấy ba thứ chính ở giữa màn hình:
| Phần | Ý nghĩa |
|---|---|
Ô "Enter a capture filter …" | Bộ lọc bắt gói (capture filter): lọc ngay lúc thu, gói không khớp bị bỏ luôn, không lấy lại được. Cú pháp riêng, ví dụ port 8000. Trong bài này để trống cho an toàn: thu hết rồi lọc sau. |
Nút "All interfaces shown" | Chọn nhóm giao diện hiển thị (tất cả, hoặc chỉ giao diện có dữ liệu). Cứ để mặc định. |
Danh sách giao diện | Mỗi dòng là một "cửa" mạng. Đường sóng nhỏ bên phải tên cho biết đang có lưu lượng. Nhấp đúp vào dòng để bắt đầu bắt gói ngay trên giao diện đó. Hoặc nhấp một lần để chọn rồi bấm nút vây cá mập xanh ở thanh công cụ. |
Danh sách trên Mac có rất nhiều tên lạ vì macOS tạo sẵn nhiều giao diện cho tính năng hệ thống. Bảng dưới giải thích từng nhóm (tên và số có thể khác theo máy bạn). Với lab chỉ cần hai dòng in đậm; còn lại bạn có thể bỏ qua.
| Tên giao diện | Là gì | Có cần cho lab? |
|---|---|---|
Loopback: lo0 (Linux: lo) | Giao diện nội bộ 127.0.0.1: gói từ máy gửi thẳng cho chính máy, không ra khỏi máy | Có: Lab 1 và Lab 2, vì server và client cùng nằm trong máy bạn |
Wi-Fi: en0 | Card Wi-Fi thật. Mọi gói đi ra router, Internet đều qua đây. Đường sóng nhỏ bên phải là lưu lượng đang chạy | Chỉ ở bước tùy chọn của Lab 2 (truy cập example.com). Không dùng để bắt gói tới 127.0.0.1 |
utun0 … utun4 | Đường hầm phần mềm (user tunnel): VPN, iCloud Private Relay và một số dịch vụ hệ thống | Không. Chỉ bắt khi bạn đang tìm hiểu lưu lượng VPN |
awdl0 | Apple Wireless Direct Link: kết nối trực tiếp giữa thiết bị Apple (AirDrop, AirPlay, Handoff, Sidecar) | Không |
llw0 | Low Latency WLAN: giao diện đi cặp với awdl0 cho các tính năng trên | Không |
anpi0 … anpi2 | Giao diện nội bộ do Mac chip Apple tạo, gắn với cổng và phụ kiện của hệ thống; thường không có lưu lượng | Không |
Ethernet Adapter (en4/en5/en6) | Card Ethernet. Có thể là dây mạng qua bộ chuyển USB hoặc Thunderbolt, hoặc giao diện ảo do phần mềm máy ảo, chia sẻ mạng USB từ điện thoại tạo ra | Không, trừ khi bạn cắm dây mạng thật và muốn bắt trên đó |
Thunderbolt 1 … 3 (en1/en2/en3) | Ba cổng Thunderbolt có thể dùng để nối mạng giữa hai máy qua cáp Thunderbolt | Không |
Thunderbolt Bridge: bridge0 | Cầu nối gộp các cổng Thunderbolt thành một mạng | Không |
gif0, stf0 | Giao diện đường hầm của hệ điều hành: gif là đường hầm IP chung, stf là cầu nối IPv6 qua IPv4 (6to4). Hầu như không dùng | Không |
ap1 | Giao diện điểm phát Wi-Fi: xuất hiện khi bạn bật chia sẻ Internet (Internet Sharing) cho thiết bị khác | Không |
nan0 | Neighbor Awareness Networking (Wi-Fi Aware): kết nối Wi-Fi trực tiếp giữa các thiết bị lân cận | Không |
Các dòng có biểu tượng bánh răng ở cuối danh sách (Cisco remote capture: ciscodump, Random packet generator: randpkt, SSH remote capture: sshdump, và các dòng tương tự như UDP Listener, Wi-Fi remote capture) không phải card mạng. Đó là công cụ bổ trợ (extcap) của Wireshark: ciscodump và sshdump bắt gói từ một thiết bị khác (router Cisco, máy chủ SSH) qua mạng; randpkt sinh gói giả để thử nghiệm. Bấm đúp vào chúng sẽ mở hộp cấu hình kết nối tới máy khác, nằm ngoài phạm vi bài này. Chỉ cấu hình khi bạn được phép bắt gói trên thiết bị đó.
localhost thì chọn Loopback. Một đầu ở xa (website thật, máy khác trong nhà) thì chọn card đang dùng để ra mạng, thường là Wi-Fi: en0. Chọn sai là lý do số một khiến bảng gói trống.3c. Cửa sổ chính khi đang bắt gói: sáu vùng cần biết
| Số | Vùng | Dùng để làm gì |
|---|---|---|
| ① | Thanh công cụ | Các nút điều khiển (bảng ngay dưới) |
| ② | Ô lọc hiển thị (display filter) | Gõ điều kiện, nhấn Enter, chỉ giữ lại gói khớp. Đây là ô bạn dùng nhiều nhất. Nền xanh lá là cú pháp đúng, đỏ là sai (chưa Enter được), vàng là cảnh báo nhưng vẫn chạy. Nút mũi tên xanh bên phải là "áp dụng" (giống Enter), mũi tên xuống mở lịch sử bộ lọc, nút X xóa trắng ô lọc, biểu tượng bookmark ở bên trái mở bộ lọc đã lưu, dấu + (không cần dùng) mở thanh "Filter Buttons" với ô Label, Filter, Comment để lưu bộ lọc thành nút bấm nhanh. Lỡ bấm nhầm + thì bấm Cancel ở góc phải thanh đó là đóng lại, dữ liệu không mất. Phím tắt đưa con trỏ vào ô này: ⌘ + / |
| ③ | Danh sách gói (Packet List) | Mỗi dòng là một gói. Cột: No. số thứ tự; Time giây kể từ gói đầu; Source/Destination IP gửi và nhận; Protocol giao thức cao nhất Wireshark nhận ra (TCP, HTTP, TLSv1.3, DNS…); Length số byte; Info tóm tắt, ví dụ GET / HTTP/1.1 hoặc 51514 → 8000 [SYN]. Nhấp một dòng để xem chi tiết ở khung ④ và ⑤. Màu nền chỉ là gợi ý theo giao thức, đừng dựa vào màu mà hãy đọc cột Protocol |
| ④ | Chi tiết gói (Packet Details) | Gói được bóc theo từng lớp như bài đã học: Frame → Internet Protocol (IP) → Transmission Control Protocol (TCP) → Hypertext Transfer Protocol (HTTP). Bấm mũi tên ▸ để mở từng lớp và thấy từng trường, ví dụ Cookie |
| ⑤ | Byte của gói (Packet Bytes) | Dữ liệu thô: bên trái là số hex, bên phải là ký tự đọc được. Với HTTP bạn đọc được chữ ngay ở cột phải, với HTTPS chỉ thấy ký tự vô nghĩa. Bấm vào một trường ở ④ thì đoạn byte tương ứng ở ⑤ được tô sáng |
| ⑥ | Thanh trạng thái | Bên trái là tên giao diện đang bắt. Bên phải: Packets là tổng số gói đã thu, Displayed là số gói đang hiển thị sau khi lọc. Hai số khác nhau nghĩa là bộ lọc đang ẩn bớt dòng (không xóa) |
3d. Các nút trên thanh công cụ (từ trái sang phải)
Rê chuột lên một nút để xem tên đầy đủ. Những nút cần dùng trong bài:
| Nút | Tên | Làm gì | Lưu ý |
|---|---|---|---|
| Vây cá mập xanh dương | Start capturing packets (⌘ + E) | Bắt đầu bắt gói trên giao diện đang chọn | Chỉ sáng khi đã chọn giao diện. Bấm trước khi gõ lệnh curl |
| Hình vuông đỏ | Stop capturing (⌘ + E) | Dừng bắt gói | Dừng xong gói vẫn còn trên màn hình để phân tích. Nếu quên dừng, bảng cuộn mãi và file phình to |
| Vây cá mập xanh lá có mũi tên vòng | Restart current capture | Dừng và bắt đầu lại ngay trên cùng giao diện | Gói cũ sẽ mất; Wireshark hỏi lưu hay không. Rất tiện khi muốn làm sạch rồi bắt lần mới |
| Bánh răng | Capture options (⌘ + K) | Mở hộp thoại chọn giao diện, đặt capture filter, giới hạn kích thước | Bài này không cần chỉnh |
| Thư mục | Open a capture file | Mở file .pcapng đã lưu | Dùng để xem lại hoặc mở bản capture mẫu |
| Tờ giấy có bút | Save this capture file | Lưu toàn bộ gói đã bắt thành file | Chỉ lưu khi cần giữ bằng chứng. File chứa dữ liệu thật, nhớ xóa khi xong |
| Dấu X | Close this capture file | Đóng bản capture hiện tại, quay về màn hình chào | Hỏi lưu nếu chưa lưu |
| Kính lúp | Find a packet (⌘ + F) | Tìm gói có chuỗi, hex hoặc tên trường | Thanh tìm hiện bên dưới ô lọc, nhớ chọn đúng vùng tìm (Packet bytes để tìm chữ thô) |
| Hai mũi tên xanh trái, phải | Go back / forward | Lùi và tiến trong lịch sử các gói bạn đã chọn | |
| Mũi tên lên và xuống | Go to first / last packet | Nhảy tới gói đầu hoặc gói cuối | |
| Nút có mũi tên xuống ở cuối danh sách | Automatically scroll during live capture | Bật: bảng tự cuộn xuống gói mới nhất khi đang bắt. Tắt: giữ nguyên chỗ bạn đang đọc | Tắt đi nếu bạn đang đọc một dòng mà bảng cứ cuộn đi |
| Dòng kẻ nhiều màu | Colorize packet list | Bật/tắt tô màu dòng theo giao thức | Tắt đi nếu màu làm khó đọc |
| Kính lúp có dấu + / − / = | Zoom in / out / normal | Phóng to, thu nhỏ, khôi phục cỡ chữ | Dùng khi chụp ảnh màn hình hoặc chữ nhỏ |
| Hai nút cuối (cột, bố cục) | Resize columns / layout | Tự chỉnh độ rộng cột cho vừa nội dung | Khi cột Info bị cắt chữ thì bấm nút này |
3e. Bộ lọc hiển thị: gõ gì vào ô ②
Các bộ lọc sau đủ cho cả hai lab. Gõ vào ô lọc rồi nhấn Enter; xóa trắng ô rồi Enter để hiện lại tất cả. Có thể ghép bằng && (và), || (hoặc), ! (phủ định).
| Gõ vào ô lọc | Hiện những gói nào | Dùng ở |
|---|---|---|
tcp.port == 8000 | Mọi gói có port nguồn hoặc đích là 8000 (luồng HTTP của lab) | Lab 1 |
tcp.port == 8000 || tcp.port == 8443 | Cả luồng HTTP và luồng HTTPS | Lab 2 |
http | Chỉ gói đã được nhận ra là HTTP | Lab 1 |
http.request.method == "POST" | Chỉ các request POST | Lab 1 |
tls | Chỉ gói TLS (bắt tay và Application Data) | Lab 2 |
tls.handshake.type == 1 | Chỉ gói Client Hello của TLS | Lab 2 |
dns | Chỉ truy vấn và trả lời DNS | Lab 2, bước 5 |
tcp.flags.syn == 1 | Gói có cờ SYN (bắt đầu bắt tay TCP, cả SYN và SYN/ACK) | Phần B3 |
frame contains "demo123" | Gói có chuỗi demo123 nằm nguyên văn trong dữ liệu. Không có kết quả nghĩa là chuỗi không lộ | Cả hai lab, phép thử chữ rõ |
Gõ dần dần, Wireshark gợi ý tên trường trong danh sách thả xuống. Nếu ô chuyển nền đỏ, hay gặp: sai dấu (= thay vì ==), thiếu dấu ngoặc kép quanh chuỗi, gõ sai tên trường.
3e-2. Đọc hiểu một bộ lọc: tên trường, toán tử, giá trị
Mọi bộ lọc hiển thị đều có cùng một hình dạng: tên_trường toán_tử giá_trị. Ví dụ tcp.port == 8000 đọc là "trường tcp.port bằng 8000". Tên trường chính là các mục bạn thấy trong khung ④ (Packet Details): tcp là giao thức, dấu chấm đi vào từng thuộc tính của giao thức đó. Bấm một dòng ở khung ④, thanh dưới cùng của cửa sổ hiện đúng tên trường để bạn chép vào ô lọc. Chỉ gõ tên giao thức (như http, tls, dns) nghĩa là "gói có giao thức này".
Các trường (thuộc tính) hay dùng
| Trường | Thuộc giao thức / lớp | Ý nghĩa | Kiểu giá trị và ví dụ |
|---|---|---|---|
frame.len | Frame (gói thô) | Kích thước cả gói, tính bằng byte | Số: frame.len > 1000 |
frame | Frame | Toàn bộ nội dung byte của gói. Dùng với contains để tìm chuỗi bất kỳ | Chuỗi: frame contains "demo123" |
ip.addr | IP (lớp mạng, bài 5) | IP của gói, cả nguồn lẫn đích | Địa chỉ, không có ngoặc kép: ip.addr == 127.0.0.1 |
ip.src / ip.dst | IP | IP nguồn / IP đích riêng từng chiều | ip.dst == 203.0.113.10 |
tcp.port | TCP (bài 5 và phần B3) | Port của gói, cả nguồn lẫn đích. Khớp nếu một trong hai là giá trị đó | Số: tcp.port == 8000 |
tcp.srcport / tcp.dstport | TCP | Port nguồn / port đích riêng từng chiều. tcp.dstport == 8000 chỉ lấy gói đi tới server | Số |
tcp.stream | TCP | Số thứ tự của một luồng (một kết nối). Do Follow TCP Stream điền sẵn | Số: tcp.stream eq 3 |
tcp.flags.syn | TCP (bắt tay) | Cờ SYN: 1 nghĩa là gói xin kết nối | Bật/tắt: tcp.flags.syn == 1 hoặc chỉ tcp.flags.syn |
tcp.flags.ack | TCP | Cờ ACK: xác nhận đã nhận | tcp.flags.ack == 1 |
tcp.flags.fin | TCP | Cờ FIN: một bên báo đóng kết nối bình thường | tcp.flags.fin == 1 |
tcp.flags.reset | TCP | Cờ RST: ngắt kết nối đột ngột, thường do port đóng hoặc bị chặn | tcp.flags.reset == 1 |
tcp.len | TCP | Số byte dữ liệu ứng dụng trong gói. Bằng 0 là gói chỉ điều khiển (SYN, ACK…) | tcp.len > 0 |
http.request.method | HTTP (phần A1) | Method của request: GET, POST… | Chuỗi: http.request.method == "POST" |
http.request.uri | HTTP | Đường dẫn trong request | http.request.uri == "/dong-phi" |
http.host | HTTP | Giá trị header Host | http.host contains "example" |
http.cookie | HTTP | Giá trị header Cookie | http.cookie contains "phien=" |
http.response.code | HTTP | Mã trạng thái của response (200, 404…) | Số: http.response.code == 404 |
tls.handshake.type | TLS (phần C1) | Loại thông điệp bắt tay: 1 = Client Hello, 2 = Server Hello, 11 = Certificate, 20 = Finished | Số: tls.handshake.type == 1 |
tls.handshake.extensions_server_name | TLS | Tên miền mà client xin kết nối (SNI), nằm chữ rõ trong Client Hello | tls.handshake.extensions_server_name == "localhost" |
dns.qry.name | DNS (phần B1) | Tên miền đang được hỏi | dns.qry.name == "example.com" |
Toán tử (đặt giữa tên trường và giá trị) và cách ghép nhiều điều kiện:
| Toán tử | Cách viết khác | Nghĩa | Ví dụ |
|---|---|---|---|
== | eq | Bằng | tcp.port == 8000 |
!= | ne | Khác. Với trường có thể xuất hiện hai lần như ip.addr, nên viết !(ip.addr == 1.2.3.4) thay vì ip.addr != 1.2.3.4 | tcp.port != 22 |
> < >= <= | gt lt ge le | So sánh số | frame.len >= 500 |
contains | Có chứa chuỗi con, phân biệt hoa thường | frame contains "Cookie" | |
matches | ~ | Khớp biểu thức chính quy | http.host matches "^clb\." |
in {…} | Thuộc một tập giá trị, các giá trị cách nhau bằng dấu cách | tcp.port in {8000 8443} | |
&& | and | Và: cả hai điều kiện cùng đúng | http && tcp.port == 8000 |
|| | or | Hoặc: một trong hai đúng | tcp.port == 8000 || tcp.port == 8443 |
! | not | Phủ định cả điều kiện đứng sau | !tls |
( ) | Nhóm điều kiện để rõ thứ tự | (tcp.port == 8000 || tcp.port == 8443) && tcp.len > 0 |
Mổ xẻ một bộ lọc dài:
http.request.method == "POST" && tcp.dstport == 8000 && frame contains "demo123"| Mảnh | Đọc là |
|---|---|
http.request.method == "POST" | Gói là request HTTP có method POST |
&& tcp.dstport == 8000 | và đang đi tới port 8000, tức chiều client gửi lên server |
&& frame contains "demo123" | và trong dữ liệu có nguyên văn chuỗi demo123 (cookie giả) |
Kết quả: đúng gói request của Lan có cookie, bỏ qua mọi gói khác. Nếu bộ lọc này không trả về dòng nào khi bạn bắt HTTPS, đó chính là bằng chứng dữ liệu đã được mã hóa.
Cột Info: các cờ TCP bạn sẽ gặp
| Cờ trong ngoặc vuông | Nghĩa | Gặp ở đâu |
|---|---|---|
[SYN] | Client xin mở kết nối | Gói đầu của bắt tay ba bước |
[SYN, ACK] | Server đồng ý và xác nhận | Gói thứ hai |
[ACK] | Xác nhận đã nhận | Gói thứ ba, và sau mỗi lần nhận dữ liệu |
[PSH, ACK] | Có dữ liệu ứng dụng, đẩy lên ngay. Request và response HTTP nằm ở các gói này | Gói mang GET, POST, 200 OK |
[FIN, ACK] | Một bên báo đóng kết nối bình thường | Cuối cuộc hội thoại |
[RST] hoặc [RST, ACK] | Ngắt đột ngột; thường là port không có ai nghe hoặc bị từ chối | Khi gọi tới port đóng, ví dụ phép thử nhanh ở cuối bước 3 |
port 8000) quyết định gói nào được thu từ đầu; gói bị loại bỏ thì mất. Bộ lọc hiển thị (ô ②, cú pháp tcp.port == 8000) chỉ ẩn bớt dòng, gói vẫn còn trong bản capture. Học viên mới nên để ô capture filter trống và chỉ dùng bộ lọc hiển thị.3f. Follow TCP Stream: đọc cả cuộc hội thoại như một đoạn chat
Đây là tính năng làm nên "khoảnh khắc ngộ ra" của lab. Một request và response thường rải qua nhiều gói; Follow TCP Stream ghép chúng lại. Chuột phải vào một dòng gói của luồng cần xem → Follow → TCP Stream (hoặc menu Analyze → Follow → TCP Stream, phím tắt ⌥⌘⇧T trên macOS, Ctrl + Alt + Shift + T trên Windows/Linux). Cửa sổ mới hiện ra:
| Phần | Ý nghĩa |
|---|---|
Chữ màu đỏ | Dữ liệu client gửi đi (ví dụ request POST /dong-phi kèm cookie) |
Chữ màu xanh | Dữ liệu server trả lại (response) |
Ô "Entire conversation (… bytes)" | Chọn xem cả hai chiều hoặc chỉ một chiều |
Ô "Show as" | Cách hiển thị: ASCII (mặc định, đọc chữ), Hex Dump, Raw… Dùng ASCII |
Ô "Stream" | Số thứ tự luồng. Đổi số để xem các luồng khác trong cùng bản capture |
Ô "Find" và "Find Next" | Tìm chuỗi trong cuộc hội thoại, ví dụ Cookie |
Nút "Filter Out This Stream" | Ẩn luồng này khỏi danh sách để tập trung vào luồng khác |
Nút "Save as…" và "Print" | Lưu hoặc in nội dung. Cẩn thận, nội dung chứa dữ liệu thật |
Nút "Back" / "Close" | Quay lại cửa sổ chính. Chú ý: Wireshark tự điền bộ lọc kiểu tcp.stream eq 3 vào ô ②, nên danh sách chỉ còn luồng đó. Muốn xem lại tất cả: xóa trắng ô ② rồi Enter |
Với luồng HTTP ở port 8000, bạn đọc được trọn vẹn request và response. Với luồng HTTPS ở port 8443, cửa sổ chỉ hiện ký tự lộn xộn: đó là bằng chứng bằng mắt rằng nội dung đã được mã hóa.
3g. Phím tắt đáng nhớ
| Việc | macOS | Windows / Linux |
|---|---|---|
| Bắt đầu / dừng bắt gói | ⌘ + E | Ctrl + E |
| Đưa con trỏ vào ô lọc hiển thị | ⌘ + / | Ctrl + / |
| Tìm gói | ⌘ + F | Ctrl + F |
| Capture options | ⌘ + K | Ctrl + K |
| Follow TCP Stream | ⌥ ⌘ ⇧ T | Ctrl + Alt + Shift + T |
| Lưu bản capture | ⌘ + S | Ctrl + S |
3h. Lỗi thường gặp khi dùng Wireshark
| Dấu hiệu | Nguyên nhân | Cách xử lý |
|---|---|---|
| Khung vàng "don't have permission to capture" | Chưa cài ChmodBPF (macOS) hoặc chưa vào nhóm wireshark (Linux) | Làm bước 3a, thoát hẳn Wireshark rồi mở lại |
| Bắt gói chạy nhưng bảng trống | Chọn sai giao diện (ví dụ Wi-Fi trong khi server chạy ở loopback), hoặc chưa có ai gọi server | Nhìn thanh tiêu đề: phải là Capturing from Loopback: lo0. Dừng, bấm X về màn hình chào, chọn đúng loopback, bắt đầu lại rồi mới gõ lệnh curl |
| Có gói nhưng không thấy dòng HTTP | Bộ lọc quá hẹp, hoặc port sai | Xóa ô lọc rồi Enter; thử tcp.port == 8000. Luồng 8443 mà Protocol chỉ hiện TCP thì chuột phải → Decode As… → port 8443 → TLS |
| Ô lọc nền đỏ, Enter không chạy | Sai cú pháp | Dùng ==, đặt chuỗi trong ngoặc kép, xem gợi ý thả xuống |
| Số "Displayed" nhỏ hơn "Packets" | Bộ lọc đang ẩn bớt | Bình thường; xóa ô lọc để hiện hết |
| Wireshark hỏi "Save packets before continuing?" | Bạn bấm Start/Restart khi bản capture cũ chưa lưu | Chọn Continue without Saving nếu không cần giữ |
| Với HTTPS vẫn không đọc được nội dung | Đúng như thiết kế: người bắt gói không có khóa phiên | Đây là kết quả mong muốn của lab, không phải lỗi |
.pcapng chứa dữ liệu thật, nên xóa khi xong. Ở lab này chỉ dùng loopback và dữ liệu giả nên rất an toàn.Loopback: lo0. Trong lúc đó chạy curl http://127.0.0.1:1 ở một terminal (lệnh này báo lỗi kết nối bị từ chối, bình thường). Quay lại, bạn thấy vài dòng TCP với cờ [SYN] và [RST, ACK]: bạn đã bắt được gói đầu tiên. Bấm hình vuông đỏ để dừng. Nếu thấy dòng, mọi thứ đã sẵn sàng.Bước 4. Bắt gói và đọc chữ rõ bằng Wireshark
Server vẫn chạy ở Terminal A. Giờ ta quan sát những gì thực sự chạy trên dây (ở đây là giao diện loopback). Tên giao diện loopback tùy hệ điều hành:
| Hệ điều hành | Giao diện loopback trong Wireshark |
|---|---|
| macOS | Loopback: lo0 |
| Linux | Loopback: lo (hoặc lo) |
| Windows | Adapter for loopback traffic capture (Npcap; tên có thể khác theo phiên bản) |
- Mở Wireshark. Ở màn hình đầu, nhấp đúp vào giao diện loopback ở bảng trên. Đường sóng bên cạnh tên sẽ nhảy lên và gói bắt đầu hiện. Nếu chưa có gói nào, đừng lo, chưa có ai gọi server. Kiểm tra thanh tiêu đề cửa sổ: phải ghi
Capturing from Loopback: lo0. Nếu ghiWi-Fi: en0là bạn đang bắt sai giao diện: gói gửi tới 127.0.0.1 không bao giờ đi qua Wi-Fi nên bảng sẽ trống mãi. Khi đó bấm hình vuông đỏ, bấm nút X để về màn hình chào rồi chọn lại loopback. Nếu bạn chạy server ở port khác 8000 thì sửa luôn bộ lọc cho khớp port đó. - Ở Terminal B, gửi một request có kèm cookie giả (cookie là đoạn "bằng chứng đã đăng nhập" của bài 3, ở đây chỉ là dữ liệu giả):
curl -H "Cookie: phien=demo123" http://127.0.0.1:8000/| Phần | Ý nghĩa |
|---|---|
curl | Gửi một request HTTP và in response ra màn hình. |
-H "Cookie: phien=demo123" | -H thêm một header vào request. Ở đây ta thêm header Cookie với giá trị giả phien=demo123. |
http://127.0.0.1:8000/ | Địa chỉ đích: máy này, port 8000, đường dẫn /. Phần http:// cho biết đây là HTTP thường, không mã hóa. |
- Quay lại Wireshark, bấm nút hình vuông đỏ (Stop) để dừng bắt gói.
- Gõ vào ô lọc phía trên cùng (nền chuyển xanh lá là cú pháp đúng) rồi nhấn Enter:
tcp.port == 8000Đây là : chỉ ẩn bớt dòng, không xóa gói. Bạn sẽ thấy khoảng chục dòng: ba gói đầu là bắt tay TCP (SYN, SYN, ACK, ACK, phần B3), tiếp theo là dòng HTTP GET / HTTP/1.1, dòng HTTP/1.0 200 OK, rồi các gói đóng kết nối.
- Nhấp vào dòng
GET / HTTP/1.1. Ở khung giữa, mở mục Hypertext Transfer Protocol để thấy từng header. - Chuột phải vào dòng đó, chọn Follow → TCP Stream (hoặc menu Analyze → Follow → TCP Stream). Wireshark ghép các gói thành cuộc hội thoại: chữ đỏ là client gửi, chữ xanh là server trả.
GET / HTTP/1.1
Host: 127.0.0.1:8000
User-Agent: curl/8.7.1
Accept: */*
Cookie: phien=demo123
HTTP/1.0 200 OK
Server: SimpleHTTP/0.6 Python/3.9.6
Content-type: text/html
Content-Length: 37
<h1>Cau lac bo - Lich sinh hoat</h1>Dòng Cookie: phien=demo123 nằm đó, đọc được nguyên văn. Với một cookie phiên thật, bất kỳ thiết bị nào nhìn thấy gói này cũng có thể dùng lại nó. Nếu không thấy gói: kiểm tra đã chọn đúng giao diện loopback, Terminal A còn chạy, và capture đã bắt đầu trước khi gõ lệnh curl (gói đã đi qua trước đó thì không bắt lại được). Bảng dưới là dữ liệu minh họa đã giản lược (không phải capture từ máy bạn); bấm một dòng để xem giải thích.
| No. | Protocol | Source port | Dest. port | Info · Chọn để xem |
|---|
tcpdump. Mở một terminal, gõ sudo tcpdump -i lo0 -A -s 0 "tcp port 8000" (Linux đổi lo0 thành lo), nhập mật khẩu máy, rồi chạy lệnh curl ở terminal khác. -i chọn giao diện, -A in nội dung gói dạng chữ, -s 0 lấy trọn gói. Cookie hiện ngay trên màn hình. Dừng bằng Ctrl+C.Bước 5. Mô phỏng Lan bấm "Đóng phí" (gửi dữ liệu bằng POST)
Ở bước 4 bạn mới bắt request GET. Tình huống của bài là Lan gửi tên và số tiền, tức POST có body. Server Python mặc định không nhận POST, nên ta viết một server nhỏ hơn, dài chừng 40 dòng, dùng chung cho cả hai lab.
Trước hết dừng server cũ: ở Terminal A nhấn Ctrl + C (port 8000 phải được giải phóng). Rồi tạo file server.py trong thư mục network-lab. Cách nhanh nhất là dán lệnh sau vào terminal (nhấn nút Sao chép):
cat > server.py <<'EOF'
# server.py - web server thu nghiem cho bai 6. Chi nghe tren may cua ban.
# Chay HTTP: python3 server.py (port 8000)
# Chay HTTPS: python3 server.py --tls (port 8443, can cert.pem va key.pem)
import ssl
import sys
from http.server import BaseHTTPRequestHandler, HTTPServer
from urllib.parse import parse_qs
USE_TLS = "--tls" in sys.argv
PORT = 8443 if USE_TLS else 8000
class Handler(BaseHTTPRequestHandler):
def reply(self, status, body):
self.send_response(status)
self.send_header("Content-Type", "text/html; charset=utf-8")
self.send_header("Content-Length", str(len(body)))
self.end_headers()
self.wfile.write(body)
def do_GET(self):
try:
with open("index.html", "rb") as f:
self.reply(200, f.read())
except FileNotFoundError:
self.reply(404, b"Khong tim thay index.html. Hay chay server trong thu muc network-lab.")
def do_POST(self):
size = int(self.headers.get("Content-Length", 0))
fields = parse_qs(self.rfile.read(size).decode("utf-8"))
print(" Cookie server nhan duoc :", self.headers.get("Cookie"))
print(" Du lieu server nhan duoc:", fields)
self.reply(200, b"<h1>Da nhan phi cua Lan</h1>")
server = HTTPServer(("127.0.0.1", PORT), Handler)
if USE_TLS:
context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
context.load_cert_chain("cert.pem", "key.pem")
server.socket = context.wrap_socket(server.socket, server_side=True)
scheme = "https" if USE_TLS else "http"
print(f"Dang chay tai {scheme}://127.0.0.1:{PORT}/ (Ctrl+C de dung)")
server.serve_forever()
EOF@'
# server.py - web server thu nghiem cho bai 6. Chi nghe tren may cua ban.
# Chay HTTP: python3 server.py (port 8000)
# Chay HTTPS: python3 server.py --tls (port 8443, can cert.pem va key.pem)
import ssl
import sys
from http.server import BaseHTTPRequestHandler, HTTPServer
from urllib.parse import parse_qs
USE_TLS = "--tls" in sys.argv
PORT = 8443 if USE_TLS else 8000
class Handler(BaseHTTPRequestHandler):
def reply(self, status, body):
self.send_response(status)
self.send_header("Content-Type", "text/html; charset=utf-8")
self.send_header("Content-Length", str(len(body)))
self.end_headers()
self.wfile.write(body)
def do_GET(self):
try:
with open("index.html", "rb") as f:
self.reply(200, f.read())
except FileNotFoundError:
self.reply(404, b"Khong tim thay index.html. Hay chay server trong thu muc network-lab.")
def do_POST(self):
size = int(self.headers.get("Content-Length", 0))
fields = parse_qs(self.rfile.read(size).decode("utf-8"))
print(" Cookie server nhan duoc :", self.headers.get("Cookie"))
print(" Du lieu server nhan duoc:", fields)
self.reply(200, b"<h1>Da nhan phi cua Lan</h1>")
server = HTTPServer(("127.0.0.1", PORT), Handler)
if USE_TLS:
context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
context.load_cert_chain("cert.pem", "key.pem")
server.socket = context.wrap_socket(server.socket, server_side=True)
scheme = "https" if USE_TLS else "http"
print(f"Dang chay tai {scheme}://127.0.0.1:{PORT}/ (Ctrl+C de dung)")
server.serve_forever()
'@ | Set-Content -Path server.py -Encoding asciicat > server.py <<'EOF'
# server.py - web server thu nghiem cho bai 6. Chi nghe tren may cua ban.
# Chay HTTP: python3 server.py (port 8000)
# Chay HTTPS: python3 server.py --tls (port 8443, can cert.pem va key.pem)
import ssl
import sys
from http.server import BaseHTTPRequestHandler, HTTPServer
from urllib.parse import parse_qs
USE_TLS = "--tls" in sys.argv
PORT = 8443 if USE_TLS else 8000
class Handler(BaseHTTPRequestHandler):
def reply(self, status, body):
self.send_response(status)
self.send_header("Content-Type", "text/html; charset=utf-8")
self.send_header("Content-Length", str(len(body)))
self.end_headers()
self.wfile.write(body)
def do_GET(self):
try:
with open("index.html", "rb") as f:
self.reply(200, f.read())
except FileNotFoundError:
self.reply(404, b"Khong tim thay index.html. Hay chay server trong thu muc network-lab.")
def do_POST(self):
size = int(self.headers.get("Content-Length", 0))
fields = parse_qs(self.rfile.read(size).decode("utf-8"))
print(" Cookie server nhan duoc :", self.headers.get("Cookie"))
print(" Du lieu server nhan duoc:", fields)
self.reply(200, b"<h1>Da nhan phi cua Lan</h1>")
server = HTTPServer(("127.0.0.1", PORT), Handler)
if USE_TLS:
context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
context.load_cert_chain("cert.pem", "key.pem")
server.socket = context.wrap_socket(server.socket, server_side=True)
scheme = "https" if USE_TLS else "http"
print(f"Dang chay tai {scheme}://127.0.0.1:{PORT}/ (Ctrl+C de dung)")
server.serve_forever()
EOFKiểm tra bằng ls (macOS/Linux) hoặc dir (Windows): thư mục phải có index.html và server.py. Cũng có thể tạo bằng trình soạn thảo: dán nguyên đoạn Python vào, lưu với tên server.py (cùng lưu ý về Notepad và TextEdit ở bước 1). Ý nghĩa các phần chính của file:
| Phần | Ý nghĩa |
|---|---|
HTTPServer(("127.0.0.1", PORT), Handler) | Tạo server nghe ở loopback, port 8000 (hoặc 8443 khi có --tls ở Lab 2). Mỗi request đến được giao cho lớp Handler xử lý. |
do_GET | Hàm chạy khi có request GET: đọc file index.html và trả về với mã 200. Không có file thì trả 404. |
do_POST | Hàm chạy khi có request POST: đọc đúng Content-Length byte của body, tách thành các cặp tên=giá trị, rồi in cookie và dữ liệu ra terminal. Server nào cũng phải làm việc tương tự để nhận form. |
parse_qs | Tách chuỗi ten=Lan&so_tien=200000 thành từng trường, giống cách form HTML được gửi. |
--tls (dùng ở Lab 2) | Khi có tham số này, server bọc socket bằng TLS và chạy HTTPS ở port 8443. |
Chạy server mới ở Terminal A, rồi gửi POST từ Terminal B khi Wireshark đang bắt gói (bấm Start lại trên loopback; nếu Wireshark hỏi lưu bản capture cũ thì chọn Continue without Saving):
python3 server.pypy server.pypython3 server.pycurl -i -X POST -H "Cookie: phien=demo123" -d "ten=Lan&so_tien=200000&ghi=ok" http://127.0.0.1:8000/dong-phi| Phần | Ý nghĩa |
|---|---|
-i | In cả header của response, để thấy mã trạng thái. |
-X POST | Dùng method POST thay cho GET mặc định. |
-H "Cookie: phien=demo123" | Header Cookie giả, đóng vai mã phiên đăng nhập của Lan. |
-d "ten=Lan&so_tien=200000&ghi=ok" | -d là data: nội dung body. curl tự đặt Content-Length và Content-Type kiểu form như request ở phần A1. |
.../dong-phi | Đường dẫn xử lý việc đóng phí, giống request minh họa ở phần A1. |
Dang chay tai http://127.0.0.1:8000/ (Ctrl+C de dung)
Cookie server nhan duoc : phien=demo123
Du lieu server nhan duoc: {'ten': ['Lan'], 'so_tien': ['200000'], 'ghi': ['ok']}
127.0.0.1 - - [19/Oct/2026 20:05:47] "POST /dong-phi HTTP/1.1" 200 -HTTP/1.0 200 OK
Server: BaseHTTP/0.6 Python/3.9.6
Content-Type: text/html; charset=utf-8
Content-Length: 28
<h1>Da nhan phi cua Lan</h1>Dừng capture, lọc tcp.port == 8000, chuột phải vào dòng POST /dong-phi → Follow → TCP Stream. Bạn đọc được cả Cookie: phien=demo123 lẫn body ten=Lan&so_tien=200000&ghi=ok. Server nhận được dữ liệu vì nó là một đầu của kết nối; nhưng bất cứ ai nằm giữa đường cũng đọc được y hệt, và với HTTP thì còn sửa được trước khi tới server. Phần C sẽ chặn việc này.
BÀI TẬP 2 · 10 PHÚT
Tìm chữ rõ trong capture của chính bạn
Trong cửa sổ Follow TCP Stream của lần bắt gói POST, ghi lại:
- Port nguồn (port tạm của client) và port đích.
- Dòng request đầu tiên và dòng đầu của response (mã trạng thái).
- Dòng
Cookiebạn đã gửi: có đọc được không? - Nội dung body của request và nội dung body của response.
- Dùng ô lọc
frame contains "demo123"(thay chotcp.port == 8000). Còn bao nhiêu gói hiện ra, và vì sao đó là bằng chứng của chữ rõ?
Sau đó dừng capture và server (Ctrl+C), xóa file capture nếu không cần: file PCAP có thể chứa dữ liệu của luồng khác.
Xem đáp án
- Port đích là 8000; port nguồn là số ngẫu nhiên cao (thường trên 49152), mỗi lần chạy khác nhau.
POST /dong-phi HTTP/1.1vàHTTP/1.0 200 OK(server Python trả HTTP/1.0; curl gửi 1.1, hai bên có thể khác phiên bản).- Đọc được nguyên văn
Cookie: phien=demo123. Đây chính là điều bất kỳ ai trên đường đi cũng làm được với HTTP. - Body request:
ten=Lan&so_tien=200000&ghi=ok. Body response:<h1>Da nhan phi cua Lan</h1>. - Hiện ra gói (hoặc các gói) chứa request có cookie, vì chuỗi
demo123nằm nguyên văn trong dữ liệu gói. Nếu dữ liệu được mã hóa, chuỗi đó không xuất hiện và bộ lọc không tìm thấy gì; Lab 2 kiểm tra đúng điều này.
Kết luận phần A: HTTP không mã hóa lộ mọi thứ. Phần B xem ai nằm trên đường đi, phần C cách chặn.
B1. Đường đi (1): DNS tìm địa chỉ máy chủ
8 phútPhần A dùng địa chỉ số trực tiếp. Trên Internet, Lan gõ tên, nên trước tiên máy phải đổi tên thành IP. Việc này do làm: nhận câu hỏi, dùng kết quả đã lưu () hoặc hỏi tiếp các máy chủ DNS.
| Thông tin | Ví dụ | Ý nghĩa |
|---|---|---|
| Tên hỏi | clb.example | Tên đang cần tra |
| Loại bản ghi | A (IPv4), AAAA (IPv6) | Loại thông tin cần |
| Kết quả | 203.0.113.10 | Địa chỉ trả về (địa chỉ tài liệu, minh họa) |
| TTL | 300 giây | Thời gian được phép lưu cache |
Rủi ro bảo mật của DNS
- DNS thông thường không mã hóa và không tự xác thực: ai ở giữa đường nhìn thấy tên website bạn truy cập, và nếu giả được câu trả lời (DNS spoofing) thì đưa được người dùng tới máy chủ giả.
- Kẻ chiếm được tài khoản nhà đăng ký tên miền (bài 2) sửa được bản ghi A và chuyển cả website sang máy chủ của họ. Cần MFA và quyền tối thiểu cho tài khoản này.
- Tra được IP chưa chứng minh trang tải được, hay đúng là trang mong muốn.
BÀI TẬP 3 · 5 PHÚT
Quan sát DNS và nghĩ như kẻ tấn công
Chạy hai lần liên tiếp:
nslookup example.com
dig example.com- Ghi IP và TTL (
dighiện TTL ở cột thứ hai). Lần chạy thứ hai TTL có giảm không? Vì sao? - Nếu kẻ tấn công sửa được bản ghi A của
clb.example, Lan gõ đúng tên vẫn thấy gì? Tài khoản nào cần được bảo vệ?
Xem đáp án
- TTL thường giảm dần vì kết quả đang nằm trong cache của resolver và đếm ngược tới khi hết hạn. Hết TTL thì tra lại.
- Lan vào một máy chủ do kẻ tấn công điều khiển, có thể là bản sao giống hệt trang thật để lấy tiền hoặc mật khẩu. Cần bảo vệ tài khoản ở nhà đăng ký tên miền và DNS (MFA, quyền tối thiểu, theo dõi thay đổi bản ghi). Ngoài ra HTTPS (phần C) giúp trình duyệt nhận ra máy chủ không đúng chủ tên miền.
B2. Đường đi (2): router và NAT
10 phútBiết IP máy chủ rồi, gói tin rời mạng nhà qua . Router có hai việc đáng chú ý về bảo mật.
Việc 1: dịch địa chỉ (NAT)
IP riêng như 192.168.1.10 không dùng trực tiếp trên Internet. Khi gói đi ra, router thực hiện : thay địa chỉ nguồn bằng IP công cộng của router. Nhiều thiết bị chung một IP công cộng nên router còn đổi cả port () và ghi vào bảng ánh xạ:
| Kết nối bên trong | Ánh xạ bên ngoài | Đích |
|---|---|---|
| 192.168.1.10:51514 | 198.51.100.25:62001 | 203.0.113.10:443 |
| 192.168.1.11:51514 | 198.51.100.25:62002 | 203.0.113.10:443 |
Hai máy cùng dùng port 51514 vẫn được tách nhờ hai port ngoài khác nhau. Khi server trả lời về 62001 hoặc 62002, router tra bảng và chuyển về đúng máy.
Việc 2: là điểm mọi gói đều đi qua
Router (và mọi thiết bị trên đường: Wi-Fi công cộng, nhà mạng, thiết bị trung gian) thấy được IP, port và với HTTP cả nội dung. Router bị chiếm thì kẻ tấn công đọc và sửa được lưu lượng chưa mã hóa (tấn công kẻ đứng giữa, ). Vì vậy: đổi mật khẩu quản trị mặc định của router, cập nhật firmware, và đừng tin Wi-Fi lạ cho dữ liệu nhạy cảm.
BÀI TẬP 4 · 10 PHÚT
Đọc bảng NAT và đối chiếu với máy bạn
Phần 1 (trên giấy). Dùng bảng NAT ở trên:
- Một gói từ
203.0.113.10:443đến198.51.100.25:62002. Router chuyển nó về đâu? - Một gói lạ từ
192.0.2.77:4444đến198.51.100.25:62999. Chuyện gì xảy ra và vì sao?
Phần 2 (trên máy bạn). Dùng lệnh ở bài 5 để ghi IP riêng và gateway của máy. Tùy chọn: chạy curl https://ifconfig.me để xem IP công cộng của bạn và so với IP riêng.
Xem đáp án
Phần 1.
- Về
192.168.1.11:51514, vì bảng ghi 62002 tương ứng với máy .11. - Bị bỏ: không có ánh xạ nào cho port 62999 nên router không biết chuyển cho máy nào. Đây là lý do mạng nhà ít bị "gõ cửa" từ ngoài, nhưng cần firewall để chủ động chặn.
Phần 2. IP riêng thường dạng 192.168.x.x hoặc 10.x.x.x; IP công cộng là địa chỉ khác hẳn và chung cho mọi thiết bị trong nhà (hoặc cả nhiều nhà nếu có CGNAT). Gateway thường là 192.168.x.1.
B3. Đường đi (3): firewall và TCP
12 phútTường lửa
cho phép hoặc chặn lưu lượng theo quy tắc (IP, port, giao thức, trạng thái kết nối). Nguyên tắc: chặn mặc định, chỉ mở thứ cần thiết (default deny). Mỗi port mở ra ngoài là một điểm có thể bị tấn công. Ví dụ quy tắc cho máy chủ của câu lạc bộ:
| Thứ tự | Hành động | Đến port | Từ |
|---|---|---|---|
| 1 | Cho phép | 443 (HTTPS) | Mọi nơi |
| 2 | Cho phép | 22 (quản trị từ xa SSH) | Chỉ 203.0.113.50 (máy của quản trị viên) |
| 3 | Chặn | Tất cả port còn lại | Mọi nơi |
Kết nối chỉ thành công khi nhiều lớp cùng đúng: có đường đi, firewall không chặn, có chương trình đang lắng nghe đúng IP và port, hai bên nói giao thức tương thích, và ứng dụng cho phép yêu cầu. Vì vậy "mở port", "chạy server" và "cấp quyền sửa dữ liệu" là ba việc khác nhau. Mở port 8000 không tạo ra web server; server chỉ lắng nghe 127.0.0.1 thì máy khác không vào được dù firewall đã mở.
TCP: bắt tay ba bước
cho luồng byte đúng thứ tự, truyền lại phần bị mất. Trước khi gửi dữ liệu, hai bên làm : SYN (client xin kết nối) → SYN/ACK (server đồng ý) → ACK (client xác nhận). Chỉ sau đó HTTP mới bắt đầu chạy bên trên.
- Bắt tay TCP không mã hóa. Kết nối HTTP vẫn dùng TCP, nội dung vẫn là chữ rõ.
- Server phải giữ trạng thái cho mỗi kết nối đang bắt tay dở. Kẻ tấn công gửi rất nhiều SYN mà không hoàn tất (SYN flood) làm cạn tài nguyên: một dạng . Phòng bằng giới hạn tốc độ và cơ chế chống SYN flood của hệ điều hành hoặc nhà cung cấp.
- TCP có thể chuyển đúng request mà ứng dụng vẫn trả 403 hay 404. TCP không biết gì về nghiệp vụ.
Ghi chú: gửi từng gói rời, không bảo đảm đủ và đúng thứ tự. chạy trên UDP nhưng có độ tin cậy và TLS tích hợp, là nền của HTTP/3, nên thấy UDP cổng 443 không tự là dấu hiệu tấn công.
BÀI TẬP 5 · 10 PHÚT
Quyết định của firewall và đọc dấu hiệu SYN flood
Phần 1. Dùng bộ quy tắc ở trên, quyết định cho phép hay chặn:
- Gói từ
198.51.100.9đến cổng 443. - Gói từ
198.51.100.9đến cổng 22. - Gói từ
203.0.113.50đến cổng 22. - Gói từ
203.0.113.50đến cổng 3306 (cơ sở dữ liệu).
Phần 2. Đọc đoạn capture phía server (rút gọn) và cho biết đâu là bắt tay bình thường, đâu đáng ngờ:
1 192.0.2.10:40001 -> server:443 SYN
2 server:443 -> 192.0.2.10:40001 SYN/ACK
3 192.0.2.10:40001 -> server:443 ACK
4 192.0.2.21:50110 -> server:443 SYN
5 192.0.2.22:50111 -> server:443 SYN
6 192.0.2.23:50112 -> server:443 SYN
7 192.0.2.24:50113 -> server:443 SYN
(... hàng nghìn dòng SYN từ nhiều IP, không có ACK ...)Xem đáp án
Phần 1.
- Cho phép (quy tắc 1).
- Chặn (quy tắc 2 chỉ cho 203.0.113.50, rơi xuống quy tắc 3).
- Cho phép (quy tắc 2).
- Chặn (không có quy tắc cho 3306, rơi xuống chặn mặc định). Cơ sở dữ liệu không nên mở ra ngoài.
Phần 2. Dòng 1 đến 3 là bắt tay bình thường đủ ba bước. Dòng 4 trở đi: rất nhiều SYN từ nhiều IP khác nhau, server trả SYN/ACK nhưng không nhận ACK, kết nối treo dở. Đó là dấu hiệu SYN flood (tấn công từ chối dịch vụ). Cách ứng phó: bật SYN cookies hoặc bảo vệ chống DoS của nhà cung cấp, giới hạn tốc độ, ghi lại thời điểm và log để báo cáo (bài 4).
B4. Lab 3: nhìn mạng nhà mình từ trong và từ ngoài
15 phútLab này dùng chính mạng nhà bạn để trả lời ba câu hỏi: trong nhà đang có thiết bị nào, mỗi thiết bị có IP và port gì; IP công cộng của nhà là gì; và có thiết bị nào "chìa ra" Internet mà không cần thiết không. Nhớ lại bài 5 và phần B2: các thiết bị trong nhà dùng IP nội bộ (thường 192.168.x.x, 10.x.x.x), còn router dùng một IP công cộng duy nhất để nói với Internet.
Mỗi bước có tab cho macOS, Windows và Linux. Chọn tab đúng với máy bạn. Dưới mỗi khối lệnh có bảng giải thích từng phần của lệnh, để bạn đổi được tham số khi cần.
Bước 0. Cài công cụ nmap
nmap là công cụ quét mạng miễn phí, dùng xuyên suốt lab. Cài một lần:
brew install nmapTải bộ cài tại https://nmap.org/download.html, chạy file .exe và giữ tùy chọn cài Npcapsudo apt install nmap
# Fedora: sudo dnf install nmap| Phần | Ý nghĩa |
|---|---|
brew install nmap | brew là Homebrew, trình quản lý gói của macOS. install nmap cài gói tên nmap. Chưa có Homebrew thì cài theo brew.sh. |
sudo | Chạy lệnh với quyền quản trị. Linux sẽ hỏi mật khẩu máy. Lệnh cài đặt cần quyền này. |
apt install / dnf install | Trình quản lý gói của Ubuntu/Debian (apt) và Fedora (dnf). Lệnh tải và cài nmap từ kho chính thức của hệ điều hành. |
Npcap | Driver bắt gói trên Windows. Nmap cần nó để quét chính xác. Bộ cài nmap có sẵn tùy chọn này. |
Bước 1. Tìm IP của máy mình và của router
Router là của mạng nhà: mọi gói ra ngoài đi qua nó. Chạy lệnh theo hệ điều hành của bạn:
ipconfig getifaddr en0
route -n get default | grep gatewayipconfig
# Xem dòng "IPv4 Address" (IP máy) và "Default Gateway" (router)ip -4 addr show
ip route | grep default| Phần | Ý nghĩa |
|---|---|
ipconfig getifaddr en0 | ipconfig: lệnh xem cấu hình mạng trên macOS. getifaddr: lấy địa chỉ của một giao diện. en0: tên giao diện Wi-Fi trên đa số Mac. Nếu lệnh không ra IP, chạy ifconfig để tìm giao diện có inet 192.168.x.x rồi thay en0 bằng tên đó (ví dụ en1). |
route -n get default | route: xem bảng định tuyến. -n: không đổi IP thành tên miền, cho ra nhanh hơn. get default: hỏi tuyến mặc định, tức đường đi ra Internet. |
| grep gateway | Dấu | đưa kết quả lệnh trước vào lệnh sau. grep gateway chỉ giữ dòng có chữ gateway. Dòng đó chứa IP của router. |
ipconfig (Windows) | Không có tham số thì in mọi card mạng. Tìm mục Wi-Fi (Wireless LAN adapter Wi-Fi): IPv4 Address là IP máy, Default Gateway là router. Thêm /all để xem thêm DNS và MAC. |
ip -4 addr show | ip: công cụ mạng của Linux. -4: chỉ hiện địa chỉ IPv4. addr show: hiện địa chỉ của các giao diện. Đọc dòng inet 192.168.1.23/24: 192.168.1.23 là IP máy, /24 là độ dài phần mạng. |
ip route | grep default | ip route: in bảng định tuyến. Dòng default via 192.168.1.1 cho biết 192.168.1.1 là gateway. grep default chỉ giữ dòng đó. |
Ghi lại hai số: IP máy (ví dụ 192.168.1.23) và gateway (ví dụ 192.168.1.1).
Bước 2. Liệt kê thiết bị đang "quen mặt" với máy bạn
Lệnh arp -a chạy được trên cả ba hệ điều hành. Nó in bảng ARP: cặp IP và MAC của các thiết bị mà máy bạn vừa trao đổi gói tin với nó. Đây không phải danh sách đầy đủ, vì máy chỉ biết những thiết bị đã nói chuyện với nó.
arp -aarp -aarp -a
# Hoặc (không cần net-tools): ip neigh| Phần | Ý nghĩa |
|---|---|
arp -a | arp: xem bảng ARP (ánh xạ IP sang MAC). -a: hiện mọi mục. Mỗi dòng gồm IP, MAC và loại (dynamic: tự học từ mạng). |
ip neigh (Linux) | Cùng việc với arp -a, dùng công cụ ip hiện đại. Hữu ích khi máy không có lệnh arp. |
Để thấy đầy đủ hơn, dùng nmap quét ping toàn mạng. Thay dải mạng bằng dải của nhà bạn:
nmap -sn 192.168.1.0/24| Phần | Ý nghĩa |
|---|---|
nmap | Công cụ quét mạng đã cài ở bước 0. |
-sn | Ping scan: chỉ hỏi xem IP nào đang bật, không quét port. Nhanh và nhẹ. |
192.168.1.0/24 | Dải mạng. /24 nghĩa là 256 địa chỉ từ .0 đến .255. Đổi theo IP máy ở bước 1: nếu máy là 10.0.0.15 thì dải là 10.0.0.0/24. |
sudo (Mac, Linux) | Quyền quản trị giúp nmap dùng ARP, thấy được nhiều thiết bị hơn. Windows: mở PowerShell hoặc CMD bằng quyền Administrator. |
Host is up | Dòng xuất hiện khi thiết bị đang bật và trả lời. |
Kết quả mẫu (đã rút gọn, địa chỉ minh họa):
Nmap scan report for 192.168.1.1 (router)
Host is up.
Nmap scan report for 192.168.1.23 (máy của bạn)
Host is up.
Nmap scan report for 192.168.1.40 (điện thoại?)
Host is up.
Nmap done: 256 IP addresses (3 hosts up)Bước 3. Xem từng thiết bị đang mở port nào
Với một IP trong nhà mà bạn sở hữu (ví dụ máy của chính bạn), quét các port phổ biến và đoán dịch vụ. Lệnh giống nhau trên ba hệ điều hành:
nmap -sV --top-ports 100 192.168.1.23| Phần | Ý nghĩa |
|---|---|
nmap | Công cụ quét mạng. |
-sV | Version detection: cố đoán tên và phiên bản dịch vụ đang chạy ở mỗi port (ví dụ ssh, http). Chậm hơn một chút nhưng đọc kết quả dễ hơn. |
--top-ports 100 | Chỉ quét 100 port phổ biến nhất thay vì mặc định khoảng 1000. Nhanh hơn. Muốn quét kỹ hơn thì bỏ tham số này. |
192.168.1.23 | IP của thiết bị cần xem. Chỉ dùng IP máy bạn sở hữu. |
Đọc kết quả từng dòng: 22/tcp open ssh nghĩa là port 22 đang có dịch vụ SSH chờ kết nối. Máy đang nghe ở port nào thì đó là điểm có thể bị gõ cửa, dù cùng mạng nhà. Nhớ rằng là số, còn dịch vụ là chương trình đứng sau số đó.
Bước 4. Tìm IP công cộng của nhà
Có hai cách và nên làm cả hai để đối chiếu:
- Từ trang quản trị router: mục trạng thái Internet hoặc WAN ghi địa chỉ IP của router ra Internet. Đây là IP công cộng nếu nó không nằm trong dải nội bộ.
- Từ một dịch vụ hiển thị IP: dùng lệnh dưới đây. Dịch vụ thấy IP bạn đang đi ra, nên trả về IP công cộng của mạng nhà.
curl ifconfig.mecurl.exe ifconfig.mecurl ifconfig.me| Phần | Ý nghĩa |
|---|---|
curl | Công cụ gửi yêu cầu HTTP từ dòng lệnh. Có sẵn trên macOS, Linux và Windows 10 trở lên. |
curl.exe (Windows) | Dùng tên đầy đủ để chắc chắn gọi curl thật. PowerShell có alias curl trỏ tới lệnh khác, nên gõ curl không đúng như mong đợi. |
ifconfig.me | Dịch vụ trả về IP mà nó nhìn thấy khi bạn kết nối. Thay bằng api.ipify.org nếu dịch vụ này không phản hồi. |
Nếu địa chỉ trên router là 100.64.x.x đến 100.127.x.x, hoặc khác với IP dịch vụ trả về, nhà có thể đang dùng : nhà mạng cho nhiều khách hàng dùng chung một IP. Khi đó bạn không thể mở port từ ngoài vào nhà bằng cách cấu hình router, vì IP công cộng không thuộc riêng nhà bạn.
Bước 5. Thử nhìn nhà mình từ ngoài
Muốn biết thiết bị nào đang chìa ra Internet, phải nhìn từ bên ngoài mạng nhà. Cách an toàn nhất: tắt Wi-Fi nhà, bật 4G hoặc phát hotspot từ điện thoại, rồi dùng laptop (đang ở mạng ngoài) quét IP công cộng của chính nhà bạn với một danh sách port ngắn. Lệnh giống nhau trên ba hệ điều hành:
nmap -Pn -p 21,22,23,80,443,3389,8080 203.0.113.77| Phần | Ý nghĩa |
|---|---|
-Pn | Bỏ qua bước ping trước khi quét. Nhiều router và firewall không trả lời ping, nên nếu không có -Pn nmap có thể báo sai là máy tắt. |
-p 21,22,23,80,443,3389,8080 | Danh sách port cần thử, cách nhau bằng dấu phẩy. Có thể dùng dải như 20-100. Không dùng -p- (quét cả 65535 port): lâu và dễ bị coi là hành vi tấn công. |
203.0.113.77 | IP công cộng của nhà bạn (lấy ở bước 4). Đây là địa chỉ tài liệu, chỉ để minh họa; thay bằng IP thật của bạn. |
Ý nghĩa các trạng thái port:
| Trạng thái | Nghĩa | Hướng xử lý |
|---|---|---|
open | Có dịch vụ đang nhận kết nối từ ngoài | Nếu không chủ đích mở, tìm nguồn: port forwarding hoặc UPnP. Tắt dịch vụ hoặc chặn ở router |
closed | Có đường tới nhưng không có dịch vụ nghe ở port đó | Ổn. Không có gì để khai thác ở port này |
filtered | Router hoặc firewall chặn, không trả lời | Tốt, đúng nguyên tắc chặn mặc định |
Kết luận phần B4
Mạng nhà có ba lớp cần nhìn: trong nhà (những IP nội bộ và port đang nghe), ranh giới (router và NAT, có phải CGNAT không), và ngoài Internet (port nào thấy được từ bên ngoài). Mục tiêu không phải không có port nào mở, mà là mọi port mở đều có lý do và có người chịu trách nhiệm.
BÀI TẬP 6 · 10 PHÚT
Lập sơ đồ mạng nhà
Với mạng nhà bạn (hoặc mạng thử của lớp):
- Ghi IP của máy bạn và IP gateway.
- Chạy
arp -avànmap -sntrên dải mạng. Lập bảng: IP, tên thiết bị (đoán được hay không), ghi chú. - Chọn một thiết bị bạn sở hữu và liệt kê các port đang mở từ
nmap -sV --top-ports 100.
Gợi ý: nếu thấy thiết bị không nhận ra, đừng vội kết luận là xấu. Nhiều điện thoại dùng MAC ngẫu nhiên nên tên và địa chỉ có thể lạ.
Xem đáp án
- IP máy lấy từ lệnh ipconfig hoặc ip addr. Gateway thường là
.1, nhưng cần đối chiếu bằng lệnh vì không phải lúc nào cũng vậy. - Bảng có thể có vài dòng: router, máy bạn, TV thông minh, máy in, điện thoại. Thiết bị không nhận ra thì tra MAC hoặc tạm ngắt Wi-Fi từng thiết bị để xem IP nào biến mất.
- Máy của bạn có thể mở port 5000 hoặc 7000 (AirPlay Receiver trên macOS) hoặc các port tương tự. Ghi lại dịch vụ và xác nhận bạn đang cần nó.
BÀI TẬP 7 · 10 PHÚT
Đọc kết quả quét từ ngoài
Bạn quét từ mạng 4G tới IP công cộng của nhà và nhận được:
PORT STATE SERVICE
22/tcp open ssh
80/tcp filtered http
443/tcp closed https
8080/tcp open http-proxy- Port nào cần xử lý ngay? Vì sao?
- Port 443
closedcó nghĩa là website nhà đang bị lỗi hay không? Giải thích. - Nếu WAN của router là
100.72.14.9, kết quả quét có còn ý nghĩa với việc mở port trên router không?
Xem đáp án
- Port 22 (SSH) và 8080 đang
opentừ Internet. Port 22 là cổng quản trị từ xa, nếu không cần thì đóng, nếu cần thì giới hạn IP được phép. Port 8080 thường là web quản trị hoặc dịch vụ thử nghiệm, cần xác nhận thiết bị nào đang trả lời và tắt hoặc chặn nếu không chủ đích. Đây là ưu tiên cao. - Không nhất thiết.
closednghĩa là có đường tới nhưng không có dịch vụ nghe ở port 443 trên IP đó. Nếu website được đặt ở nơi khác (hosting, cloud) thì 443 của nhà đóng là đúng. Muốn chắc, hỏi lại: website đang chạy ở đâu? - Không có ý nghĩa để mở port vào nhà. Với CGNAT, IP công cộng dùng chung nên cấu hình router không đảm bảo kết nối từ ngoài. Muốn truy cập từ xa, dùng VPN hoặc dịch vụ trung gian, không mở port ra Internet.
C1. TLS và HTTPS: biến chữ rõ thành chữ mã
8 phútPhần A cho thấy vấn đề (chữ rõ), phần B cho thấy ai nằm trên đường đi. Giải pháp: , cơ chế mã hóa kênh truyền. là HTTP chạy bên trong kênh TLS, thường ở port 443. Sau khi TCP bắt tay xong, hai bên làm bắt tay TLS:
- Thống nhất phiên bản và thuật toán.
- Server gửi : gắn tên miền với khóa công khai, được ký bởi một tổ chức cấp chứng chỉ (CA) mà trình duyệt tin tưởng.
- Client kiểm tra: tên miền khớp, chưa hết hạn, chuỗi chứng chỉ dẫn tới CA tin cậy.
- Hai bên tạo khóa phiên chung và dùng khóa đó mã hóa mọi dữ liệu còn lại.
Kênh thiết lập xong cho ba bảo vệ, khớp với bài 1: bí mật (người ngoài không đọc được), toàn vẹn (sửa giữa đường bị phát hiện), xác thực máy chủ (đúng chủ của tên miền). Nhờ đó, request của Lan ở phần A1 đi qua router và nhà mạng dưới dạng dữ liệu mã hóa: người trung gian không đọc được cookie và không sửa được trang trả về mà không bị phát hiện.
HTTPS chưa giải quyết hết
| HTTPS bảo vệ | HTTPS không bảo vệ |
|---|---|
| Nội dung, header, cookie trên đường truyền | Nội dung website có trung thực hay không |
| Phát hiện bị sửa giữa đường | Phân quyền sai trong ứng dụng |
| Xác nhận đang nói với chủ của tên miền | Dữ liệu đã bị sửa sẵn trên server (bài 4) |
| Metadata: IP, thời điểm, lượng dữ liệu, thường cả tên miền |
clb-example.com hay thay l bằng 1) và xin chứng chỉ hợp lệ cho chính tên đó. Kênh vẫn mã hóa nhưng bạn đang nói chuyện với sai bên. Luôn đọc tên miền trong thanh địa chỉ.Cấu hình HTTPS đúng cho website của bạn
- Chuyển hướng (301) mọi truy cập HTTP sang HTTPS, và bật header
Strict-Transport-Security(HSTS) để trình duyệt tự dùng HTTPS từ lần sau. - Đặt cờ
Securecho cookie phiên (chỉ gửi qua HTTPS) vàHttpOnly(script trong trang không đọc được cookie). - Theo dõi hạn chứng chỉ: hết hạn thì trình duyệt cảnh báo và người dùng không vào được.
- Khi trình duyệt cảnh báo chứng chỉ, đừng bấm bỏ qua với trang có đăng nhập hay thanh toán.
BÀI TẬP 8 · 5 PHÚT
Phân tích ba cảnh báo chứng chỉ
Cho mỗi trường hợp, nêu: ý nghĩa, rủi ro, quản trị viên nên làm gì, người dùng nên làm gì.
- Chứng chỉ chỉ cấp cho
clb.example, người dùng vàowww.clb.example: "name mismatch". - Chứng chỉ hết hạn hôm qua.
- Chứng chỉ tự ký (self-signed), không có CA nào đứng sau.
Xem đáp án
- Tên trong chứng chỉ không khớp tên đang truy cập. Có thể chỉ là cấu hình thiếu, cũng có thể là máy chủ khác. Quản trị: cấp chứng chỉ bao gồm cả
www.clb.example(hoặc chuyển hướng về tên chuẩn). Người dùng: không nhập thông tin nhạy cảm, báo quản trị. - Hết hạn: kênh vẫn mã hóa được nhưng không còn bảo đảm danh tính; thường do quên gia hạn. Quản trị: gia hạn, bật gia hạn tự động và cảnh báo trước hạn. Người dùng: chờ, đừng bỏ qua cảnh báo với trang thanh toán.
- Tự ký: không ai xác nhận chủ tên miền nên kẻ giữa đường tự tạo chứng chỉ giống hệt. Chỉ chấp nhận được trong môi trường thử nghiệm nội bộ. Quản trị: dùng CA công cộng miễn phí như Let's Encrypt cho website thật. Người dùng: không tin.
C2. Lab 2: so sánh HTTP và HTTPS bằng capture
25 phútLab 1 cho thấy HTTP lộ hết. Lab này đặt cùng một request lên hai kênh, HTTP và HTTPS (HTTP chạy trong kênh ), rồi bắt gói để so sánh. Ta dùng đúng server.py vừa viết: không có tham số thì chạy HTTP ở port 8000, có --tls thì chạy HTTPS ở port 8443. Làm trong máy mình nên không cần Internet, không rủi ro và kết quả lặp lại được.
Bước 1. Tạo chứng chỉ tự ký
HTTPS cần hai file: khóa riêng (key.pem, giữ bí mật ở server) và (cert.pem, gắn tên miền với khóa công khai). Website thật xin chứng chỉ từ một tổ chức cấp (CA). Ở lab, ta tự ký cho chính mình, nên trình duyệt và curl sẽ không tin sẵn; đó là điều ta muốn quan sát. Vào thư mục network-lab (cd ~/network-lab hoặc cd $HOME\network-lab) và gõ trên một dòng:
openssl req -x509 -newkey rsa:2048 -nodes -keyout key.pem -out cert.pem -days 7 -subj "/CN=localhost" -addext "subjectAltName=DNS:localhost,IP:127.0.0.1"& "C:\Program Files\Git\usr\bin\openssl.exe" req -x509 -newkey rsa:2048 -nodes -keyout key.pem -out cert.pem -days 7 -subj "/CN=localhost" -addext "subjectAltName=DNS:localhost,IP:127.0.0.1"openssl req -x509 -newkey rsa:2048 -nodes -keyout key.pem -out cert.pem -days 7 -subj "/CN=localhost" -addext "subjectAltName=DNS:localhost,IP:127.0.0.1"
# Chưa có openssl: sudo apt install openssl| Phần | Ý nghĩa |
|---|---|
openssl req | Công cụ OpenSSL, nhóm lệnh req: tạo yêu cầu chứng chỉ. |
-x509 | Thay vì gửi yêu cầu cho CA, tự ký luôn và xuất ra chứng chỉ. Đây là điểm khiến chứng chỉ thành "tự ký". |
-newkey rsa:2048 | Tạo luôn một khóa riêng mới, kiểu RSA 2048 bit. |
-nodes | Không đặt mật khẩu cho khóa riêng để server khởi động không bị hỏi. Chỉ chấp nhận ở lab. |
-keyout key.pem / -out cert.pem | Tên file khóa riêng và tên file chứng chỉ sẽ được tạo trong thư mục hiện tại. |
-days 7 | Chứng chỉ chỉ có hiệu lực 7 ngày. Dùng ngắn cho đồ thử nghiệm. |
-subj "/CN=localhost" | Tên chủ chứng chỉ (Common Name) là localhost, tên máy này. |
-addext "subjectAltName=..." | Danh sách tên và IP mà chứng chỉ được phép đại diện. Trình duyệt và curl hiện đại chỉ kiểm tra mục này. Thiếu nó sẽ gặp lỗi "name mismatch" (bài tập 8). |
Windows | Máy chưa có Git for Windows thì cài tại git-scm.com (đi kèm openssl), hoặc mở Git Bash và gõ đúng lệnh macOS/Linux ở trên. |
Generating a RSA private key
..+++++
writing new private key to 'key.pem'
-----Kiểm tra bằng ls hoặc dir: có thêm cert.pem và key.pem.
Bước 2. Chạy cùng lúc server HTTP và server HTTPS
Cần hai server song song nên dùng hai terminal, cả hai đều cd vào network-lab:
python3 server.pypython3 server.py --tlspy server.pypy server.py --tlspython3 server.pypython3 server.py --tlsTerminal A: Dang chay tai http://127.0.0.1:8000/ (Ctrl+C de dung)
Terminal B: Dang chay tai https://127.0.0.1:8443/ (Ctrl+C de dung)Lỗi FileNotFoundError: cert.pem ở Terminal B nghĩa là bạn đang đứng sai thư mục hoặc chưa làm xong bước 1. Mở thêm Terminal C (cũng trong network-lab) để gõ lệnh curl.
Bước 3. Gọi HTTPS và xem TLS làm gì
3a. Gọi khi chưa tin chứng chỉ. Ở Terminal C:
curl https://localhost:8443/curl: (60) SSL certificate problem: self signed certificate
More details here: https://curl.se/docs/sslcerts.htmlĐây chính là trường hợp "chứng chỉ tự ký" của bài tập 8: kênh có thể mã hóa được, nhưng không có CA nào bảo đảm rằng chủ của localhost là bạn, nên curl từ chối. Trình duyệt cũng vậy: vào https://localhost:8443/ sẽ thấy trang cảnh báo đỏ ("Your connection is not private"). Ở lab này bấm tiếp tục là chấp nhận được vì chính bạn tạo ra chứng chỉ; với trang đăng nhập hay thanh toán thật thì không bao giờ bấm bỏ qua.
3b. Chỉ rõ chứng chỉ nào được tin. Thay vì tắt kiểm tra, ta bảo curl tin đúng file cert.pem của mình:
curl -i --cacert cert.pem https://localhost:8443/| Phần | Ý nghĩa |
|---|---|
--cacert cert.pem | Chỉ định CA (hoặc chứng chỉ) được tin. Vì cert.pem tự ký nên nó cũng là "CA" của chính nó. Nhờ tên localhost khớp trong subjectAltName nên kiểm tra tên cũng qua. |
https://localhost:8443/ | Scheme https:// bảo curl bắt tay TLS trước khi gửi HTTP; 8443 là port ta chọn cho server HTTPS. |
Không dùng -k | -k (--insecure) tắt hẳn kiểm tra chứng chỉ, tức là chấp nhận cả máy chủ giả. Đừng tập thói quen này, nhất là trong script triển khai. |
HTTP/1.0 200 OK
Server: BaseHTTP/0.6 Python/3.9.6
Content-Type: text/html; charset=utf-8
Content-Length: 37
<h1>Cau lac bo - Lich sinh hoat</h1>Nội dung y hệt khi dùng HTTP: người dùng cuối không nhìn thấy khác biệt, khác biệt nằm trên đường truyền. Giờ gửi POST của Lan qua HTTPS:
curl -i --cacert cert.pem -X POST -H "Cookie: phien=demo123" -d "ten=Lan&so_tien=200000&ghi=ok" https://localhost:8443/dong-phiNhìn Terminal B: server vẫn in ra đủ phien=demo123 và ten=Lan. Server là một đầu của kênh nên đọc được hết; điều TLS làm là khiến người đứng giữa không đọc được.
3c. Xem bắt tay TLS từ phía client. Thêm -v (verbose) để curl kể từng bước:
curl -v --cacert cert.pem https://localhost:8443/* Host localhost:8443 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
* Trying [::1]:8443...
* connect to ::1 port 8443 failed: Connection refused
* Trying 127.0.0.1:8443...
* Connected to localhost (127.0.0.1) port 8443
* (304) (OUT), TLS handshake, Client hello (1):
* (304) (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
...
> GET / HTTP/1.1Đọc theo thứ tự: tên localhost được đổi thành IP (DNS, B1); curl thử IPv6 ::1 bị từ chối vì server chỉ nghe IPv4 127.0.0.1, rồi quay về IPv4 (bình thường, liên quan đến bài 5); TCP kết nối xong; sau đó mới đến Client hello, Server hello, Certificate, Finished của TLS; chỉ sau cùng mới là dòng GET / HTTP/1.1 được gửi trong kênh đã mã hóa. Đúng thứ tự DNS → TCP → TLS → HTTP của phần D.
Bước 4. Bắt gói và so sánh hai kênh
- Mở Wireshark, bắt trên giao diện loopback như Lab 1 (macOS
lo0, Linuxlo, Windows Npcap Loopback). Bắt đầu capture trước khi gõ lệnh. - Ở Terminal C gửi lần lượt hai POST giống hệt nhau, một HTTP và một HTTPS:
curl -i -X POST -H "Cookie: phien=demo123" -d "ten=Lan&so_tien=200000&ghi=ok" http://127.0.0.1:8000/dong-phicurl -i --cacert cert.pem -X POST -H "Cookie: phien=demo123" -d "ten=Lan&so_tien=200000&ghi=ok" https://localhost:8443/dong-phi- Dừng capture. Lọc hai kênh cùng lúc:
tcp.port == 8000 || tcp.port == 8443Cột Protocol của luồng port 8000 ghi HTTP; luồng port 8443 ghi TLSv1.2 hoặc TLSv1.3. Nếu luồng 8443 chỉ hiện TCP, chuột phải vào một gói của nó → Decode As… → đặt TCP port 8443 thành TLS → OK.
- Nhấp vào các dòng của luồng 8443 và mở khung giữa. Bạn sẽ thấy lần lượt:
| Gói | Ý nghĩa | Thấy gì |
|---|---|---|
| TCP SYN / SYN-ACK / ACK | Bắt tay TCP (phần B3) | Không mã hóa, giống Lab 1 |
| Client Hello | Client chào, đề xuất thuật toán | Mở Extension: server_name: thấy tên localhost ở dạng chữ rõ. Đây là lý do tên miền thường vẫn lộ với HTTPS |
| Server Hello (rồi Certificate nếu là TLS 1.2) | Server chọn thuật toán và gửi chứng chỉ | Với TLS 1.2 mở được chứng chỉ, thấy CN=localhost. Với TLS 1.3 chứng chỉ đã được mã hóa nên không có dòng riêng |
| Application Data | Dữ liệu HTTP bên trong kênh | Chỉ còn byte vô nghĩa. Không thấy POST, cookie hay body |
- Chuột phải vào một gói của luồng 8443 → Follow → TCP Stream: chỉ là ký tự lộn xộn. So với luồng 8000 vừa đọc được trọn vẹn request.
- Phép thử quyết định. Gõ ô lọc sau và Enter:
frame contains "demo123"frame contains "so_tien"Chỉ gói của luồng port 8000 hiện ra. Không có gói nào ở port 8443 chứa chuỗi này, dù cùng một cookie và cùng một body đã được gửi. Đó là sự khác biệt giữa HTTP và HTTPS, tự bạn chứng minh bằng dữ liệu của chính mình.
Bước 5 (tùy chọn). Thử với một website thật
Muốn thấy cả DNS, hãy bắt trên giao diện Wi-Fi hoặc Ethernet thật (không phải loopback), đóng ứng dụng không cần thiết và không đăng nhập thứ nhạy cảm trong lúc bắt. Dùng example.com, trang mẫu công khai:
nslookup example.com
curl --http1.1 -I https://example.com--http1.1 ép HTTP/1.1 cho dễ quan sát; -I chỉ lấy header (method HEAD). Trên Windows PowerShell dùng curl.exe. Dừng capture, lọc lần lượt dns, tcp, tls. Bạn thấy truy vấn DNS (chữ rõ, ai cũng đọc được tên bạn tra), bắt tay TCP, bắt tay TLS với server_name là example.com, rồi chỉ còn Application Data. Truy vấn DNS và kết nối HTTPS có thể ra IP khác nhau (cache, IPv4/IPv6, cân bằng tải), nên đừng ghép hai dòng chỉ vì chúng gần nhau.
Dọn dẹp
Ở mỗi terminal đang chạy server nhấn Ctrl + C. Xóa khóa riêng và file capture bạn không còn cần: rm key.pem cert.pem (macOS/Linux) hoặc del key.pem, cert.pem (Windows); file .pcapng xóa bằng trình quản lý file vì có thể chứa dữ liệu luồng khác. Có thể giữ thư mục network-lab để làm lại.
BÀI TẬP 9 · 10 PHÚT
Điền bảng "ai thấy gì"
Từ hai lab, điền bảng cho một request HTTP (Lab 1) và một request HTTPS (Lab 2). Mỗi ô ghi "thấy" hoặc "không thấy" đối với người bắt gói ở giữa đường:
| Thông tin | HTTP | HTTPS |
|---|---|---|
| IP và port đích | ? | ? |
| Tên miền truy cập | ? | ? |
| Đường dẫn và method (GET /…) | ? | ? |
| Cookie | ? | ? |
| Nội dung trang | ? | ? |
| Truy vấn DNS (DNS thường) | ? | ? |
Câu hỏi thêm: nếu kẻ giữa đường cố sửa số tài khoản trong trang HTTPS, chuyện gì xảy ra?
Xem đáp án
| Thông tin | HTTP | HTTPS |
|---|---|---|
| IP và port đích | Thấy | Thấy |
| Tên miền truy cập | Thấy (Host header, DNS) | Thường thấy (DNS, Server Name trong TLS) |
| Đường dẫn và method | Thấy | Không thấy |
| Cookie | Thấy | Không thấy |
| Nội dung trang | Thấy | Không thấy |
| Truy vấn DNS (DNS thường) | Thấy | Thấy |
Sửa giữa đường: TLS kiểm tra toàn vẹn nên dữ liệu bị sửa làm bắt tay hoặc giải mã thất bại, kết nối bị ngắt thay vì hiển thị trang sai. Metadata (IP, tên miền, lượng dữ liệu) vẫn lộ, đó là lý do HTTPS giảm rủi ro chứ không xóa hết.
D. Chẩn đoán theo lớp và rà soát website
15 phútHành trình đi qua nhiều lớp, và mỗi lớp lỗi cho một dấu hiệu khác. Biết thứ tự này, thay vì sửa ngẫu nhiên, bạn đọc dấu hiệu để chọn đúng lớp kiểm tra:
| Dấu hiệu | Lớp nghi ngờ | Kiểm tra tiếp |
|---|---|---|
| Không tra được tên | DNS | Tên, resolver, loại bản ghi |
| Có IP nhưng không kết nối được | Mạng, firewall, dịch vụ | Đích, port, tuyến, firewall, server có lắng nghe không |
| TCP có, TLS lỗi | Chứng chỉ, cấu hình TLS | Tên khớp, hạn dùng, chuỗi tin cậy |
| TLS có, HTTP 403 | Quyền, cấu hình ứng dụng | Quy tắc truy cập, đường dẫn |
| HTTP 200 nhưng dữ liệu sai | Ứng dụng, dữ liệu, cache | Nghiệp vụ, bản ghi, lịch sử sửa (bài 4) |
Khi gắn thêm tên miền mới vào cùng máy chủ, phải đúng cả bốn lớp: DNS trỏ đúng máy; web server biết tên mới thuộc website nào; chứng chỉ TLS có tên mới; ứng dụng chỉnh URL chuẩn và cookie. "Đã trỏ A record đúng" chỉ là một quan sát ở lớp DNS, chưa phải kết luận mọi thứ xong.
BÀI TẬP 10 · 8 PHÚT
Chẩn đoán năm tình huống
Với mỗi tình huống, nêu lớp nghi ngờ nhất và việc kiểm tra đầu tiên:
nslookup clb.examplebáo "NXDOMAIN" (không tồn tại).- Tra DNS ra IP đúng,
curltreo rồi báo "connection timed out". - Kết nối được nhưng trình duyệt báo "certificate expired".
- Trang mở được nhưng thành viên thường thấy 403 khi vào trang danh sách.
- Số tài khoản hiển thị sai nhưng mọi thứ trả mã 200 và có ổ khóa.
Xem đáp án
- DNS: bản ghi chưa có hoặc tên miền hết hạn. Kiểm tra bản ghi tại nhà đăng ký và hạn tên miền.
- Mạng/firewall/dịch vụ: gói đi mà không có phản hồi nên thường là firewall chặn hoặc server không lắng nghe. Kiểm tra port có mở, server có chạy, bắt gói xem có SYN mà không thấy SYN/ACK.
- TLS: chứng chỉ hết hạn. Gia hạn và bật tự động gia hạn.
- Ứng dụng: 403 là phân quyền (đúng cho thành viên thường nếu danh sách chỉ dành cho người phụ trách). Kiểm tra quy tắc quyền, không phải router.
- Dữ liệu: HTTPS và 200 không bảo đảm toàn vẹn. Xem lịch sử chỉnh sửa, quyền sửa, log (bài 4), đối chiếu bản đã duyệt.
BÀI TẬP 11 · Về nhà, 20 PHÚT
Rà soát một website bằng danh sách kiểm tra
Chọn website của câu lạc bộ (hoặc website bạn có quyền kiểm tra) và điền bảng. Mỗi mục ghi Đạt, Chưa đạt hoặc Chưa biết, kèm bằng chứng (lệnh đã chạy, ảnh chụp):
| Mục | Cách kiểm tra |
|---|---|
| 1. Tài khoản tên miền có MFA, email khôi phục còn thuộc quyền | Đăng nhập nhà đăng ký, xem cài đặt bảo mật |
| 2. Tên miền và chứng chỉ còn hạn trên 30 ngày | Xem hạn ở nhà đăng ký; bấm vào ổ khóa xem chứng chỉ |
| 3. HTTP tự chuyển sang HTTPS | curl -I http://tên-miền, tìm mã 301 và dòng Location: https://… |
| 4. Có header HSTS | curl -I https://tên-miền, tìm Strict-Transport-Security |
5. Cookie phiên có Secure và HttpOnly | Công cụ nhà phát triển của trình duyệt, mục Application → Cookies |
| 6. Chỉ mở các port cần thiết | Hỏi nhà cung cấp hosting danh sách quy tắc firewall |
| 7. File nhạy cảm không nằm trong thư mục công khai | Thử truy cập đường dẫn tới file danh sách thành viên mà không đăng nhập |
Chỉ kiểm tra website của mình hoặc nơi được cho phép; các lệnh trên là yêu cầu thông thường, không dò quét.
Xem đáp án
Không có đáp án duy nhất. Một báo cáo tốt: mỗi mục có kết quả và bằng chứng; mục "Chưa đạt" kèm cách sửa và người chịu trách nhiệm; mục "Chưa biết" ghi rõ cần ai xác nhận. Xếp thứ tự xử lý theo rủi ro (bài 2): mất quyền tên miền và lộ dữ liệu thành viên nặng hơn thiếu HSTS.
Tóm tắt
- Mạch bài: nội dung (HTTP chữ rõ) → đường đi (DNS, NAT, firewall, TCP) → bảo vệ (TLS/HTTPS) → chẩn đoán.
- không mã hóa lộ cookie, mật khẩu và nội dung cho mọi thiết bị trên đường đi.
- không mã hóa; tài khoản tên miền cần MFA vì sửa bản ghi là chuyển được cả website.
- không phải . Firewall chặn mặc định, chỉ mở port cần thiết. SYN flood là một dạng .
- cho bí mật, toàn vẹn, xác thực máy chủ, nhưng không bảo đảm website trung thực hay ứng dụng phân quyền đúng.
- Chẩn đoán theo lớp: DNS, TCP/firewall, TLS, HTTP, ứng dụng.
Tự kiểm tra · 5 câu có giải thích +
Ghi chú cá nhân +
Tự lưu trên trình duyệt. Không nhập thông tin bí mật.