Kiến thức tiên quyết
Đầu tiên, hãy xem xét các bit điều khiển và máy trạng thái của TCP, là cơ sở để hiểu về quá trình bắt tay ba bước của TCP.
Các bit điều khiển gói TCP
Các bit điều khiển trong tiêu đề gói TCP được sử dụng để điều khiển trạng thái của kết nối TCP và có thể chỉ ra nhiều thông tin điều khiển như thiết lập kết nối, kết thúc, đặt lại, v.v.
Có sáu bit điều khiển phổ biến:
- SYN (Đồng bộ hóa số thứ tự): Yêu cầu thiết lập kết nối (một phần của quá trình bắt tay ba bước). Nó được đặt trong gói ban đầu trong quá trình thiết lập kết nối, cho biết người gửi muốn thiết lập kết nối và đồng bộ hóa số thứ tự. Vì TCP là song hướng, cả hai bên đều cần gửi SYN khi thiết lập kết nối. Mặc dù các gói SYN không thể mang dữ liệu, nhưng chúng vẫn tiêu thụ một số thứ tự.
- ACK (Trường xác nhận có ý nghĩa): Xác nhận dữ liệu đã nhận. Khi cờ ACK được đặt, máy thu sẽ điền vào số thứ tự tiếp theo dự kiến trong trường xác nhận. Một gói ACK không mang dữ liệu sẽ không tiêu thụ số thứ tự.
- FIN (Không còn dữ liệu từ người gửi): Yêu cầu kết thúc kết nối (một phần của quá trình ngắt kết nối bốn bước). Nó được đặt trong gói sau khi tất cả dữ liệu đã được gửi, thông báo cho máy thu rằng người gửi đã hoàn tất việc gửi tất cả dữ liệu. Vì TCP là song hướng, cả hai bên đều cần gửi FIN khi đóng kết nối. Mặc dù các gói FIN không mang dữ liệu, nhưng chúng vẫn tiêu thụ một số thứ tự.
- RST (Đặt lại kết nối): Đặt lại kết nối, được sử dụng để kết thúc kết nối bất thường hoặc lỗi. Khi máy thu nhận được cờ RST, nó sẽ ngay lập tức kết thúc kết nối mà không cần xác nhận dữ liệu nào. Ví dụ, vấn đề TIME_WAIT được đề cập trong các bài viết trước. Lưu ý: Sự hiện diện của các gói RST trong môi trường sản xuất thường cho thấy các vấn đề tiềm ẩn.
- PSH (Chức năng đẩy): Cho biết máy thu rằng dữ liệu đã nhận nên được chuyển đến lớp ứng dụng ngay lập tức, cho thấy dữ liệu nên được xử lý nhanh chóng hơn là chờ đợi thêm dữ liệu tiếp theo.
- URG (Trường con trỏ khẩn cấp có ý nghĩa): Cho biết dữ liệu có mức độ ưu tiên cao và nên được máy thu xử lý càng sớm càng tốt.
- ECE (ECN-Echo): Cho biết liệu cả hai bên đã đàm phán hỗ trợ Thông báo tắc nghẽn rõ ràng trong quá trình bắt tay ba bước hay chưa.
Số thứ tự (Seq)
Vì TCP là song hướng, cả hai bên của một kết nối đơn đều có thể gửi dữ liệu cho nhau, vì vậy mỗi bên phải duy trì trường Seq của riêng mình.
Seq được tạo động và ngẫu nhiên, giúp ngăn chặn các gói giả mạo đặt lại kết nối (tấn công RST).
TCP cung cấp truyền dẫn có thứ tự, vì vậy mỗi phân đoạn dữ liệu phải bao gồm một trường số Seq:
- Khi máy thu nhận được các gói không theo thứ tự, nó có thể sắp xếp lại chúng dựa trên Seq.
- Khi máy thu nhận được các gói trùng lặp, nó có thể loại bỏ trùng lặp dựa trên Seq.
Như hình vẽ, phương pháp tăng số thứ tự (quan trọng):
- Đối với phân đoạn 1, nếu số Seq bắt đầu là 1 và độ dài là 1448 byte, thì số Seq của phân đoạn 2 sẽ là 1 + 1448 = 1449.
- Nếu độ dài của phân đoạn 2 cũng là 1448, thì số Seq của phân đoạn 3 sẽ là 1449 + 1448 = 2897.
Nói cách khác, kích thước của một số Seq được tính bằng cách cộng số Seq và độ dài của phân đoạn trước đó.
Seq = Seq của phân đoạn trước + Độ dài (Len)
Do đó, trong quá trình truyền dữ liệu TCP, các phân đoạn được gửi bởi bất kỳ bên nào cũng phải liên tục: số Seq của gói tiếp theo bằng Seq của gói trước đó + Độ dài (trừ quá trình bắt tay ba bước và ngắt kết nối bốn bước).
Len (Độ dài phân đoạn)
Điều quan trọng cần lưu ý là Độ dài (Len) không bao gồm độ dài của tiêu đề TCP; do đó, đừng cho rằng một gói có Len = 0
là vô nghĩa. Bản thân tiêu đề TCP mang rất nhiều thông tin.
ACK (Số xác nhận)
Máy thu cho người gửi biết nó đã nhận được các phân đoạn (số Seq) nào.
- Nếu người gửi gửi một phân đoạn có Seq:1 và Len:100 cho máy thu, thì phản hồi ACK từ máy thu sẽ là 1 + 100 = 101, cho biết nó đã nhận được tất cả dữ liệu lên đến Seq 101.
- Nếu người gửi gửi một phân đoạn có Seq:101 và Len:50 cho máy thu, thì phản hồi ACK từ máy thu sẽ là 101 + 50 = 151, cho biết nó đã nhận được tất cả dữ liệu lên đến Seq 151.
Ví dụ: nếu Bên A gửi một phân đoạn "Seq:x Len:y" cho Bên B, thì phản hồi ACK của Bên B sẽ là x + y, có nghĩa là nó đã nhận được tất cả các byte lên đến x + y
.
Kết luận: Số ACK mà máy thu gửi lại hoàn toàn bằng số Seq tiếp theo mà người gửi dự kiến sẽ gửi. Do đó, chúng ta có thể thấy rằng số ACK của gói 10377 hoàn toàn bằng số Seq của gói 10378.
Nếu không bên nào gửi dữ liệu trong quá trình giao tiếp, thì số ACK được trả về bởi bên kia sẽ không thay đổi (nghĩa là nó vẫn giữ nguyên giá trị ban đầu trong quá trình bắt tay ba bước).
Máy trạng thái TCP
Dưới đây là sơ đồ máy trạng thái TCP cổ điển, bao gồm tất cả các trạng thái của kết nối TCP từ khi thiết lập ban đầu đến khi kết thúc cuối cùng trong suốt vòng đời của nó.
Đây là phiên bản được mã hóa màu từ Wikipedia:
Ví dụ về quá trình bắt tay ba bước
Dưới đây là một sơ đồ điển hình minh họa quá trình bắt tay ba bước.
- Bắt tay đầu tiên: Máy khách khởi tạo yêu cầu kết nối, đặt bit SYN thành 1 và khởi tạo số thứ tự ngẫu nhiên (ISN) Seq = x. Sau khi gửi gói SYN, máy khách chuyển sang trạng thái SYN-SENT.
- Bắt tay thứ hai: Máy chủ, khi nhận được yêu cầu kết nối từ máy khách, khởi tạo số thứ tự ngẫu nhiên (ISN) Seq = y, đặt bit SYN và ACK thành 1 và số ACK thành x + 1. Sau khi gửi gói SYN-ACK, máy chủ chuyển sang trạng thái SYN-RECEIVED.
- Bắt tay thứ ba: Máy khách, khi nhận được phản hồi của máy chủ, đặt bit ACK thành 1 và gửi gói ACK. Sau đó, máy khách chuyển sang trạng thái ESTABLISHED. Máy chủ, khi nhận được gói ACK có số ACK là y + 1, cũng chuyển sang trạng thái ESTABLISHED, hoàn tất việc thiết lập kết nối TCP.
Trong quá trình kết nối, các chuyển đổi trạng thái của máy khách và máy chủ như sau:
Từ sơ đồ, chúng ta có thể thấy rằng đối với trạng thái ESTABLISHED (kết nối đã được thiết lập), máy khách và máy chủ nhận thấy việc hoàn tất kết nối vào các thời điểm khác nhau:
- Đối với máy khách, kết nối được coi là đã được thiết lập sau khi bắt tay thứ hai.
- Đối với máy chủ, kết nối được coi là đã được thiết lập sau khi bắt tay thứ ba.
Bắt gói Wireshark
Để hiểu rõ hơn về quá trình bắt tay ba bước TCP, chúng ta sử dụng Wireshark để bắt gói:
Mở Wireshark và bắt đầu bắt gói, sau đó thực hiện lệnh sau trong thiết bị đầu cuối:
curl -I -H "Connection: close" https://dbwu.tech
Chuyển sang giao diện Wireshark và sử dụng bộ lọc TCP để xem các gói. Bạn có thể quan sát quá trình bắt tay ba bước TCP, trong đó 192.168.3.68 là địa chỉ IP cục bộ trong LAN.
- Bắt tay đầu tiên: Máy khách khởi tạo yêu cầu kết nối bằng cách sử dụng trường Seq được đặt thành 3123802190.
- Bắt tay thứ hai: Máy chủ trả lời với trường Seq được đặt thành 1071295171, ACK = x + 1, là 3123802191.
- Bắt tay thứ ba: Máy khách trả lời với ACK = y + 1, là 1071295172.
Mẹo: Theo mặc định, Wireshark hiển thị các giá trị Seq tương đối (bắt đầu từ 0). Nếu bạn muốn xem các giá trị Seq ngẫu nhiên thực tế của máy khách và máy chủ, bạn có thể điều chỉnh điều này trong cài đặt của Wireshark:
Chỉnh sửa - Tùy chọn - Giao thức - TCP
Bỏ chọn: Số thứ tự tương đối
Chứng minh (Phiên bản sơ lược)
Sau khi giải thích nền tảng lý thuyết về quá trình bắt tay ba bước TCP, chúng ta có thể phân tích và chứng minh mệnh đề:
Cần ít nhất ba lần bắt tay để thiết lập kết nối TCP.
Sử dụng một phương pháp chứng minh toán học cơ bản gọi là Chứng minh bằng phản chứng, chúng ta đặt ra điều sau:
Kết nối TCP có thể được thiết lập mà không cần ba lần bắt tay.
Cụ thể, chúng ta giả định rằng TCP có thể thiết lập kết nối với ít hơn ba lần bắt tay, được biểu thị bằng N. Chúng ta chia N thành ba phạm vi:
N < 1 | N == 1 | N == 2
Chúng ta sẽ chứng minh từng trường hợp riêng biệt.
1. N < 1
Khi N < 1, điều đó có nghĩa là không ai khởi tạo lần bắt tay đầu tiên. Trong trường hợp này, không bên nào biết về sự tồn tại của bên kia, khiến việc thiết lập kết nối trở nên không thể. Do đó, N < 1 là không hợp lệ, dẫn chúng ta đến giả thuyết tiếp theo: N == 1.
2. N == 1
Khi N == 1, điều đó ngụ ý rằng chỉ có một lần bắt tay xảy ra, tức là người gửi gửi yêu cầu kết nối (SYN) cho máy thu. Tuy nhiên, không có hành động nào khác xảy ra sau khi yêu cầu được gửi, vì vậy kết nối không thể được thiết lập vì:
- Người gửi không thể xác nhận xem chức năng truyền của nó có hoạt động bình thường hay không (cho dù nó có thể gửi dữ liệu bình thường đến máy thu hay không).
- Máy thu không thể xác nhận xem chức năng nhận của nó có hoạt động bình thường hay không (bao gồm cả việc nó có đang lắng nghe trên cổng chính xác và bộ đệm của nó có hoạt động bình thường hay không).
Mà không có những xác nhận này, người gửi coi kết nối chưa được thiết lập và sẽ không tiếp tục gửi dữ liệu. Do đó, N == 1 là không hợp lệ, dẫn chúng ta đến giả thuyết tiếp theo: N == 2.
3. N == 2
Khi N == 2, điều đó ngụ ý rằng có hai lần bắt tay xảy ra. Dựa trên chứng minh cho N == 1, chúng ta tiếp tục kiểm tra.
Sau lần bắt tay đầu tiên, máy thu xác nhận yêu cầu của người gửi bằng một phản hồi (SYN-ACK). Tương tự như tin nhắn của người gửi, phản hồi của máy thu được gửi nhưng không có gì khác xảy ra, vì vậy kết nối vẫn không thể được thiết lập. Bây giờ, hai điều được xác nhận:
- Chức năng truyền của người gửi hoạt động bình thường.
- Chức năng nhận của máy thu hoạt động bình thường.
Tuy nhiên, máy thu không thể xác nhận:
- Xem chức năng truyền của nó có hoạt động bình thường hay không (cho dù nó có thể gửi dữ liệu bình thường đến người gửi hay không).
- Xem chức năng nhận của người gửi có hoạt động bình thường hay không.
Do đó, N == 2 cũng không đủ để thiết lập kết nối, chứng tỏ rằng cần ít nhất ba lần bắt tay để thiết lập đầy đủ kết nối TCP.
Chứng minh mệnh đề ban đầu
Thông qua phương pháp chứng minh bằng phản chứng được cung cấp trước đó, chúng ta có thể chứng minh rằng cần ít nhất ba lần bắt tay để thiết lập kết nối TCP.
Theo lập luận được nêu trước đó, hãy xem xét các thay đổi trạng thái của người gửi và máy thu khi N == 3.
Sau lần bắt tay thứ hai, người gửi nhận được gói phản hồi thiết lập kết nối (SYN-ACK) từ máy thu và trả lời bằng một gói xác nhận (ACK).
Bây giờ điều sau đây có thể được xác nhận:
- Xem chức năng truyền của máy thu có hoạt động bình thường hay không (cho dù nó có thể gửi dữ liệu bình thường đến người gửi hay không).
- Xem chức năng nhận của người gửi có hoạt động bình thường hay không.
Hai vấn đề xuất hiện khi N == 2 giờ đây đã được giải quyết:
- Chức năng truyền của máy thu hoạt động bình thường.
- Chức năng nhận của người gửi hoạt động bình thường.
Chứng minh (Phiên bản chính xác)
Trước đây, chúng ta đã sử dụng một phương pháp chứng minh bằng phản chứng sơ lược cùng với trạng thái của các gói TCP để chứng minh rằng cần ít nhất ba lần bắt tay để thiết lập kết nối TCP. Ngoài ra, chúng ta có thể chứng minh điều này một cách chặt chẽ bằng cách sử dụng số thứ tự TCP (Seq).
Để đạt được truyền dữ liệu đáng tin cậy, cả hai bên trong giao tiếp TCP phải duy trì một số thứ tự (Seq) để xác định các gói nào đã được bên kia nhận.
Quá trình bắt tay ba bước bao gồm: cả hai bên trao đổi số thứ tự ban đầu của họ và xác nhận rằng bên kia đã nhận được các số thứ tự ban đầu này.
- Nếu chỉ có một lần bắt tay, máy thu không gửi số thứ tự ban đầu của nó.
- Nếu chỉ có hai lần bắt tay, chỉ có số thứ tự ban đầu của người gửi có thể được xác nhận, trong khi số thứ tự ban đầu của máy thu không thể được xác minh.
Hơn nữa, với chỉ hai lần bắt tay, có thể có một tình huống ngoại lệ do các gói bị trì hoãn dẫn đến các kết nối không hợp lệ.
Như hình vẽ, có nhiều đường dẫn trong mạng. Gói đầu tiên được máy khách gửi để thiết lập kết nối có thể kết thúc trên một đường dẫn có độ trễ nghiêm trọng, khiến nó mất nhiều thời gian để đến máy chủ.
Sau khi máy khách hết thời gian chờ, nó cho rằng gói đầu tiên bị mất và khởi tạo lại yêu cầu. Yêu cầu thứ hai đi theo một đường dẫn bình thường và hoàn tất kết nối nhanh chóng.
Từ quan điểm của máy khách, giao tiếp dường như đã kết thúc, nhưng sau đó gói đầu tiên của nó đến muộn tại máy chủ. Vì máy chủ không biết đây là một yêu cầu cũ và không hợp lệ, nên nó trả lời bình thường.
Nếu TCP chỉ có hai lần bắt tay, một kết nối không hợp lệ (bản sao đã hết hạn) sẽ được thiết lập trên máy chủ.
Tuy nhiên, theo cơ chế bắt tay ba bước, khi máy khách nhận được phản hồi của máy chủ, nó nhận ra rằng đây là một kết nối lỗi thời và trả lời bằng một gói RST. Khi nhận được RST, máy chủ đóng kết nối.
Điểm chính: Điều mà quá trình bắt tay ba bước xác nhận là số thứ tự ban đầu (ISN, Initial Sequence Number) của cả người gửi và máy thu. Giá trị này phân biệt kết nối hiện tại với các kết nối cũ trong lịch sử.
Kết luận
Về lý thuyết, ngay cả nhiều hơn ba lần bắt tay cũng không đảm bảo kết nối TCP "hoàn toàn đáng tin cậy". Tuy nhiên, thông qua ba lần bắt tay, ít nhất nó có thể được xác nhận rằng kết nối là "cơ bản khả dụng". Việc tăng số lần bắt tay chỉ đơn thuần làm tăng mức độ tin cậy trong "khả năng sẵn có của kết nối".
Sau khi bắt tay ba bước của TCP, các thay đổi trạng thái của người gửi và máy thu như sau:
- Người gửi xác nhận: việc truyền và nhận của chính nó là bình thường, và việc truyền và nhận của bên kia là bình thường.
- Máy thu xác nhận: việc truyền và nhận của chính nó là bình thường, và việc truyền và nhận của bên kia là bình thường.
Tóm lại, quá trình bắt tay ba bước trong TCP là một ví dụ điển hình về "sự đánh đổi" trong kỹ thuật phần mềm.
Dịch từ https://dbwu.tech/posts/network/why-tcp-does-needs-three-way-handshake/
The 3-way handshake is not necessary. It does what it suppose to but that is not why it works. In 1978, published in 1980, Richard Watson of LLL proved that the necessary and sufficient condition for synchronization for reliable data transfer is to impose an upper bound on 3 times: MPL, Maximum Packet Life time; A, maximum time to wait before sending an Ack; and R, maximum time to exhaust retries.
The message exchange has nothing to do with it. TCP sort of works because TTL bounds MPL and the other two are bounded by the assumptions about performance and the that the TCB has to be held for 120 seconds before the port-ids can be re-used. This is less secure and less robust. Watson and team defined a protocol called delta-t, implemented it and used it at LLL for many years.
This is a hard result to wrap one's head around. It isn't that the 3-way handshake is wrong, it just has nothing to do with why it works. Any sequence of 3 or packets will have the same effect as long as the bounds are enforced.
There is much more to this result. For more information and the sources, you can contact me at day@bu.edu.
Of the 3 or 4 protocols considered in the mid-70s, TCP was by far the worst design and when there was vote, it was not chosen by a margin of 2-1.
Take care,
John Day