TCP và UDP: hiểu kết nối, cổng và dấu hiệu lỗi

Phân biệt TCP, UDP và cổng dịch vụ qua handshake, ACK, datagram và dấu hiệu timeout. Đọc kết quả kiểm tra theo từng lớp trước khi thay đổi mạng.
Máy tính ping được máy chủ nhưng phần mềm vẫn báo timeout. Một người đề nghị mở cổng 443, người khác muốn đổi DNS. Cả hai đề xuất đều thiếu một dữ kiện: kết nối đang dùng TCP hay UDP, và phép thử đã dừng ở giai đoạn nào? Địa chỉ IP chỉ đưa lưu lượng tới host; việc giao dữ liệu cho tiến trình ứng dụng còn phụ thuộc giao thức vận chuyển, cổng và trạng thái ở hai đầu.
Bài này nối tiếp đường đi ra Internet, dùng client 192.168.10.20 và server minh họa 203.0.113.80. Ta phân tích TCP cho HTTPS, rồi so với UDP qua truy vấn DNS. Ví dụ sequence, port và output đều được biên tập để giải thích, chưa phải capture thực nghiệm. IP thuộc TEST-NET không phải dịch vụ để thử trực tiếp.
1. Định danh một luồng trước khi đọc trạng thái
Client có thể đồng thời mở nhiều tab tới một server. Để phân biệt các kết nối TCP, cần cặp địa chỉ và cổng ở hai đầu; khi mô tả luồng nói chung còn ghi giao thức vận chuyển. Một ví dụ là TCP từ 192.168.10.20:51514 tới 203.0.113.80:443. Nếu tab khác dùng port nguồn 51515, đó là kết nối khác dù cùng server và dịch vụ.
Port không phải ổ cắm vật lý trên switch. Nó là số trong header vận chuyển được hệ điều hành dùng để phân phối dữ liệu tới socket thích hợp. TCP 53 và UDP 53 thuộc hai không gian giao thức khác nhau; firewall cho phép một bên không tự cho phép bên còn lại. Trong bảng NAT/PAT, địa chỉ và port còn có thể đổi giữa các điểm quan sát.
Registry của IANA cho biết tên dịch vụ và cổng được đăng ký. Đăng ký đó không xác nhận mọi lưu lượng tại port mang đúng ứng dụng đã ghi. Một server có thể chạy HTTPS ở port khác, và một tiến trình không mong muốn cũng có thể lắng nghe ở 443. Khi điều tra, đối chiếu cấu hình, tiến trình và lưu lượng thực tế.
Đừng mặc định port nguồn luôn nằm trong cùng dải trên mọi hệ điều hành. Việc chọn cổng tạm thời phụ thuộc cấu hình và hệ thống. Con số 51514 trong bài chỉ giúp theo dõi một phiên; nó không phải điều kiện bắt buộc để HTTPS hoạt động hay một giá trị nên gán thủ công cho trình duyệt.
2. TCP thiết lập trạng thái bằng handshake
Trong trường hợp mở kết nối thông thường, client gửi SYN với sequence ban đầu. Server trả SYN-ACK, rồi client xác nhận bằng ACK. Hai phía có thể thương lượng các tùy chọn, chẳng hạn MSS và window scaling. MSS liên quan lượng dữ liệu TCP, không đồng nghĩa kích thước toàn frame Ethernet; các header và tùy chọn còn chiếm chỗ riêng.
Đặc tả TCP hiện hành, RFC 9293, là nguồn đối chiếu cho trạng thái và ngữ nghĩa header. Để đọc ví dụ đơn giản, giả sử SYN của client có SEQ 1000 và SYN của server có SEQ 7000. SYN chiếm một vị trí sequence, nên SYN-ACK xác nhận 1001, còn ACK cuối xác nhận 7001. Đây là số tuyệt đối giả định; công cụ capture có thể hiển thị số tương đối.

