1. Giới thiệu
Khi nhắc đến quy trình kết nối giữa client và server, nhiều người cho rằng chỉ đơn giản là gửi yêu cầu và nhận phản hồi. Tuy nhiên, thực tế cho thấy rằng phía sau mỗi kết nối thành công là một hệ thống phức tạp với nhiều bước phối hợp giữa client, server và hệ điều hành. Bài viết này sẽ phân tích chi tiết từng giai đoạn trong cơ chế kết nối để các bạn có cái nhìn toàn diện hơn về cách thức hoạt động này.
2. Quy Trình Kết Nối
Trong quá trình phát triển ứng dụng, chúng ta thường chú trọng vào việc tối ưu hóa cơ sở dữ liệu, lập trình và nhiều giải pháp khác. Nhưng một khía cạnh quan trọng mà ít người chú ý đến chính là quy trình giao tiếp mạng giữa client và server.
Bài viết này sẽ trình bày cụ thể quy trình thiết lập kết nối giữa client và server, đồng thời sẽ chỉ ra những vấn đề thường gặp trong thực tế và cách khắc phục chúng.
3. Các Vấn Đề Thường Gặp
Vấn Đề Bảo Mật: Đợi Gói ACK
Lỗ hổng bảo mật: Trong khi chờ gói ACK cuối cùng từ client để hoàn tất kết nối, các client độc hại có thể lợi dụng lỗ hổng này để thực hiện các cuộc tấn công từ chối dịch vụ (DoS). Cách thức diễn ra là client gửi gói SYN và nhận gói SYN-ACK từ server nhưng không gửi gói ACK cuối cùng, dẫn đến việc chiếm giữ một "slot" trong hàng đợi SYN, khiến hàng đợi này nhanh chóng đầy. Kẻ tấn công có thể thực hiện hành vi này nhiều lần, dẫn đến việc server không thể chấp nhận thêm kết nối mới.
Giải pháp: Sử dụng SYN Cookies giúp server không lưu trữ trạng thái kết nối (stateless) mà mã hóa thông tin cần thiết vào gói SYN-ACK. Chỉ khi client gửi lại gói ACK, thông tin mới được khôi phục và kết nối hoàn tất. Thêm vào đó, thiết lập Timeout để server hủy kết nối nếu không nhận được gói ACK trong khoảng thời gian nhất định (ví dụ: 100-520ms).
Tình Huống Không Gọi Hàm Accept
Nếu ứng dụng backend không gọi hàm accept vì lý do nào đó: như bị treo hoặc xử lý không kịp, kết nối sẽ tồn tại trong hàng đợi accept cho đến khi hết thời gian chờ hoặc kernel không thể thêm kết nối hoàn chỉnh nào vào hàng đợi này do đã đầy.
Điều này gây ra nhiều vấn đề nghiêm trọng:
- Hàng đợi accept đầy dẫn tới việc kernel không thể xử lý thêm các gói SYN mới từ client.
- Kết quả là các kết nối mới từ client sẽ bị từ chối hoặc thất bại.
Giải pháp:
- Tối ưu hóa hiệu suất backend: Gọi hàm accept nhanh chóng để giải phóng các kết nối trong hàng đợi, tăng cường khả năng xử lý nhiều kết nối song song, ví dụ bằng cách sử dụng mô hình đa luồng hoặc đa tiến trình.
- Phát hiện và xử lý kết nối độc hại: Sử dụng dịch vụ bảo mật như Cloudflare để phát hiện hành vi xâm nhập và bảo vệ hệ thống khỏi các cuộc tấn công DoS/DDoS.
- Cấu hình accept queue: Tăng kích thước hàng đợi accept để xử lý nhiều kết nối hơn. Tuy nhiên, đây chỉ là giải pháp tạm thời và cần kết hợp với các biện pháp tối ưu hóa khác.
4. Thông Tin Liên Hệ
Nếu bạn muốn thảo luận thêm về bài viết này, hãy liên hệ với mình qua các kênh mạng xã hội dưới đây:
- LinkedIn: https://www.linkedin.com/in/nguyentrungnam/
- Facebook: https://www.facebook.com/trungnam.nguyen.395/
Rất mong được kết nối và cùng thảo luận!
source: viblo