Cuộn ngang khi cần, hoặc chạm sơ đồ để mở ảnh gốc.
Nếu client sau đó gửi đúng 100 byte bắt đầu từ SEQ 1001 và phía nhận đã có toàn bộ dải đó, ACK có thể là 1101. Một ACK có thể xác nhận nhiều segment, không bắt buộc mỗi segment đều có một ACK riêng. Khi đọc capture, cần chú ý delayed ACK, retransmission và việc công cụ có quan sát được cả hai chiều hay không.
SYN được gửi chưa chứng minh server nhận được nó. SYN-ACK quay về chứng minh thêm rằng phản hồi đã tới điểm quan sát, nhưng chưa chứng minh TLS hoặc nghiệp vụ thành công. Thậm chí khi TCP established, server vẫn có thể trả lỗi HTTP, thiếu tài nguyên xử lý hoặc đóng phiên theo chính sách ứng dụng.
3. Dữ liệu TCP là luồng byte, không giữ ranh giới thông điệp ứng dụng
Ứng dụng có thể ghi hai đoạn dữ liệu, nhưng bên nhận không được giả định sẽ đọc đúng hai đoạn tương ứng. TCP cung cấp luồng byte có thứ tự; việc chia thông điệp cần framing của giao thức ứng dụng, như độ dài, ký tự phân cách hoặc quy tắc HTTP. Một TLS record cũng có thể trải qua nhiều TCP segment.
Khi mất dữ liệu, TCP có cơ chế phát hiện và truyền lại. Cơ chế này giúp ứng dụng tránh tự xây toàn bộ lớp vận chuyển tin cậy, nhưng không cam kết độ trễ hoặc thời hạn hoàn thành. Dữ liệu tới chậm vẫn có thể vô ích cho một thao tác đã hết deadline. Bộ đếm retransmission tăng là dấu hiệu cần phân tích, không tự chỉ ra dây mạng tại client đang hỏng.
Flow control giúp phía gửi tôn trọng khả năng nhận của bên kia; congestion control điều chỉnh việc gửi theo tình trạng mạng. Hai nhiệm vụ có liên quan nhưng không đồng nhất. Receiver window nhỏ, mất gói hoặc hàng đợi giữa đường có thể tạo triệu chứng tốc độ thấp tương tự nhau. Không tăng buffer mù quáng trước khi xác định loại giới hạn đang gặp.
FIN thể hiện kết thúc gửi theo hướng của một bên, còn RST hủy hoặc từ chối theo ngữ cảnh của phiên. Vì vậy “thấy RST là server chết” không phải kết luận an toàn. Một firewall có thể gửi reset, một kết nối tới port không lắng nghe cũng có thể bị reset, và ứng dụng có thể chủ động hủy phiên đã mở.
4. UDP giữ datagram nhưng không tự làm việc của TCP
UDP có header cơ bản ngắn, gồm port nguồn/đích, length và checksum. Theo RFC 768, giao thức này không tự cung cấp bắt tay, ACK hay retransmission như TCP. Mỗi lần ứng dụng nhận một UDP datagram thành công vẫn có ranh giới thông điệp; không xem nó như một luồng byte liên tục.
Nói “UDP không tin cậy” là nói về bảo đảm do lớp UDP cung cấp, không có nghĩa ứng dụng chạy trên nó luôn bỏ mặc mất gói. Ứng dụng có thể thêm xác nhận, số thứ tự, retry và điều khiển tắc nghẽn. QUIC là một ví dụ quan trọng: nó chạy trên UDP nhưng có cơ chế vận chuyển và bảo mật ở phía trên; xem RFC 9000.

Cuộn ngang khi cần, hoặc chạm sơ đồ để mở ảnh gốc.
Ví dụ DNS truyền thống thường bắt đầu bằng UDP 53, nhưng DNS còn dùng TCP và các hình thức được mã hóa khác. Một phản hồi UDP bị cắt ngắn có thể dẫn tới truy vấn lại bằng TCP theo khả năng và quy tắc của resolver. Chỉ mở UDP 53 rồi khẳng định DNS luôn đủ là một thiết kế thiếu điều kiện; RFC 7766 giải thích yêu cầu hỗ trợ TCP cho DNS.
Gói UDP lớn có thể dẫn tới phân mảnh IP hoặc vượt khả năng đường đi, tùy phiên bản IP và cấu hình. Mất một mảnh có thể làm cả datagram không được tái lắp. Bởi vậy, header nhỏ không tự biến UDP thành lựa chọn tốt cho mọi payload lớn. Cần chọn kích thước và cách phục hồi theo giao thức ứng dụng.
5. Đọc timeout, refused và im lặng theo đúng mức bằng chứng
Timeout nghĩa phép chờ đã hết theo giới hạn của công cụ hoặc ứng dụng. Nó không tự phân biệt host tắt, ACL drop, sai tuyến, mất đường về, nghẽn hay server xử lý chậm. Với TCP, capture thấy SYN lặp mà không có phản hồi tại client chỉ mô tả điều client quan sát; muốn biết gói dừng ở đâu cần thêm điểm đo.
Connection refused thường tương ứng một sự từ chối kết nối được báo lại nhanh, ví dụ TCP reset khi không có listener. Nó hữu ích để phân biệt với chờ im lặng, nhưng vẫn cần xác định ai tạo phản hồi. Đừng đổi DNS chỉ vì nhận một reset từ đúng IP, và đừng tắt firewall toàn bộ để chứng minh giả thuyết.

Cuộn ngang khi cần, hoặc chạm sơ đồ để mở ảnh gốc.
UDP không có handshake chung, nên một datagram không được trả lời có thể là yêu cầu sai định dạng, dịch vụ im lặng theo thiết kế, gói bị lọc hoặc port không có listener. ICMP port unreachable là một dữ kiện khác, nhưng không được bảo đảm luôn quay lại. Kiểm tra UDP nên dùng request hợp lệ của chính giao thức và đối chiếu log phía server.
Khi chỉ một số người dùng lỗi, hãy so sánh IP nguồn, đường NAT, resolver và endpoint thực tế. Một tên miền có thể dẫn tới nhiều server khác nhau. Hai lần thử cùng tên nhưng khác IP không phải hai phép đo hoàn toàn tương đương; ghi cả tên và IP đã kết nối giúp đội vận hành tái hiện vấn đề.
6. Dùng lệnh đọc trạng thái và ghi lại phạm vi phép thử
Trên Windows 11, PowerShell có thể dùng lệnh dưới đây với host thực tế được phép kiểm tra. Tên mẫu là placeholder phải thay trước khi chạy; bài không hướng dẫn quét cổng hoặc dò tìm hệ thống bên ngoài.
Test-NetConnection -ComputerName <may-chu-duoc-phep> -Port 443
Get-NetTCPConnection -State Established
Get-NetUDPEndpoint
Test-NetConnection kiểm tra TCP khi dùng -Port; không coi nó là phép kiểm tra UDP. Hai lệnh liệt kê endpoint đọc trạng thái cục bộ, không phải danh sách kết nối đã được server xác nhận. Quyền đọc thông tin hoặc tiến trình có thể khác tùy máy.
Trên Linux có iproute2, ss -tn hiển thị socket TCP, còn ss -un hiển thị socket UDP. Thêm tùy chọn listener hoặc process cần hiểu phạm vi và quyền; không chia sẻ output nguyên trạng nếu có địa chỉ, ứng dụng nội bộ hoặc thông tin quản trị nhạy cảm.
Trong ticket, ghi giờ thử, giao thức, cặp IP/port, trạng thái kết nối và kết quả ứng dụng. Nếu đã có TCP established nhưng TLS lỗi, bổ sung tên máy chủ, nội dung lỗi chứng chỉ và thời gian hệ thống. Không ghi mật khẩu, cookie hoặc token vào ticket để “cung cấp đủ dữ liệu”.
7. Kiểm tra lại cách suy luận trước khi chuyển sang địa chỉ IP
Ba câu hỏi nên trả lời được là: vì sao TCP 53 khác UDP 53; tại sao established không chứng minh thao tác lưu đơn thành công; và vì sao UDP im lặng chưa có nghĩa port đóng? Câu trả lời cần nói tới protocol namespace, lớp ứng dụng và việc UDP không có thủ tục phản hồi chung.
Hãy thử giải thích một luồng TCP gồm IP/cổng trước và sau PAT bằng sơ đồ bài trước. Sau đó đổi một điều kiện: server trả HTTP 403 sau khi TCP/TLS thành công. Phép kiểm tra tiếp theo thuộc quyền truy cập ứng dụng, không phải phép chia subnet. Khi tách được các tầng như vậy, đọc IPv4 và subnetting để tính đúng địa chỉ nguồn, đích và gateway trước khi kiểm tra transport.