SSU2

Proposal 159
Đã đóng
Author eyedeekay, orignal, zlatinb, zzz
Created 2021-09-12
Last Updated 2025-03-05
Target Version 0.9.56

Trạng thái

Kế hoạch triển khai:

FeatureTesting (not default)Enabled by default
Local test code2022-02
Joint test code2022-03
Joint test in-net0.9.54 2022-05
Freeze basic protocol0.9.54 2022-05
Basic Session0.9.55 2022-080.9.56 2022-11
Address Validation (Retry)0.9.55 2022-080.9.56 2022-11
Fragmented RI in handshake0.9.55 2022-080.9.56 2022-11
New Token0.9.55 2022-080.9.57 2022-11
Freeze extended protocol0.9.55 2022-08
Relay0.9.55 2022-080.9.56 2022-11
Peer Test0.9.55 2022-080.9.56 2022-11
Enable for random 2%0.9.55 2022-08
Path Validation0.9.55+ dev0.9.56 2022-11
Connection Migration0.9.55+ dev0.9.56 2022-11
Immediate ACK flag0.9.55+ dev0.9.56 2022-11
Key Rotation0.9.57 2023-020.9.58 2023-05
Disable SSU 1 (i2pd)0.9.56 2022-11
Disable SSU 1 (Java I2P)0.9.58 2023-050.9.61 2023-12
Session cơ bản bao gồm giai đoạn bắt tay và dữ liệu. Giao thức mở rộng bao gồm relay và peer test.

Tổng quan

Đề xuất này mô tả một giao thức thỏa thuận khóa được xác thực nhằm cải thiện khả năng chống lại các hình thức tự động hóa nhận dạng và tấn công khác nhau của SSU.

Đề xuất được tổ chức như sau: các mục tiêu bảo mật được trình bày, tiếp theo là thảo luận về giao thức cơ bản. Sau đó, một đặc tả hoàn chỉnh của tất cả các thông điệp giao thức được cung cấp. Cuối cùng, các địa chỉ router và nhận dạng phiên bản được thảo luận.

Như các transport I2P khác, SSU2 được định nghĩa để truyền tải point-to-point (router-to-router) các thông điệp I2NP. Nó không phải là một data pipe đa mục đích. Giống như SSU, nó cũng cung cấp hai dịch vụ bổ sung: Relaying để vượt qua NAT và Peer Testing để xác định khả năng tiếp cận inbound. Nó cũng cung cấp dịch vụ thứ ba, không có trong SSU, cho connection migration khi một peer thay đổi IP hoặc port.

Động lực

SSU là lớp giao thức duy nhất còn lại yêu cầu ElGamal, rất chậm. Kiểm soát luồng cho SSU phức tạp và không hoạt động tốt. Một số phần của SSU dễ bị tấn công giả mạo địa chỉ. Quá trình bắt tay không sử dụng Noise.

Mục Tiêu Thiết Kế

  • Giảm sử dụng CPU bằng cách loại bỏ ElGamal. Sử dụng X25519 cho DH.

  • Duy trì các chức năng Peer Test và Relay, đồng thời tăng cường bảo mật cho chúng.

  • Làm cho việc triển khai dễ dàng hơn bằng cách cho phép sử dụng các thuật toán kiểm soát luồng tiêu chuẩn.

  • Giảm độ trễ thiết lập kết nối. Thời gian thiết lập trung bình hiện tại là khoảng 135 ms đối với NTCP2 và 187 ms đối với SSU, mặc dù NTCP2 có thêm một vòng truyền tải; việc thay thế ElGamal trong SSU2 sẽ giúp giảm thời gian này, nhưng các thay đổi khác cũng có thể hữu ích.

  • Duy trì hoặc tăng thông lượng tối đa so với SSU 1, được đo trên một loạt độ trễ mô phỏng và tỷ lệ phần trăm mất gói tin trên testnet.

  • Ngăn chặn các cuộc tấn công khuếch đại lưu lượng và định tuyến sai từ các địa chỉ nguồn giả mạo thông qua “xác thực địa chỉ”.

  • Làm cho việc nhận dạng gói tin dễ dang hơn, để giảm sự phụ thuộc vào các phương án dự phòng và heuristics khiến mã trở nên quá phức tạp.

  • Chính thức hóa và cải thiện việc di chuyển kết nối khi IP hoặc cổng của peer thay đổi. Không di chuyển kết nối cho đến khi hoàn tất xác thực địa chỉ, để ngăn chặn các cuộc tấn công. Một số triển khai SSU 1 sử dụng các phương pháp heuristic tốn kém để xử lý thay đổi cổng do NAT rebinding. Không có triển khai SSU 1 nào được biết đến có thể xử lý thay đổi IP.

  • Hỗ trợ SSU 1 và 2 trên một cổng duy nhất, tự động phát hiện, và được xuất bản như một “transport” duy nhất (tức là RouterAddress) trong NetDB.

  • Xuất bản hỗ trợ cho chỉ phiên bản 1, chỉ phiên bản 2, hoặc 1+2 trong netDb ở một trường riêng biệt, và mặc định là chỉ phiên bản 1 (không ràng buộc hỗ trợ phiên bản với một phiên bản router cụ thể)

  • Đảm bảo rằng tất cả các triển khai (Java/i2pd/Go) có thể thêm hỗ trợ phiên bản 2 (hoặc không) theo lịch trình riêng của họ

  • Thêm padding ngẫu nhiên vào tất cả các thông điệp bao gồm thông điệp handshake và thông điệp dữ liệu. Tất cả padding phải được bảo vệ bởi MAC, khác với padding cuối gói tin trong SSU 1. Cung cấp cơ chế tùy chọn cho cả hai bên để yêu cầu padding tối thiểu và tối đa và/hoặc phân phối padding. Chi tiết của phân phối padding phụ thuộc vào cài đặt cụ thể và có thể được hoặc không được chỉ định trong chính giao thức đó.

  • Làm xáo trộn các header và nội dung của các thông điệp không được mã hóa hoàn toàn đủ mức để các hộp DPI và chữ ký AV không thể dễ dàng phân loại chúng. Đồng thời đảm bảo rằng các thông điệp gửi tới một peer hoặc nhóm peer đơn lẻ không có mẫu bit tương tự nhau.

  • Sửa lỗi mất bit trong DH do định dạng Java Ticket1112, và tăng tốc DH bằng cách chuyển sang X25519.

  • Chuyển sang sử dụng hàm dẫn xuất khóa thực sự (KDF) thay vì sử dụng trực tiếp kết quả DH

  • Thêm “khả năng chống thăm dò” (như Tor gọi); bao gồm khả năng chống replay.

  • Duy trì trao đổi khóa xác thực 2 chiều (2W-AKE). 1W-AKE không đủ cho ứng dụng của chúng ta.

  • Dựa vào khóa công khai tĩnh được công bố trong RouterInfo như một phần khác của xác thực.

  • Thêm các tùy chọn/phiên bản trong handshake để có thể mở rộng trong tương lai.

  • Không làm tăng đáng kể CPU cần thiết cho việc thiết lập kết nối; nếu có thể, giảm đáng kể.

  • Loại bỏ yêu cầu padding thành bội số của 16 byte được áp đặt bởi mã hóa AES trong SSU 1.

  • Sử dụng ChaCha/Poly1305 tiêu chuẩn cho mã hóa và MAC, thay thế mã hóa AES và MAC HMAC-MD5-128 không chuẩn được sử dụng trong SSU 1.

  • Sử dụng các khóa mã hóa riêng biệt cho gửi và nhận, thay vì sử dụng các khóa chung cho cả hai hướng như trong SSU 1.

  • Sử dụng bắt tay 3 thông điệp, một chuyến khứ hồi, như trong NTCP2. Loại bỏ độ trễ chờ đợi các thông điệp dữ liệu khiến SSU thực tế trở thành bắt tay hai chuyến khứ hồi.

  • Cải thiện đáng kể hiệu quả của ACKs và NACKs, vốn rất tệ trong SSU 1. Giảm băng thông cần thiết cho ACKs và NACKs, và tăng kích thước gói có sẵn cho dữ liệu. Mã hóa hiệu quả NACKs cho chuỗi tin nhắn bị thiếu, điều này phổ biến qua WiFi.

  • Giảm độ phức tạp cần thiết để triển khai phân mảnh thông điệp I2NP. Bỏ qua cơ chế phân mảnh và mã hóa cho các thông điệp I2NP hoàn chỉnh.

  • Giảm thiểu overhead của giao thức trước khi padding, đặc biệt đối với ACK. Mặc dù padding sẽ được thêm vào, overhead trước khi padding vẫn là overhead. Các node băng thông thấp phải có thể sử dụng SSU2.

  • Duy trì timestamps để phát hiện replay và skew.

  • Tránh mọi vấn đề năm 2038 trong timestamp, phải hoạt động ít nhất đến năm 2106.

  • Tăng MTU tối thiểu từ 620 lên 1280 để cải thiện hiệu suất, dễ dàng triển khai, và tăng kích thước thông điệp I2NP tối đa. Việc phân mảnh và tái lắp ráp khá tốn kém. Bằng cách cung cấp không gian cho các thông điệp tunnel 1028 byte, phần lớn các thông điệp I2NP sẽ không cần phân mảnh.

  • Tăng MTU tối đa từ 1488 (1484 cho IPv6) lên 1500 để tăng hiệu quả. Loại bỏ yêu cầu MTU phải là bội số của 16.

  • Tăng kích thước tối đa của thông điệp I2NP từ khoảng 32K trong SSU 1 lên khoảng 64 KB như trong NTCP2.

  • Loại bỏ chữ ký của các trường IP và port khỏi quá trình handshake, để các router không biết IP và port bên ngoài của mình có thể kết nối được.

  • Giữ lại cơ chế khám phá IP/port từ SSU 1 trong quá trình handshake, để các router có thể học được IP và port bên ngoài của chúng.

  • Bao gồm các đại diện của các nhà phát triển router Java, C++, và Go trong thiết kế.

Non-Goals

  • Khả năng chống DPI không thể phá vỡ… đó sẽ là pluggable transports, Proposal 109.

  • Một transport dựa trên TLS (hoặc giống HTTPS)… đó sẽ là Proposal 104.

  • Khả năng chống DPI dựa trên thời gian (thời gian/độ trễ giữa các thông điệp có thể phụ thuộc vào triển khai; độ trễ trong thông điệp có thể được đưa vào tại bất kỳ điểm nào, bao gồm trước khi gửi random padding chẳng hạn). Độ trễ nhân tạo (mà obfs4 gọi là IAT hoặc inter-arrival time) độc lập với chính giao thức.

  • Khả năng phủ nhận việc tham gia vào một phiên (có chữ ký trong đó).

Các mục tiêu không ưu tiên có thể được xem xét lại một phần hoặc thảo luận:

  • Mức độ bảo vệ chống Deep Packet Inspection (DPI)

  • Bảo mật Post-Quantum (PQ)

  • Khả năng phủ nhận

Security Goals

Chúng tôi xem xét ba bên:

  • Alice, người muốn thiết lập một phiên mới.
  • Bob, người mà Alice muốn thiết lập phiên với.
  • Mallory, kẻ tấn công “man in the middle” giữa Alice và Bob.

Tối đa hai người tham gia có thể thực hiện các cuộc tấn công chủ động.

Alice và Bob đều sở hữu một cặp khóa tĩnh, được chứa trong RouterIdentity của họ.

Giao thức được đề xuất cố gắng cho phép Alice và Bob thỏa thuận về một khóa bí mật chung (K) dưới các yêu cầu sau:

  1. Bảo mật khóa riêng tư: cả Bob và Mallory đều không thể biết được bất kỳ thông tin gì về khóa riêng tư tĩnh của Alice. Tương tự, Alice cũng không thể biết được bất kỳ thông tin gì về khóa riêng tư tĩnh của Bob.

  2. Session key K chỉ được biết bởi Alice và Bob.

  3. Perfect forward secrecy (bảo mật chuyển tiếp hoàn hảo): khóa phiên đã thỏa thuận vẫn được giữ bí mật trong tương lai, ngay cả khi khóa riêng tĩnh của Alice và/hoặc Bob bị tiết lộ sau khi khóa đã được thỏa thuận.

  4. Xác thực hai chiều: Alice chắc chắn rằng cô ấy đã thiết lập một phiên làm việc với Bob, và ngược lại.

  5. Bảo vệ chống DPI trực tuyến: Đảm bảo rằng việc phát hiện Alice và Bob đang tham gia vào giao thức chỉ bằng các kỹ thuật kiểm tra gói tin sâu (DPI) đơn giản là không hề dễ dàng. Xem bên dưới.

  6. Khả năng phủ nhận có giới hạn: cả Alice và Bob đều không thể phủ nhận sự tham gia của mình vào giao thức, nhưng nếu một trong hai bên làm lộ khóa chia sẻ thì bên kia có thể phủ nhận tính xác thực của nội dung dữ liệu được truyền tải.

Đề xuất hiện tại cố gắng cung cấp tất cả năm yêu cầu dựa trên giao thức Station-To-Station (STS) giao thức Station-To-Station (STS). Lưu ý rằng giao thức này cũng là cơ sở cho giao thức SSU.

Additional DPI Discussion

Chúng tôi giả định hai thành phần DPI:

Online DPI

DPI trực tuyến kiểm tra tất cả các luồng dữ liệu theo thời gian thực. Các kết nối có thể bị chặn hoặc bị can thiệp theo cách khác. Dữ liệu kết nối hoặc metadata có thể được xác định và lưu trữ để phân tích ngoại tuyến. DPI trực tuyến không có quyền truy cập vào cơ sở dữ liệu mạng I2P. DPI trực tuyến chỉ có khả năng tính toán thời gian thực hạn chế, bao gồm tính toán độ dài, kiểm tra trường dữ liệu, và các phép tính đơn giản như XOR. DPI trực tuyến có khả năng thực hiện các hàm mật mã thời gian thực nhanh như ChaCha20, AEAD, và hashing, nhưng những thao tác này sẽ quá tốn kém để áp dụng cho hầu hết hoặc tất cả các luồng dữ liệu. Bất kỳ ứng dụng nào của các thao tác mật mã này sẽ chỉ áp dụng cho các luồng trên tổ hợp IP/Port đã được xác định trước đó bằng phân tích ngoại tuyến. DPI trực tuyến không có khả năng thực hiện các hàm mật mã có chi phí cao như DH hoặc elligator2. DPI trực tuyến không được thiết kế đặc biệt để phát hiện I2P, mặc dù nó có thể có các quy tắc phân loại hạn chế cho mục đích đó.

Mục tiêu là ngăn chặn việc nhận dạng giao thức bởi DPI trực tuyến.

Khái niệm về DPI trực tuyến hoặc “đơn giản” ở đây được hiểu là bao gồm các khả năng đối thủ sau đây:

  1. Khả năng kiểm tra tất cả dữ liệu được gửi hoặc nhận bởi mục tiêu.

  2. Khả năng thực hiện các thao tác trên dữ liệu được quan sát, chẳng hạn như áp dụng block cipher hoặc hash function.

  3. Khả năng lưu trữ và so sánh với các thông điệp đã gửi trước đó.

  4. Khả năng sửa đổi, trì hoãn hoặc phân mảnh các gói tin.

Tuy nhiên, DPI trực tuyến được giả định có các hạn chế sau:

  1. Không thể ánh xạ địa chỉ IP thành router hash. Mặc dù điều này khá đơn giản với quyền truy cập thời gian thực vào cơ sở dữ liệu mạng, nhưng sẽ cần một hệ thống DPI được thiết kế đặc biệt để nhắm mục tiêu I2P.

  2. Việc không thể sử dụng thông tin thời gian để phát hiện giao thức.

  3. Nói chung, bộ công cụ DPI trực tuyến không chứa bất kỳ công cụ tích hợp nào được thiết kế đặc biệt để phát hiện I2P. Điều này bao gồm việc tạo ra các “honeypot”, ví dụ như bao gồm phần đệm không ngẫu nhiên trong các thông điệp của chúng. Lưu ý rằng điều này không loại trừ các hệ thống machine learning hoặc các công cụ DPI có khả năng cấu hình cao miễn là chúng đáp ứng các yêu cầu khác.

Để chống lại việc phân tích payload, hệ thống đảm bảo rằng tất cả các thông điệp đều không thể phân biệt được với dữ liệu ngẫu nhiên. Điều này cũng đòi hỏi độ dài của chúng phải ngẫu nhiên, việc này phức tạp hơn là chỉ đơn thuần thêm padding ngẫu nhiên. Thực tế, trong Phụ lục A, các tác giả lập luận rằng một scheme padding ngây thơ (tức là uniform) không giải quyết được vấn đề này. Do đó, Phụ lục A đề xuất bao gồm các độ trễ ngẫu nhiên hoặc phát triển một scheme padding thay thế có thể cung cấp sự bảo vệ hợp lý cho cuộc tấn công được đề xuất.

Để bảo vệ chống lại mục thứ sáu ở trên, các triển khai nên bao gồm độ trễ ngẫu nhiên trong giao thức. Những kỹ thuật như vậy không được đề cập trong đề xuất này, nhưng chúng cũng có thể giải quyết các vấn đề về độ dài padding. Tóm lại, đề xuất này cung cấp sự bảo vệ tốt chống lại phân tích payload (khi các cân nhắc trong Phụ lục A được tính đến), nhưng chỉ cung cấp sự bảo vệ hạn chế chống lại phân tích luồng.

Offline DPI

Offline DPI kiểm tra dữ liệu được lưu trữ bởi online DPI để phân tích sau đó. Offline DPI có thể được thiết kế đặc biệt để phát hiện I2P. Offline DPI có quyền truy cập thời gian thực vào cơ sở dữ liệu mạng I2P. Offline DPI có quyền truy cập vào thông số kỹ thuật này và các thông số kỹ thuật I2P khác. Offline DPI có khả năng tính toán không giới hạn, bao gồm tất cả các chức năng mật mã được định nghĩa trong thông số kỹ thuật này.

DPI ngoại tuyến không có khả năng chặn các kết nối hiện có. DPI ngoại tuyến có khả năng thực hiện gửi gần thời gian thực (trong vòng vài phút sau khi thiết lập) đến host/port của các bên thông qua packet injection. DPI ngoại tuyến có khả năng thực hiện phát lại gần thời gian thực (trong vòng vài phút sau khi thiết lập) các tin nhắn trước đó (đã chỉnh sửa hoặc không) để “probing” hoặc các mục đích khác.

Việc ngăn chặn nhận dạng giao thức bởi DPI ngoại tuyến không phải là một mục tiêu. Tất cả việc giải mã dữ liệu bị làm rối trong hai thông điệp đầu tiên, được thực hiện bởi các router I2P, cũng có thể được thực hiện bởi DPI ngoại tuyến.

Mục tiêu là từ chối các kết nối cố gắng sử dụng phát lại các thông điệp trước đó.

Address Validation

Sau đây được sao chép từ QUIC RFC 9000. Đối với mỗi phần, hãy xem xét và chỉnh sửa.

Xác thực địa chỉ đảm bảo rằng một endpoint không thể được sử dụng cho các cuộc tấn công khuếch đại lưu lượng. Trong loại tấn công này, một gói tin được gửi đến máy chủ với thông tin địa chỉ nguồn giả mạo xác định nạn nhân. Nếu máy chủ tạo ra nhiều gói tin hơn hoặc các gói tin lớn hơn để phản hồi gói tin đó, kẻ tấn công có thể sử dụng máy chủ để gửi nhiều dữ liệu hơn về phía nạn nhân so với khả năng tự gửi của chính nó.

Biện pháp phòng thủ chính chống lại các cuộc tấn công khuếch đại là xác minh rằng một peer có thể nhận gói tin tại địa chỉ transport mà nó tuyên bố. Do đó, sau khi nhận gói tin từ một địa chỉ chưa được xác thực, một endpoint PHẢI giới hạn lượng dữ liệu gửi đến địa chỉ chưa xác thực đó không quá ba lần lượng dữ liệu nhận được từ địa chỉ đó. Giới hạn về kích thước phản hồi này được gọi là giới hạn chống khuếch đại.

Xác thực địa chỉ được thực hiện cả trong quá trình thiết lập kết nối (xem Mục 8.1) và trong quá trình di chuyển kết nối (xem Mục 8.2).

Address Validation during Connection Establishment

Việc thiết lập kết nối ngầm định cung cấp xác thực địa chỉ cho cả hai endpoint. Cụ thể, việc nhận được một gói tin được bảo vệ bằng khóa Handshake xác nhận rằng peer đã xử lý thành công một gói tin Initial. Khi một endpoint đã xử lý thành công gói tin Handshake từ peer, nó có thể coi địa chỉ peer đã được xác thực.

Ngoài ra, một endpoint CÓ THỂ xem xét địa chỉ peer đã được xác thực nếu peer sử dụng một connection ID được chọn bởi endpoint và connection ID chứa ít nhất 64 bit entropy.

Đối với client, giá trị của trường Destination Connection ID trong gói Initial đầu tiên của nó cho phép nó xác thực địa chỉ server như một phần của việc xử lý thành công bất kỳ gói nào. Các gói Initial từ server được bảo vệ bằng các key được tạo ra từ giá trị này (xem Section 5.2 của QUIC-TLS). Thay vào đó, giá trị này được server phản hồi lại trong các gói Version Negotiation (Section 6) hoặc được bao gồm trong Integrity Tag trong các gói Retry (Section 5.8 của QUIC-TLS).

Trước khi xác thực địa chỉ client, các server KHÔNG ĐƯỢC gửi nhiều hơn ba lần số byte so với số byte mà chúng đã nhận được. Điều này giới hạn mức độ của bất kỳ cuộc tấn công khuếch đại nào có thể được thực hiện bằng cách sử dụng địa chỉ nguồn giả mạo. Nhằm mục đích tránh khuếch đại trước khi xác thực địa chỉ, các server PHẢI đếm tất cả các payload byte nhận được trong các datagram được gán duy nhất cho một kết nối đơn lẻ. Điều này bao gồm các datagram chứa packet được xử lý thành công và các datagram chứa packet bị loại bỏ hoàn toàn.

Các client PHẢI đảm bảo rằng các UDP datagram chứa các gói Initial có UDP payload ít nhất 1200 byte, thêm các PADDING frame khi cần thiết. Một client gửi các datagram được đệm cho phép server gửi nhiều dữ liệu hơn trước khi hoàn thành xác thực địa chỉ.

Việc mất gói tin Initial hoặc Handshake từ server có thể gây ra deadlock nếu client không gửi thêm các gói tin Initial hoặc Handshake. Deadlock có thể xảy ra khi server đạt đến giới hạn chống khuếch đại và client đã nhận được xác nhận cho tất cả dữ liệu mà nó đã gửi. Trong trường hợp này, khi client không có lý do để gửi thêm gói tin, server sẽ không thể gửi thêm dữ liệu vì nó chưa xác thực địa chỉ của client. Để ngăn chặn deadlock này, client PHẢI gửi một gói tin khi Probe Timeout (PTO) xảy ra; xem Mục 6.2 của QUIC-RECOVERY. Cụ thể, client PHẢI gửi một gói tin Initial trong một UDP datagram chứa ít nhất 1200 byte nếu nó không có Handshake keys, và nếu không thì gửi một gói tin Handshake.

Một server có thể muốn xác thực địa chỉ client trước khi bắt đầu quá trình bắt tay mật mã. QUIC sử dụng một token trong gói tin Initial để cung cấp xác thực địa chỉ trước khi hoàn thành quá trình bắt tay. Token này được gửi đến client trong quá trình thiết lập kết nối bằng gói tin Retry (xem Mục 8.1.2) hoặc trong một kết nối trước đó sử dụng frame NEW_TOKEN (xem Mục 8.1.3).

Ngoài các giới hạn gửi được áp đặt trước khi xác thực địa chỉ, các server cũng bị ràng buộc trong việc gửi dữ liệu bởi các giới hạn được thiết lập bởi bộ điều khiển tắc nghẽn. Các client chỉ bị ràng buộc bởi bộ điều khiển tắc nghẽn.

Token Construction

Một token được gửi trong NEW_TOKEN frame hoặc Retry packet PHẢI được xây dựng theo cách cho phép server xác định cách nó được cung cấp cho client. Các token này được mang trong cùng một field nhưng yêu cầu xử lý khác nhau từ các server.

Address Validation Using Retry Packets

Khi nhận được gói Initial từ client, server có thể yêu cầu xác thực địa chỉ bằng cách gửi một gói Retry (Mục 17.2.5) chứa một token. Token này PHẢI được client lặp lại trong tất cả các gói Initial mà nó gửi cho kết nối đó sau khi nhận được gói Retry.

Khi xử lý một gói tin Initial chứa token được cung cấp trong gói tin Retry, server không thể gửi một gói tin Retry khác; nó chỉ có thể từ chối kết nối hoặc cho phép kết nối tiếp tục.

Miễn là kẻ tấn công không thể tạo ra một token hợp lệ cho địa chỉ của chính nó (xem Mục 8.1.4) và client có thể trả lại token đó, điều này chứng minh với server rằng nó đã nhận được token.

Một server cũng có thể sử dụng gói Retry để hoãn lại trạng thái và chi phí xử lý của việc thiết lập kết nối. Việc yêu cầu server cung cấp một connection ID khác, cùng với tham số transport original_destination_connection_id được định nghĩa trong Mục 18.2, buộc server phải chứng minh rằng nó, hoặc một thực thể mà nó hợp tác cùng, đã nhận được gói Initial ban đầu từ client. Việc cung cấp một connection ID khác cũng cho phép server có một số quyền kiểm soát về cách các gói tin tiếp theo được định tuyến. Điều này có thể được sử dụng để điều hướng các kết nối đến một instance server khác.

Nếu một server nhận được một gói Initial từ client có chứa token Retry không hợp lệ nhưng về các mặt khác vẫn hợp lệ, server biết rằng client sẽ không chấp nhận một token Retry khác. Server có thể loại bỏ gói tin như vậy và cho phép client hết thời gian chờ để phát hiện lỗi handshake, nhưng điều này có thể gây ra một hình phạt độ trễ đáng kể cho client. Thay vào đó, server NÊN ngay lập tức đóng (Section 10.2) kết nối với lỗi INVALID_TOKEN. Lưu ý rằng server chưa thiết lập bất kỳ trạng thái nào cho kết nối tại thời điểm này và do đó không vào giai đoạn đóng kết nối.

Một luồng cho thấy việc sử dụng gói tin Retry được hiển thị trong Hình 9.

Client                                                  Server

Initial[0]: CRYPTO[CH] ->

                                                <- Retry+Token

Initial+Token[1]: CRYPTO[CH] ->

                                 Initial[0]: CRYPTO[SH] ACK[1]
                       Handshake[0]: CRYPTO[EE, CERT, CV, FIN]
                                 <- 1-RTT[0]: STREAM[1, "..."]

                Figure 9: Example Handshake with Retry

Address Validation for Future Connections

Máy chủ CÓ THỂ cung cấp cho các client một token xác thực địa chỉ trong một kết nối có thể được sử dụng trong kết nối tiếp theo. Xác thực địa chỉ đặc biệt quan trọng với 0-RTT vì máy chủ có khả năng gửi một lượng dữ liệu đáng kể đến client để phản hồi dữ liệu 0-RTT.

Máy chủ sử dụng frame NEW_TOKEN (Phần 19.7) để cung cấp cho client một token xác thực địa chỉ có thể được sử dụng để xác thực các kết nối trong tương lai. Trong một kết nối tương lai, client bao gồm token này trong các gói tin Initial để cung cấp xác thực địa chỉ. Client PHẢI bao gồm token trong tất cả các gói tin Initial mà nó gửi, trừ khi một Retry thay thế token bằng một token mới hơn. Client KHÔNG ĐƯỢC sử dụng token được cung cấp trong một Retry cho các kết nối tương lai. Máy chủ CÓ THỂ loại bỏ bất kỳ gói tin Initial nào không mang token mong đợi.

Khác với token được tạo cho gói Retry, được sử dụng ngay lập tức, token được gửi trong khung NEW_TOKEN có thể được sử dụng sau một khoảng thời gian đã trôi qua. Do đó, một token NÊN có thời gian hết hạn, có thể là thời gian hết hạn rõ ràng hoặc timestamp được phát hành có thể được sử dụng để tính toán động thời gian hết hạn. Máy chủ có thể lưu trữ thời gian hết hạn hoặc bao gồm nó dưới dạng mã hóa trong token.

Token được phát hành với NEW_TOKEN KHÔNG ĐƯỢC bao gồm thông tin có thể cho phép các giá trị bị liên kết bởi một observer với kết nối mà nó được phát hành. Ví dụ, nó không thể bao gồm connection ID trước đó hoặc thông tin địa chỉ, trừ khi các giá trị được mã hóa. Một server PHẢI đảm bảo rằng mỗi NEW_TOKEN frame mà nó gửi là duy nhất trên tất cả các client, ngoại trừ những frame được gửi để khắc phục việc mất mát của các NEW_TOKEN frame đã gửi trước đó. Thông tin cho phép server phân biệt giữa các token từ Retry và NEW_TOKEN CÓ THỂ được truy cập bởi các thực thể khác ngoài server.

Việc số cổng client giống nhau trên hai kết nối khác nhau là không có khả năng xảy ra; do đó việc xác thực cổng khó có thể thành công.

Một token nhận được trong NEW_TOKEN frame có thể áp dụng cho bất kỳ server nào mà kết nối được coi là có thẩm quyền (ví dụ: tên server được bao gồm trong chứng chỉ). Khi kết nối đến một server mà client giữ một token có thể áp dụng và chưa sử dụng, nó NÊN bao gồm token đó trong trường Token của Initial packet. Việc bao gồm token có thể cho phép server xác thực địa chỉ client mà không cần thêm một round trip. Client KHÔNG ĐƯỢC bao gồm token không áp dụng cho server mà nó đang kết nối, trừ khi client có kiến thức rằng server đã phát hành token và server mà client đang kết nối đang cùng quản lý các token. Client CÓ THỂ sử dụng token từ bất kỳ kết nối trước đó nào đến server đó.

Token cho phép server liên kết hoạt động giữa kết nối nơi token được cấp phát và bất kỳ kết nối nào mà token đó được sử dụng. Các client muốn ngắt tính liên tục của danh tính với server có thể loại bỏ các token được cung cấp thông qua NEW_TOKEN frame. Ngược lại, token thu được trong Retry packet PHẢI được sử dụng ngay lập tức trong quá trình thử kết nối và không thể được sử dụng trong các lần thử kết nối tiếp theo.

Một client KHÔNG NÊN tái sử dụng token từ NEW_TOKEN frame cho các lần thử kết nối khác nhau. Việc tái sử dụng token cho phép các kết nối được liên kết bởi các thực thể trên đường dẫn mạng; xem Mục 9.5.

Các client có thể nhận được nhiều token trên một kết nối duy nhất. Ngoài việc ngăn chặn khả năng liên kết, bất kỳ token nào cũng có thể được sử dụng trong bất kỳ lần thử kết nối nào. Các server có thể gửi thêm token để cho phép xác thực địa chỉ cho nhiều lần thử kết nối hoặc thay thế các token cũ có thể trở nên không hợp lệ. Đối với client, sự mơ hồ này có nghĩa là việc gửi token chưa sử dụng gần đây nhất có khả năng hiệu quả cao nhất. Mặc dù việc lưu và sử dụng các token cũ không có hậu quả tiêu cực, các client có thể coi các token cũ là ít có khả năng hữu ích cho server trong việc xác thực địa chỉ.

Khi một server nhận được gói tin Initial với address validation token, nó PHẢI cố gắng xác thực token đó, trừ khi nó đã hoàn thành address validation. Nếu token không hợp lệ, thì server NÊN tiếp tục như thể client không có địa chỉ đã được xác thực, bao gồm khả năng gửi gói tin Retry. Các token được cung cấp với NEW_TOKEN frames và gói tin Retry có thể được các server phân biệt (xem Mục 8.1.1), và loại sau có thể được xác thực nghiêm ngặt hơn. Nếu việc xác thực thành công, server NÊN cho phép quá trình handshake tiếp tục.

Lưu ý: Lý do để coi client là chưa được xác thực thay vì loại bỏ gói tin là vì client có thể đã nhận được token trong một kết nối trước đó sử dụng frame NEW_TOKEN, và nếu server đã mất trạng thái, nó có thể không thể xác thực token hoàn toàn, dẫn đến lỗi kết nối nếu gói tin bị loại bỏ.

Trong thiết kế stateless, một server có thể sử dụng các token được mã hóa và xác thực để truyền thông tin cho client mà server có thể khôi phục sau này và sử dụng để xác thực địa chỉ client. Các token không được tích hợp vào quá trình bắt tay mã hóa, và do đó chúng không được xác thực. Ví dụ, một client có thể sử dụng lại một token. Để tránh các cuộc tấn công khai thác tính chất này, một server có thể giới hạn việc sử dụng token của mình chỉ cho thông tin cần thiết để xác thực địa chỉ client.

Các client CÓ THỂ sử dụng các token thu được từ một kết nối cho bất kỳ lần thử kết nối nào sử dụng cùng phiên bản. Khi lựa chọn token để sử dụng, các client không cần phải xem xét các thuộc tính khác của kết nối đang được thử, bao gồm việc lựa chọn các giao thức ứng dụng có thể, session ticket, hoặc các thuộc tính kết nối khác.

Address Validation Token Integrity

Một token xác thực địa chỉ PHẢI khó đoán. Bao gồm một giá trị ngẫu nhiên với ít nhất 128 bit entropy trong token sẽ đủ, nhưng điều này phụ thuộc vào việc server nhớ giá trị mà nó gửi đến các client.

Một cơ chế dựa trên token cho phép máy chủ chuyển giao bất kỳ trạng thái nào liên quan đến việc xác thực cho client. Để thiết kế này hoạt động, token PHẢI được bảo vệ tính toàn vẹn chống lại việc sửa đổi hoặc làm giả bởi các client. Nếu không có bảo vệ tính toàn vẹn, các client độc hại có thể tạo ra hoặc đoán các giá trị cho token mà máy chủ sẽ chấp nhận. Chỉ có máy chủ mới cần quyền truy cập vào khóa bảo vệ tính toàn vẹn cho các token.

Không cần thiết phải có một định dạng được xác định rõ ràng duy nhất cho token vì server tạo ra token cũng chính là server tiêu thụ nó. Các token được gửi trong các gói Retry NÊN bao gồm thông tin cho phép server xác minh rằng địa chỉ IP nguồn và cổng trong các gói từ client vẫn giữ nguyên không đổi.

Các token được gửi trong các frame NEW_TOKEN PHẢI bao gồm thông tin cho phép server xác minh rằng địa chỉ IP của client không thay đổi từ khi token được cấp phát. Các server có thể sử dụng token từ các frame NEW_TOKEN để quyết định không gửi packet Retry, ngay cả khi địa chỉ client đã thay đổi. Nếu địa chỉ IP của client đã thay đổi, server PHẢI tuân thủ giới hạn chống khuếch đại; xem Mục 8. Lưu ý rằng khi có NAT, yêu cầu này có thể không đủ để bảo vệ các host khác chia sẻ NAT khỏi các cuộc tấn công khuếch đại.

Những kẻ tấn công có thể phát lại token để sử dụng máy chủ như bộ khuếch đại trong các cuộc tấn công DDoS. Để bảo vệ chống lại những cuộc tấn công như vậy, máy chủ PHẢI đảm bảo rằng việc phát lại token được ngăn chặn hoặc hạn chế. Máy chủ NÊN đảm bảo rằng các token được gửi trong gói Retry chỉ được chấp nhận trong thời gian ngắn, vì chúng được trả về ngay lập tức bởi client. Các token được cung cấp trong khung NEW_TOKEN (Mục 19.7) cần có hiệu lực lâu hơn nhưng KHÔNG NÊN được chấp nhận nhiều lần. Máy chủ được khuyến khích chỉ cho phép token được sử dụng một lần, nếu có thể; token CÓ THỂ bao gồm thông tin bổ sung về client để thu hẹp thêm khả năng áp dụng hoặc tái sử dụng.

DPI Trực tuyến

Xác thực đường dẫn được sử dụng bởi cả hai peer trong quá trình di chuyển kết nối (xem Phần 9) để xác minh khả năng tiếp cận sau khi thay đổi địa chỉ. Trong xác thực đường dẫn, các endpoint kiểm tra khả năng tiếp cận giữa một địa chỉ cục bộ cụ thể và một địa chỉ peer cụ thể, trong đó địa chỉ là bộ 2-tuple gồm địa chỉ IP và cổng.

Kiểm tra xác thực đường dẫn đảm bảo rằng các gói tin được gửi trên một đường dẫn đến một peer được nhận bởi peer đó. Xác thực đường dẫn được sử dụng để đảm bảo rằng các gói tin nhận được từ một peer đang di chuyển không mang địa chỉ nguồn giả mạo.

Xác thực đường dẫn không xác thực rằng một peer có thể gửi theo hướng trả về. Các thông báo xác nhận không thể được sử dụng để xác thực đường dẫn trả về vì chúng chứa entropy không đủ và có thể bị giả mạo. Các endpoint độc lập xác định khả năng tiếp cận trên mỗi hướng của một đường dẫn, và do đó khả năng tiếp cận trả về chỉ có thể được thiết lập bởi peer.

Xác thực đường dẫn có thể được sử dụng bất cứ lúc nào bởi một trong hai endpoint. Ví dụ, một endpoint có thể kiểm tra rằng một peer vẫn còn sở hữu địa chỉ của nó sau một khoảng thời gian im lặng.

Xác thực đường dẫn không được thiết kế như một cơ chế traversal NAT. Mặc dù cơ chế được mô tả ở đây có thể hiệu quả cho việc tạo ra các binding NAT hỗ trợ traversal NAT, kỳ vọng là một endpoint có thể nhận gói tin mà không cần phải gửi gói tin trước trên đường dẫn đó. Traversal NAT hiệu quả cần các cơ chế đồng bộ hóa bổ sung mà không được cung cấp ở đây.

Một endpoint CÓ THỂ bao gồm các frame khác cùng với các frame PATH_CHALLENGE và PATH_RESPONSE được sử dụng cho việc xác thực đường dẫn. Cụ thể, một endpoint có thể bao gồm các frame PADDING với frame PATH_CHALLENGE cho Path Maximum Transmission Unit Discovery (PMTUD); xem Mục 14.2.1. Một endpoint cũng có thể bao gồm frame PATH_CHALLENGE của riêng mình khi gửi frame PATH_RESPONSE.

Một endpoint sử dụng connection ID mới cho các probe được gửi từ địa chỉ local mới; xem Mục 9.5. Khi thăm dò một đường dẫn mới, một endpoint có thể đảm bảo rằng peer của nó có sẵn một connection ID chưa sử dụng cho các phản hồi. Việc gửi các frame NEW_CONNECTION_ID và PATH_CHALLENGE trong cùng một packet, nếu active_connection_id_limit của peer cho phép, đảm bảo rằng một connection ID chưa sử dụng sẽ có sẵn cho peer khi gửi phản hồi.

Một endpoint có thể chọn thăm dò nhiều đường dẫn cùng lúc. Số lượng đường dẫn đồng thời được sử dụng để thăm dò bị giới hạn bởi số connection ID bổ sung mà peer của nó đã cung cấp trước đó, vì mỗi địa chỉ local mới được sử dụng để thăm dò đòi hỏi một connection ID chưa được sử dụng trước đó.

DPI Ngoại tuyến

Để khởi tạo xác thực đường dẫn, một endpoint gửi một frame PATH_CHALLENGE chứa payload không thể dự đoán trên đường dẫn cần được xác thực.

Một endpoint CÓ THỂ gửi nhiều frame PATH_CHALLENGE để bảo vệ chống mất gói tin. Tuy nhiên, một endpoint KHÔNG NÊN gửi nhiều frame PATH_CHALLENGE trong một gói tin duy nhất.

Một endpoint KHÔNG NÊN thăm dò đường dẫn mới với các gói tin chứa khung PATH_CHALLENGE thường xuyên hơn so với việc gửi gói tin Initial. Điều này đảm bảo rằng việc di chuyển kết nối không tạo ra tải trọng lớn hơn trên đường dẫn mới so với việc thiết lập một kết nối mới.

Endpoint PHẢI sử dụng dữ liệu không thể đoán trước trong mỗi frame PATH_CHALLENGE để có thể liên kết phản hồi của peer với PATH_CHALLENGE tương ứng.

Một endpoint PHẢI mở rộng các datagram chứa frame PATH_CHALLENGE đến ít nhất kích thước datagram tối đa nhỏ nhất được phép là 1200 byte, trừ khi giới hạn chống khuếch đại cho đường dẫn không cho phép gửi datagram có kích thước này. Việc gửi các UDP datagram có kích thước này đảm bảo rằng đường dẫn mạng từ endpoint đến peer có thể được sử dụng cho QUIC; xem Phần 14.

Khi một endpoint không thể mở rộng kích thước datagram lên 1200 byte do giới hạn chống khuếch đại, path MTU sẽ không được xác thực. Để đảm bảo rằng path MTU đủ lớn, endpoint PHẢI thực hiện xác thực path thứ hai bằng cách gửi một PATH_CHALLENGE frame trong một datagram có ít nhất 1200 byte. Việc xác thực bổ sung này có thể được thực hiện sau khi PATH_RESPONSE được nhận thành công hoặc khi đã nhận đủ byte trên đường dẫn để việc gửi datagram lớn hơn sẽ không dẫn đến việc vượt quá giới hạn chống khuếch đại.

Khác với các trường hợp khác khi datagram được mở rộng, các endpoint KHÔNG ĐƯỢC loại bỏ các datagram có vẻ quá nhỏ khi chúng chứa PATH_CHALLENGE hoặc PATH_RESPONSE.

Path Validation Responses

Khi nhận được một PATH_CHALLENGE frame, endpoint PHẢI phản hồi bằng cách lặp lại dữ liệu chứa trong PATH_CHALLENGE frame trong một PATH_RESPONSE frame. Endpoint KHÔNG ĐƯỢC trì hoãn việc truyền packet chứa PATH_RESPONSE frame trừ khi bị hạn chế bởi kiểm soát tắc nghẽn.

Frame PATH_RESPONSE PHẢI được gửi trên đường dẫn mạng nơi frame PATH_CHALLENGE được nhận. Điều này đảm bảo rằng việc xác thực đường dẫn bởi một peer chỉ thành công nếu đường dẫn hoạt động theo cả hai hướng. Yêu cầu này KHÔNG ĐƯỢC thực thi bởi endpoint khởi tạo xác thực đường dẫn, vì điều đó sẽ cho phép một cuộc tấn công vào việc di chuyển; xem Mục 9.3.3.

Một endpoint PHẢI mở rộng các datagram chứa frame PATH_RESPONSE đến ít nhất kích thước datagram tối đa nhỏ nhất được phép là 1200 byte. Điều này xác minh rằng đường dẫn có thể truyền tải các datagram có kích thước này theo cả hai hướng. Tuy nhiên, một endpoint KHÔNG ĐƯỢC mở rộng datagram chứa PATH_RESPONSE nếu dữ liệu kết quả vượt quá giới hạn chống khuếch đại. Điều này dự kiến chỉ xảy ra nếu PATH_CHALLENGE nhận được không được gửi trong một datagram đã mở rộng.

Một endpoint KHÔNG ĐƯỢC gửi nhiều hơn một PATH_RESPONSE frame để phản hồi một PATH_CHALLENGE frame; xem Mục 13.3. Peer được kỳ vọng sẽ gửi thêm các PATH_CHALLENGE frame khi cần thiết để tạo ra các PATH_RESPONSE frame bổ sung.

Xác thực Địa chỉ trong quá trình Thiết lập Kết nối

Việc xác thực đường dẫn thành công khi nhận được một PATH_RESPONSE frame chứa dữ liệu đã được gửi trong PATH_CHALLENGE frame trước đó. Một PATH_RESPONSE frame được nhận trên bất kỳ đường dẫn mạng nào sẽ xác thực đường dẫn mà PATH_CHALLENGE đã được gửi.

Nếu một endpoint gửi frame PATH_CHALLENGE trong một datagram không được mở rộng đến ít nhất 1200 byte và nếu phản hồi đến nó xác thực địa chỉ peer, đường dẫn được xác thực nhưng MTU đường dẫn thì không. Do đó, endpoint hiện có thể gửi nhiều hơn ba lần lượng dữ liệu đã nhận được. Tuy nhiên, endpoint PHẢI khởi tạo một quá trình xác thực đường dẫn khác với datagram mở rộng để xác minh rằng đường dẫn hỗ trợ MTU yêu cầu.

Việc nhận được xác nhận cho một gói tin chứa PATH_CHALLENGE frame không phải là xác thực đầy đủ, vì xác nhận có thể bị giả mạo bởi một peer độc hại.

Xây dựng Token

Xác thực đường dẫn chỉ thất bại khi điểm cuối đang cố gắng xác thực đường dẫn từ bỏ nỗ lực xác thực đường dẫn của mình.

Các endpoint NÊN từ bỏ việc xác thực đường dẫn dựa trên bộ đếm thời gian. Khi thiết lập bộ đếm thời gian này, các triển khai được cảnh báo rằng đường dẫn mới có thể có thời gian khứ hồi dài hơn so với đường dẫn gốc. Giá trị gấp ba lần số lớn hơn giữa PTO hiện tại hoặc PTO cho đường dẫn mới (sử dụng kInitialRtt, như được định nghĩa trong QUIC-RECOVERY) được KHUYẾN NGHỊ.

Thời gian chờ này cho phép nhiều PTO hết hạn trước khi xác thực đường dẫn thất bại, để việc mất một frame PATH_CHALLENGE hoặc PATH_RESPONSE đơn lẻ không gây ra lỗi xác thực đường dẫn.

Lưu ý rằng endpoint có thể nhận được các gói tin chứa các frame khác trên đường dẫn mới, nhưng một frame PATH_RESPONSE với dữ liệu thích hợp là bắt buộc để việc xác thực đường dẫn thành công.

Khi một endpoint từ bỏ path validation, nó xác định rằng đường dẫn không thể sử dụng được. Điều này không nhất thiết có nghĩa là kết nối bị lỗi – các endpoint có thể tiếp tục gửi packet qua các đường dẫn khác một cách phù hợp. Nếu không có đường dẫn nào khả dụng, một endpoint có thể chờ đợi một đường dẫn mới trở nên khả dụng hoặc đóng kết nối. Một endpoint không có network path hợp lệ tới peer của nó CÓ THỂ báo hiệu điều này bằng cách sử dụng connection error NO_VIABLE_PATH, lưu ý rằng điều này chỉ có thể xảy ra nếu network path tồn tại nhưng không hỗ trợ MTU yêu cầu (Mục 14).

Việc xác thực đường dẫn có thể bị hủy bỏ vì những lý do khác ngoài việc thất bại. Chủ yếu, điều này xảy ra nếu việc di chuyển kết nối sang đường dẫn mới được khởi tạo trong khi quá trình xác thực đường dẫn trên đường dẫn cũ đang diễn ra.

Connection Migration

Sau đây được sao chép từ QUIC RFC 9000. Đối với mỗi phần, hãy xem xét và chỉnh sửa.

Việc sử dụng connection ID cho phép các kết nối có thể duy trì khi địa chỉ endpoint thay đổi (địa chỉ IP và cổng), chẳng hạn như những thay đổi do endpoint di chuyển sang một mạng mới. Phần này mô tả quy trình mà một endpoint di chuyển đến một địa chỉ mới.

Thiết kế của QUIC dựa trên việc các endpoint duy trì một địa chỉ ổn định trong suốt quá trình handshake. Một endpoint KHÔNG ĐƯỢC khởi tạo connection migration trước khi handshake được xác nhận, như được định nghĩa trong Mục 4.1.2 của QUIC-TLS.

Nếu peer đã gửi transport parameter disable_active_migration, một endpoint cũng PHẢI KHÔNG gửi các gói tin (bao gồm cả probing packets; xem Mục 9.1) từ một địa chỉ local khác đến địa chỉ mà peer đã sử dụng trong quá trình handshake, trừ khi endpoint đã thực hiện dựa trên transport parameter preferred_address từ peer. Nếu peer vi phạm yêu cầu này, endpoint PHẢI loại bỏ các gói tin đến trên đường dẫn đó mà không tạo ra Stateless Reset hoặc tiến hành path validation và cho phép peer di chuyển. Việc tạo ra Stateless Reset hoặc đóng kết nối sẽ cho phép các bên thứ ba trong mạng làm đóng các kết nối bằng cách giả mạo hoặc thao tác lưu lượng được quan sát.

Không phải tất cả các thay đổi địa chỉ peer đều là do migration có chủ ý hoặc chủ động. Peer có thể gặp phải NAT rebinding: một thay đổi địa chỉ do middlebox, thường là NAT, phân bổ một port outgoing mới hoặc thậm chí một địa chỉ IP outgoing mới cho một luồng dữ liệu. Một endpoint BẮT BUỘC phải thực hiện path validation (Mục 8.2) nếu phát hiện bất kỳ thay đổi nào đối với địa chỉ của peer, trừ khi trước đó nó đã xác thực địa chỉ đó.

Khi một endpoint không có đường dẫn đã được xác thực để gửi các gói tin, nó CÓ THỂ loại bỏ trạng thái kết nối. Một endpoint có khả năng di chuyển kết nối CÓ THỂ chờ đợi một đường dẫn mới trở nên khả dụng trước khi loại bỏ trạng thái kết nối.

Tài liệu này giới hạn việc di chuyển các kết nối đến địa chỉ client mới, ngoại trừ như được mô tả trong Mục 9.6. Client có trách nhiệm khởi tạo tất cả các di chuyển. Server không gửi các gói non-probing (xem Mục 9.1) đến địa chỉ client cho đến khi chúng thấy một gói non-probing từ địa chỉ đó. Nếu client nhận được các gói từ một địa chỉ server không xác định, client PHẢI loại bỏ những gói này.

Xác thực Địa chỉ Sử dụng Retry Packets

Một endpoint CÓ THỂ thăm dò khả năng kết nối đến peer từ một địa chỉ cục bộ mới bằng cách sử dụng path validation (Mục 8.2) trước khi di chuyển kết nối đến địa chỉ cục bộ mới. Thất bại trong path validation đơn giản có nghĩa là đường dẫn mới không thể sử dụng được cho kết nối này. Thất bại trong việc xác thực một đường dẫn không làm kết thúc kết nối trừ khi không có các đường dẫn thay thế hợp lệ nào khả dụng.

Các frame PATH_CHALLENGE, PATH_RESPONSE, NEW_CONNECTION_ID, và PADDING là “probing frames”, và tất cả các frame khác là “non-probing frames”. Một packet chỉ chứa probing frames là “probing packet”, và một packet chứa bất kỳ frame nào khác là “non-probing packet”.

Xác thực Địa chỉ cho Kết nối Tương lai

Một endpoint có thể di chuyển kết nối đến địa chỉ cục bộ mới bằng cách gửi các gói tin chứa các frame không thăm dò từ địa chỉ đó.

Mỗi endpoint xác thực địa chỉ của peer trong quá trình thiết lập kết nối. Do đó, một endpoint đang di chuyển có thể gửi dữ liệu đến peer của nó với sự hiểu biết rằng peer sẵn sàng nhận tại địa chỉ hiện tại của peer. Vì vậy, một endpoint có thể di chuyển đến một địa chỉ local mới mà không cần xác thực trước địa chỉ của peer.

Để thiết lập khả năng kết nối trên đường dẫn mới, một endpoint khởi tạo xác thực đường dẫn (Section 8.2) trên đường dẫn mới. Một endpoint CÓ THỂ hoãn xác thực đường dẫn cho đến sau khi peer gửi frame không thăm dò tiếp theo đến địa chỉ mới của nó.

Khi di chuyển, đường dẫn mới có thể không hỗ trợ tốc độ gửi hiện tại của endpoint. Do đó, endpoint sẽ đặt lại bộ điều khiển tắc nghẽn và ước tính RTT của nó, như được mô tả trong Mục 9.4.

Đường dẫn mới có thể không có cùng khả năng ECN. Do đó, điểm cuối sẽ xác thực khả năng ECN như được mô tả trong Mục 13.4.

Tính Toàn Vẹn của Token Xác Thực Địa Chỉ

Nhận được một gói tin từ địa chỉ peer mới chứa frame không phải probing cho biết rằng peer đã di chuyển đến địa chỉ đó.

Nếu bên nhận cho phép di chuyển, nó PHẢI gửi các gói tin tiếp theo đến địa chỉ peer mới và PHẢI khởi tạo xác thực đường dẫn (Mục 8.2) để xác minh quyền sở hữu địa chỉ của peer nếu việc xác thực chưa được tiến hành. Nếu bên nhận không có connection ID chưa sử dụng từ peer, nó sẽ không thể gửi bất cứ thứ gì trên đường dẫn mới cho đến khi peer cung cấp một ID; xem Mục 9.5.

Một endpoint chỉ thay đổi địa chỉ mà nó gửi gói tin đến khi phản hồi gói tin không phải probing có số thứ tự cao nhất. Điều này đảm bảo rằng một endpoint không gửi gói tin đến địa chỉ peer cũ trong trường hợp nó nhận được các gói tin bị sắp xếp lại thứ tự.

Một endpoint CÓ THỂ gửi dữ liệu đến một địa chỉ peer chưa được xác thực, nhưng nó PHẢI bảo vệ chống lại các cuộc tấn công tiềm ẩn như được mô tả trong Mục 9.3.1 và 9.3.2. Một endpoint CÓ THỂ bỏ qua việc xác thực địa chỉ peer nếu địa chỉ đó đã được thấy gần đây. Cụ thể, nếu một endpoint quay trở lại một đường dẫn đã được xác thực trước đó sau khi phát hiện một số hình thức di chuyển giả mạo, việc bỏ qua xác thực địa chỉ và khôi phục trạng thái phát hiện mất mát và kiểm soát tắc nghẽn có thể giảm tác động hiệu suất của cuộc tấn công.

Sau khi thay đổi địa chỉ mà nó gửi các gói tin không thăm dò, một endpoint có thể từ bỏ bất kỳ quá trình xác thực đường dẫn nào cho các địa chỉ khác.

Việc nhận một gói tin từ địa chỉ peer mới có thể là kết quả của việc NAT rebinding tại peer.

Sau khi xác minh địa chỉ client mới, server NÊN gửi các token xác thực địa chỉ mới (Mục 8) cho client.

Xác Thực Đường Dẫn

Có thể một peer đang giả mạo địa chỉ nguồn của nó để khiến một endpoint gửi lượng dữ liệu quá mức đến một host không mong muốn. Nếu endpoint gửi nhiều dữ liệu hơn đáng kể so với peer giả mạo, connection migration có thể được sử dụng để khuếch đại lượng dữ liệu mà kẻ tấn công có thể tạo ra nhằm vào nạn nhân.

Như được mô tả trong Mục 9.3, một endpoint được yêu cầu phải xác thực địa chỉ mới của peer để xác nhận peer đó sở hữu địa chỉ mới. Cho đến khi địa chỉ của peer được coi là hợp lệ, một endpoint sẽ giới hạn lượng dữ liệu gửi đến địa chỉ đó; xem Mục 8. Trong trường hợp không có giới hạn này, endpoint có nguy cơ bị sử dụng cho một cuộc tấn công từ chối dịch vụ nhắm vào nạn nhân không nghi ngờ gì.

Nếu một endpoint bỏ qua việc xác thực địa chỉ peer như đã mô tả ở trên, nó không cần phải giới hạn tốc độ gửi của mình.

Khởi tạo Xác thực Đường dẫn

Kẻ tấn công trên đường truyền có thể gây ra việc di chuyển kết nối giả mạo bằng cách sao chép và chuyển tiếp một gói tin với địa chỉ giả mạo sao cho nó đến trước gói tin gốc. Gói tin với địa chỉ giả mạo sẽ được coi là đến từ một kết nối đang di chuyển, và gói tin gốc sẽ được coi là trùng lặp và bị loại bỏ. Sau một cuộc di chuyển giả mạo, việc xác thực địa chỉ nguồn sẽ thất bại vì thực thể tại địa chỉ nguồn không có các khóa mật mã cần thiết để đọc hoặc phản hồi frame PATH_CHALLENGE được gửi đến nó ngay cả khi nó muốn.

Để bảo vệ kết nối khỏi bị lỗi do migration giả mạo như vậy, một endpoint PHẢI hoàn nguyên về việc sử dụng địa chỉ peer được xác thực cuối cùng khi việc xác thực địa chỉ peer mới thất bại. Ngoài ra, việc nhận các gói tin với số thứ tự gói tin cao hơn từ địa chỉ peer hợp pháp sẽ kích hoạt một connection migration khác. Điều này sẽ khiến việc xác thực địa chỉ của migration giả mạo bị hủy bỏ, do đó kiểm soát các migration được khởi tạo bởi kẻ tấn công chỉ bằng việc tiêm một gói tin duy nhất.

Nếu một endpoint không có trạng thái về địa chỉ peer đã được xác thực cuối cùng, nó PHẢI đóng kết nối một cách im lặng bằng cách loại bỏ toàn bộ trạng thái kết nối. Điều này dẫn đến việc các gói tin mới trên kết nối được xử lý một cách tổng quát. Ví dụ, một endpoint CÓ THỂ gửi Stateless Reset để đáp ứng bất kỳ gói tin đến nào tiếp theo.

Phản Hồi Xác Thực Đường Dẫn

Kẻ tấn công ngoài đường truyền có thể quan sát các gói tin và chuyển tiếp các bản sao của gói tin chính hãng đến các điểm cuối. Nếu gói tin được sao chép đến trước gói tin chính hãng, điều này sẽ xuất hiện như một NAT rebinding. Bất kỳ gói tin chính hãng nào sẽ bị loại bỏ như một bản trùng lặp. Nếu kẻ tấn công có thể tiếp tục chuyển tiếp các gói tin, nó có thể gây ra việc di chuyển đến một đường dẫn thông qua kẻ tấn công. Điều này đặt kẻ tấn công vào đường truyền, cho nó khả năng quan sát hoặc loại bỏ tất cả các gói tin tiếp theo.

Kiểu tấn công này dựa vào việc kẻ tấn công sử dụng một đường dẫn có đặc điểm gần giống với đường dẫn trực tiếp giữa các điểm cuối. Cuộc tấn công sẽ đáng tin cậy hơn nếu tương đối ít gói tin được gửi hoặc nếu việc mất gói tin trùng khớp với cuộc tấn công được thực hiện.

Một gói tin không thăm dò được nhận trên đường dẫn gốc mà làm tăng số thứ tự gói tin tối đa đã nhận sẽ khiến endpoint quay trở lại đường dẫn đó. Việc gây ra các gói tin trên đường dẫn này tăng khả năng cuộc tấn công không thành công. Do đó, việc giảm thiểu cuộc tấn công này dựa vào việc kích hoạt trao đổi các gói tin.

Để phản hồi với một cuộc di chuyển rõ ràng, các endpoint PHẢI xác thực đường dẫn đã hoạt động trước đó bằng cách sử dụng khung PATH_CHALLENGE. Điều này dẫn đến việc gửi các gói tin mới trên đường dẫn đó. Nếu đường dẫn không còn khả thi, nỗ lực xác thực sẽ hết thời gian và thất bại; nếu đường dẫn vẫn khả thi nhưng không còn được mong muốn, việc xác thực sẽ thành công nhưng chỉ dẫn đến việc gửi các gói tin thăm dò trên đường dẫn.

Một endpoint nhận được PATH_CHALLENGE trên đường dẫn hoạt động NÊN gửi một gói tin không thăm dò để phản hồi. Nếu gói tin không thăm dò đến trước bất kỳ bản sao nào được tạo bởi kẻ tấn công, điều này dẫn đến việc kết nối được chuyển trở lại đường dẫn gốc. Bất kỳ quá trình di chuyển tiếp theo nào sang đường dẫn khác sẽ khởi động lại toàn bộ quá trình này.

Biện pháp phòng thủ này không hoàn hảo, nhưng điều này không được coi là một vấn đề nghiêm trọng. Nếu đường đi qua cuộc tấn công luôn nhanh hơn đường đi ban đầu một cách đáng tin cậy mặc dù đã nhiều lần cố gắng sử dụng đường đi ban đầu đó, thì không thể phân biệt được giữa một cuộc tấn công và một cải tiến trong định tuyến.

Một endpoint cũng có thể sử dụng các phương pháp heuristic để cải thiện việc phát hiện kiểu tấn công này. Ví dụ, NAT rebinding không có khả năng xảy ra nếu các gói tin gần đây đã được nhận trên đường dẫn cũ; tương tự, rebinding hiếm khi xảy ra trên các đường dẫn IPv6. Các endpoint cũng có thể tìm kiếm các gói tin trùng lặp. Ngược lại, sự thay đổi trong connection ID có nhiều khả năng chỉ ra một migration có chủ ý hơn là một cuộc tấn công.

Xác thực Đường dẫn Thành công

Dung lượng có sẵn trên đường dẫn mới có thể không giống với đường dẫn cũ. Các gói tin được gửi trên đường dẫn cũ KHÔNG ĐƯỢC góp phần vào việc kiểm soát tắc nghẽn hoặc ước tính RTT cho đường dẫn mới.

Khi xác nhận quyền sở hữu địa chỉ mới của một peer, một endpoint PHẢI ngay lập tức đặt lại congestion controller và round-trip time estimator cho đường dẫn mới về các giá trị ban đầu (xem Phụ lục A.3 và B.3 của QUIC-RECOVERY) trừ khi thay đổi duy nhất trong địa chỉ của peer là số cổng của nó. Vì các thay đổi chỉ ở cổng thường là kết quả của NAT rebinding hoặc hoạt động của middlebox khác, endpoint CÓ THỂ thay vào đó giữ lại trạng thái điều khiển tắc nghẽn và ước tính round-trip trong những trường hợp đó thay vì quay về các giá trị ban đầu. Trong những trường hợp mà trạng thái điều khiển tắc nghẽn được giữ lại từ một đường dẫn cũ được sử dụng trên một đường dẫn mới với các đặc tính khác biệt đáng kể, một sender có thể truyền quá mạnh mẽ cho đến khi congestion controller và RTT estimator đã thích nghi. Nói chung, các triển khai được khuyên nên thận trọng khi sử dụng các giá trị trước đó trên một đường dẫn mới.

Có thể có hiện tượng sắp xếp lại rõ rệt tại bên nhận khi một endpoint gửi dữ liệu và các probe từ/đến nhiều địa chỉ trong giai đoạn migration, vì hai đường dẫn kết quả có thể có thời gian khứ hồi khác nhau. Bên nhận các gói tin trên nhiều đường dẫn vẫn sẽ gửi các ACK frame bao phủ tất cả các gói tin đã nhận.

Mặc dù có thể sử dụng nhiều đường dẫn trong quá trình di chuyển kết nối, một bối cảnh kiểm soát tắc nghẽn duy nhất và một bối cảnh khôi phục mất mát duy nhất (như được mô tả trong QUIC-RECOVERY) có thể là đủ. Ví dụ, một endpoint có thể trì hoãn việc chuyển đổi sang bối cảnh kiểm soát tắc nghẽn mới cho đến khi được xác nhận rằng đường dẫn cũ không còn cần thiết nữa (chẳng hạn như trường hợp được mô tả trong Mục 9.3.3).

Bên gửi có thể tạo ra các ngoại lệ cho các gói probe để việc phát hiện mất gói của chúng độc lập và không gây ra việc bộ điều khiển tắc nghẽn giảm tốc độ gửi một cách không hợp lý. Một endpoint có thể đặt một bộ đếm thời gian riêng biệt khi một PATH_CHALLENGE được gửi, bộ đếm này sẽ bị hủy nếu PATH_RESPONSE tương ứng được nhận. Nếu bộ đếm thời gian kích hoạt trước khi PATH_RESPONSE được nhận, endpoint có thể gửi một PATH_CHALLENGE mới và khởi động lại bộ đếm thời gian trong một khoảng thời gian dài hơn. Bộ đếm thời gian này NÊN được đặt như mô tả trong Mục 6.2.1 của QUIC-RECOVERY và KHÔNG ĐƯỢC tích cực hơn.

Xác thực Đường dẫn Thất bại

Việc sử dụng một connection ID ổn định trên nhiều đường dẫn mạng sẽ cho phép một người quan sát thụ động liên kết hoạt động giữa các đường dẫn đó. Một endpoint di chuyển giữa các mạng có thể không muốn hoạt động của họ được liên kết bởi bất kỳ thực thể nào khác ngoài peer của họ, vì vậy các connection ID khác nhau được sử dụng khi gửi từ các địa chỉ local khác nhau, như đã thảo luận trong Mục 5.1. Để điều này có hiệu quả, các endpoint cần đảm bảo rằng các connection ID mà họ cung cấp không thể được liên kết bởi bất kỳ thực thể nào khác.

Tại bất kỳ thời điểm nào, các endpoint CÓ THỂ thay đổi Destination Connection ID mà chúng truyền với một giá trị chưa được sử dụng trên đường dẫn khác.

Một endpoint KHÔNG ĐƯỢC tái sử dụng connection ID khi gửi từ nhiều hơn một địa chỉ local – ví dụ, khi khởi tạo connection migration như mô tả trong Mục 9.2 hoặc khi thăm dò một network path mới như mô tả trong Mục 9.1.

Tương tự, một endpoint KHÔNG ĐƯỢC tái sử dụng connection ID khi gửi đến nhiều hơn một địa chỉ đích. Do những thay đổi mạng nằm ngoài tầm kiểm soát của peer, một endpoint có thể nhận các gói tin từ một địa chỉ nguồn mới với cùng giá trị trường Destination Connection ID, trong trường hợp đó nó CÓ THỂ tiếp tục sử dụng connection ID hiện tại với địa chỉ remote mới trong khi vẫn gửi từ cùng địa chỉ local.

Các yêu cầu về việc tái sử dụng connection ID này chỉ áp dụng cho việc gửi các gói tin, vì những thay đổi không có chủ ý trong đường dẫn mà không có sự thay đổi trong connection ID là có thể xảy ra. Ví dụ, sau một khoảng thời gian không hoạt động mạng, NAT rebinding có thể khiến các gói tin được gửi trên một đường dẫn mới khi client tiếp tục gửi. Một endpoint phản hồi với sự kiện như vậy như được mô tả trong Phần 9.3.

Sử dụng các connection ID khác nhau cho các gói tin được gửi theo cả hai hướng trên mỗi đường mạng mới sẽ loại bỏ việc sử dụng connection ID để liên kết các gói tin từ cùng một kết nối qua các đường mạng khác nhau. Bảo vệ header đảm bảo rằng số thứ tự gói tin không thể được sử dụng để tương quan hoạt động. Điều này không ngăn chặn các thuộc tính khác của gói tin, như thời gian và kích thước, khỏi việc được sử dụng để tương quan hoạt động.

Một endpoint NÊN KHÔNG khởi tạo migration với một peer đã yêu cầu connection ID có độ dài bằng không, bởi vì lưu lượng trên đường dẫn mới có thể được liên kết một cách tầm thường với lưu lượng trên đường dẫn cũ. Nếu server có thể liên kết các gói tin với connection ID có độ dài bằng không đến đúng kết nối, điều đó có nghĩa là server đang sử dụng thông tin khác để phân tách gói tin. Ví dụ, một server có thể cung cấp một địa chỉ duy nhất cho mỗi client – chẳng hạn, sử dụng HTTP alternative services ALTSVC. Thông tin có thể cho phép định tuyến chính xác các gói tin qua nhiều đường dẫn mạng cũng sẽ cho phép hoạt động trên những đường dẫn đó được liên kết bởi các thực thể khác ngoài peer.

Một client có thể muốn giảm khả năng liên kết bằng cách chuyển sang connection ID mới, source UDP port mới, hoặc địa chỉ IP mới (xem RFC8981) khi gửi traffic sau một khoảng thời gian không hoạt động. Việc thay đổi địa chỉ mà nó gửi packet cùng lúc có thể khiến server phát hiện connection migration. Điều này đảm bảo rằng các cơ chế hỗ trợ migration được thực thi ngay cả đối với các client không gặp phải NAT rebinding hoặc migration thực sự. Việc thay đổi địa chỉ có thể khiến peer reset trạng thái congestion control của nó (xem Mục 9.4), do đó địa chỉ CHỈ NÊN được thay đổi thỉnh thoảng.

Một endpoint đã cạn kiệt các connection ID khả dụng không thể thăm dò các path mới hoặc khởi tạo migration, cũng không thể phản hồi các probe hoặc nỗ lực migration từ peer của nó. Để đảm bảo rằng migration có thể thực hiện được và các gói tin được gửi trên các path khác nhau không thể bị liên kết với nhau, các endpoint NÊN cung cấp các connection ID mới trước khi peer thực hiện migration; xem Mục 5.1.1. Nếu một peer có thể đã cạn kiệt các connection ID khả dụng, một endpoint đang migration có thể bao gồm một NEW_CONNECTION_ID frame trong tất cả các gói tin được gửi trên một network path mới.

Server’s Preferred Address

QUIC cho phép các máy chủ chấp nhận kết nối trên một địa chỉ IP và cố gắng chuyển những kết nối này sang một địa chỉ ưu tiên hơn ngay sau khi bắt tay hoàn tất. Điều này đặc biệt hữu ích khi các client ban đầu kết nối tới một địa chỉ được chia sẻ bởi nhiều máy chủ nhưng muốn sử dụng địa chỉ unicast để đảm bảo tính ổn định của kết nối. Phần này mô tả giao thức để di chuyển kết nối sang địa chỉ máy chủ ưu tiên.

Việc di chuyển kết nối đến địa chỉ máy chủ mới giữa kết nối không được hỗ trợ bởi phiên bản QUIC được chỉ định trong tài liệu này. Nếu client nhận được các gói tin từ địa chỉ máy chủ mới khi client chưa khởi tạo việc di chuyển đến địa chỉ đó, client NÊN loại bỏ các gói tin này.

Thăm Dò Một Đường Dẫn Mới

Một server truyền đạt địa chỉ ưa thích bằng cách bao gồm tham số transport preferred_address trong quá trình bắt tay TLS.

Máy chủ CÓ THỂ thông báo địa chỉ ưa thích của từng họ địa chỉ (IPv4 và IPv6) để cho phép các client chọn địa chỉ phù hợp nhất với kết nối mạng của họ.

Sau khi handshake được xác nhận, client NÊN chọn một trong hai địa chỉ được server cung cấp và khởi tạo path validation (xem Mục 8.2). Client xây dựng các gói tin sử dụng bất kỳ connection ID đang hoạt động chưa được sử dụng trước đó nào, lấy từ transport parameter preferred_address hoặc frame NEW_CONNECTION_ID.

Ngay khi việc xác thực đường dẫn thành công, client NÊN bắt đầu gửi tất cả các gói tin tương lai đến địa chỉ server mới bằng cách sử dụng connection ID mới và ngừng sử dụng địa chỉ server cũ. Nếu việc xác thực đường dẫn thất bại, client PHẢI tiếp tục gửi tất cả các gói tin tương lai đến địa chỉ IP gốc của server.

Khởi tạo Connection Migration

Một client di chuyển đến một địa chỉ ưu tiên PHẢI xác thực địa chỉ mà nó chọn trước khi di chuyển; xem Mục 21.5.3.

Một server có thể nhận được một packet được gửi đến địa chỉ IP ưa thích của nó bất kỳ lúc nào sau khi nó chấp nhận một kết nối. Nếu packet này chứa một PATH_CHALLENGE frame, server sẽ gửi một packet chứa PATH_RESPONSE frame theo Mục 8.2. Server PHẢI gửi các packet không thăm dò từ địa chỉ gốc của nó cho đến khi nhận được một packet không thăm dò từ client tại địa chỉ ưa thích của nó và cho đến khi server đã xác thực đường dẫn mới.

Server PHẢI thăm dò trên đường dẫn hướng về phía client từ địa chỉ ưa thích của nó. Điều này giúp bảo vệ chống lại việc migration giả mạo được khởi tạo bởi kẻ tấn công.

Khi server đã hoàn thành việc xác thực đường dẫn và đã nhận được một gói tin không thăm dò với số thứ tự gói tin lớn nhất mới trên địa chỉ ưu tiên của nó, server bắt đầu gửi các gói tin không thăm dò đến client chỉ từ địa chỉ IP ưu tiên của nó. Server NÊN loại bỏ các gói tin mới hơn cho kết nối này được nhận trên địa chỉ IP cũ. Server CÓ THỂ tiếp tục xử lý các gói tin bị trễ được nhận trên địa chỉ IP cũ.

Các địa chỉ mà một server cung cấp trong tham số transport preferred_address chỉ có hiệu lực cho kết nối mà chúng được cung cấp. Client KHÔNG ĐƯỢC sử dụng những địa chỉ này cho các kết nối khác, bao gồm cả các kết nối được khôi phục từ kết nối hiện tại.

Phản hồi với Migration Kết nối

Một client có thể cần thực hiện connection migration trước khi nó đã migrate đến địa chỉ ưa thích của server. Trong trường hợp này, client NÊN thực hiện path validation đến cả địa chỉ server gốc và địa chỉ ưa thích từ địa chỉ mới của client một cách đồng thời.

Nếu việc xác thực đường dẫn của địa chỉ ưa thích của server thành công, client PHẢI từ bỏ việc xác thực địa chỉ gốc và chuyển sang sử dụng địa chỉ ưa thích của server. Nếu việc xác thực đường dẫn của địa chỉ ưa thích của server thất bại nhưng việc xác thực địa chỉ gốc của server thành công, client CÓ THỂ chuyển đến địa chỉ mới của nó và tiếp tục gửi đến địa chỉ gốc của server.

Nếu các gói tin nhận được tại địa chỉ ưa thích của server có địa chỉ nguồn khác với địa chỉ quan sát được từ client trong quá trình handshake, server PHẢI bảo vệ chống lại các cuộc tấn công tiềm ẩn như mô tả trong Mục 9.3.1 và 9.3.2. Ngoài việc di chuyển đồng thời có chủ ý, điều này cũng có thể xảy ra do mạng truy cập của client sử dụng một ràng buộc NAT khác cho địa chỉ ưa thích của server.

Servers NÊN khởi tạo việc xác thực đường dẫn đến địa chỉ mới của client khi nhận được gói probe từ một địa chỉ khác; xem Mục 8.

Một client di chuyển đến địa chỉ mới NÊN sử dụng địa chỉ ưu tiên từ cùng họ địa chỉ cho server.

Connection ID được cung cấp trong transport parameter preferred_address không cụ thể cho các địa chỉ được cung cấp. Connection ID này được cung cấp để đảm bảo rằng client có sẵn một connection ID để di chuyển, nhưng client CÓ THỂ sử dụng connection ID này trên bất kỳ đường dẫn nào.

Giả mạo Địa chỉ Peer

QUIC khuyến nghị các endpoint gửi dữ liệu sử dụng IPv6 NÊN áp dụng IPv6 flow label tuân thủ RFC 6437, trừ khi API cục bộ không cho phép thiết lập IPv6 flow labels.

Thật không may, Java API không cho phép thiết lập flow labels IPv6.

Các Mục Tiêu Không Ưu Tiên

Sau đây được sao chép từ QUIC RFC 9000. Đối với mỗi phần, hãy xem xét và chỉnh sửa.

Mục tiêu của QUIC là cung cấp một kết nối vận chuyển an toàn. Phần 21.1 cung cấp tổng quan về những tính chất đó; các phần tiếp theo thảo luận về các ràng buộc và cảnh báo liên quan đến những tính chất này, bao gồm mô tả về các cuộc tấn công đã biết và các biện pháp đối phó.

Giả Mạo Địa Chỉ Trên Đường Truyền

Một phân tích bảo mật hoàn chỉnh về QUIC nằm ngoài phạm vi của tài liệu này. Phần này cung cấp mô tả không chính thức về các thuộc tính bảo mật mong muốn như một trợ giúp cho người triển khai và để hướng dẫn phân tích giao thức.

QUIC giả định mô hình mối đe dọa được mô tả trong SEC-CONS và cung cấp các biện pháp bảo vệ chống lại nhiều cuộc tấn công phát sinh từ mô hình đó.

Vì mục đích này, các cuộc tấn công được phân chia thành tấn công thụ động và tấn công chủ động. Kẻ tấn công thụ động có khả năng đọc các gói tin từ mạng, trong khi kẻ tấn công chủ động cũng có khả năng ghi các gói tin vào mạng. Tuy nhiên, một cuộc tấn công thụ động có thể bao gồm kẻ tấn công có khả năng gây ra thay đổi định tuyến hoặc sửa đổi khác trong đường dẫn được thực hiện bởi các gói tin tạo nên một kết nối.

Kẻ tấn công được phân loại thêm thành kẻ tấn công trên đường truyền (on-path) hoặc kẻ tấn công ngoài đường truyền (off-path). Kẻ tấn công trên đường truyền có thể đọc, sửa đổi, hoặc loại bỏ bất kỳ gói tin nào mà nó quan sát được sao cho gói tin đó không còn đến được đích, trong khi kẻ tấn công ngoài đường truyền quan sát các gói tin nhưng không thể ngăn gói tin gốc đến được đích dự định. Cả hai loại kẻ tấn công cũng có thể truyền các gói tin tùy ý. Định nghĩa này khác với định nghĩa trong Mục 3.5 của SEC-CONS ở chỗ kẻ tấn công ngoài đường truyền có thể quan sát các gói tin.

Các thuộc tính của handshake, gói tin được bảo vệ và di chuyển kết nối được xem xét riêng biệt.

Chuyển tiếp Gói tin Ngoài Đường dẫn

Quá trình handshake QUIC tích hợp handshake TLS 1.3 và kế thừa các thuộc tính mật mã được mô tả trong Phụ lục E.1 của TLS13. Nhiều thuộc tính bảo mật của QUIC phụ thuộc vào handshake TLS cung cấp các thuộc tính này. Bất kỳ cuộc tấn công nào vào handshake TLS đều có thể ảnh hưởng đến QUIC.

Bất kỳ cuộc tấn công nào vào quá trình bắt tay TLS làm tổn hại đến tính bí mật hoặc tính duy nhất của các khóa phiên, hoặc xác thực của các peer tham gia, đều ảnh hưởng đến các đảm bảo bảo mật khác được cung cấp bởi QUIC phụ thuộc vào những khóa đó. Ví dụ, migration (Phần 9) phụ thuộc vào hiệu quả của các biện pháp bảo vệ tính bí mật, cả cho việc thương lượng khóa sử dụng quá trình bắt tay TLS và cho việc bảo vệ gói tin QUIC, để tránh khả năng liên kết qua các đường dẫn mạng.

Một cuộc tấn công vào tính toàn vẹn của quá trình bắt tay TLS có thể cho phép kẻ tấn công ảnh hưởng đến việc lựa chọn giao thức ứng dụng hoặc phiên bản QUIC.

Ngoài các thuộc tính được cung cấp bởi TLS, quá trình bắt tay QUIC còn cung cấp một số biện pháp phòng thủ chống lại các cuộc tấn công DoS trên quá trình bắt tay.

Phát hiện mất mát và kiểm soát tắc nghẽn

Xác thực địa chỉ (Mục 8) được sử dụng để xác minh rằng một thực thể tuyên bố sở hữu một địa chỉ nhất định có thể nhận các gói tin tại địa chỉ đó. Xác thực địa chỉ giới hạn các mục tiêu tấn công khuếch đại chỉ đối với những địa chỉ mà kẻ tấn công có thể quan sát các gói tin.

Trước khi xác thực địa chỉ, các endpoint bị hạn chế về những gì chúng có thể gửi. Các endpoint không thể gửi dữ liệu đến một địa chỉ chưa được xác thực với lượng vượt quá ba lần dữ liệu đã nhận từ địa chỉ đó.

Lưu ý: Giới hạn chống khuếch đại chỉ áp dụng khi một endpoint phản hồi các gói tin nhận được từ một địa chỉ chưa được xác thực. Giới hạn chống khuếch đại không áp dụng cho các client khi thiết lập kết nối mới hoặc khi khởi tạo di chuyển kết nối.

Tác động về Quyền riêng tư của Việc Di chuyển Kết nối

Tính toán first flight của server cho một full handshake có thể tốn kém, yêu cầu cả tính toán chữ ký và trao đổi khóa. Để ngăn chặn các cuộc tấn công DoS tính toán, Retry packet cung cấp một cơ chế trao đổi token rẻ cho phép server xác thực địa chỉ IP của client trước khi thực hiện bất kỳ tính toán tốn kém nào với chi phí của một lượt round trip duy nhất. Sau một handshake thành công, server có thể phát hành token mới cho client, điều này sẽ cho phép thiết lập kết nối mới mà không phải chịu chi phí này.

Địa Chỉ Ưa Thích của Server

Một kẻ tấn công on-path hoặc off-path có thể buộc quá trình handshake thất bại bằng cách thay thế hoặc racing các gói Initial. Khi các gói Initial hợp lệ đã được trao đổi, các gói Handshake tiếp theo được bảo vệ bằng các khóa Handshake, và một kẻ tấn công on-path không thể buộc handshake thất bại ngoại trừ việc loại bỏ các gói để khiến các endpoint từ bỏ nỗ lực kết nối.

Một kẻ tấn công on-path cũng có thể thay thế địa chỉ của các gói tin ở cả hai phía và do đó khiến client hoặc server có cái nhìn không chính xác về các địa chỉ từ xa. Một cuộc tấn công như vậy không thể phân biệt được với các chức năng được thực hiện bởi NAT.

Thông báo Địa chỉ Ưu tiên

Toàn bộ quá trình handshake được bảo vệ bằng mật mã học, với các gói Initial được mã hóa bằng khóa theo từng phiên bản và các gói Handshake cùng các gói sau đó được mã hóa bằng khóa được tạo ra từ quá trình trao đổi khóa TLS. Hơn nữa, việc thương lượng tham số được tích hợp vào transcript TLS và do đó cung cấp các đảm bảo tính toàn vẹn giống như thương lượng TLS thông thường. Kẻ tấn công có thể quan sát các tham số truyền tải của client (miễn là nó biết salt cụ thể theo phiên bản) nhưng không thể quan sát các tham số truyền tải của server và không thể ảnh hưởng đến việc thương lượng tham số.

ID kết nối không được mã hóa nhưng được bảo vệ tính toàn vẹn trong tất cả các gói tin.

Phiên bản QUIC này không tích hợp cơ chế thương lượng phiên bản; các triển khai của các phiên bản không tương thích sẽ đơn giản là thất bại trong việc thiết lập kết nối.

Di chuyển đến Địa chỉ Ưu tiên

Bảo vệ gói tin (Mục 12.1) áp dụng mã hóa xác thực cho tất cả các gói tin ngoại trừ các gói tin Version Negotiation, mặc dù các gói tin Initial và Retry có mức bảo vệ hạn chế do sử dụng tài liệu khóa đặc thù cho phiên bản; xem QUIC-TLS để biết thêm chi tiết. Mục này xem xét các cuộc tấn công thụ động và chủ động chống lại các gói tin được bảo vệ.

Cả những kẻ tấn công trên đường truyền và ngoài đường truyền đều có thể thực hiện cuộc tấn công thụ động trong đó chúng lưu trữ các gói tin đã quan sát để tấn công ngoại tuyến chống lại bảo vệ gói tin trong tương lai; điều này đúng với bất kỳ người quan sát nào của bất kỳ gói tin nào trên bất kỳ mạng nào.

Kẻ tấn công thực hiện inject packets mà không thể quan sát các gói tin hợp lệ cho một kết nối thì khó có thể thành công, vì packet protection đảm bảo rằng các gói tin hợp lệ chỉ được tạo ra bởi các endpoints sở hữu key material được thiết lập trong quá trình handshake; xem Phần 7 và 21.1.1. Tương tự, bất kỳ kẻ tấn công chủ động nào quan sát các gói tin và cố gắng chèn dữ liệu mới hoặc sửa đổi dữ liệu hiện có trong những gói tin đó sẽ không thể tạo ra các gói tin được endpoint nhận coi là hợp lệ, ngoại trừ các Initial packets.

Một cuộc tấn công spoofing, trong đó kẻ tấn công chủ động ghi đè các phần không được bảo vệ của gói tin mà nó chuyển tiếp hoặc đưa vào, chẳng hạn như địa chỉ nguồn hoặc đích, chỉ có hiệu quả nếu kẻ tấn công có thể chuyển tiếp các gói tin đến điểm cuối ban đầu. Bảo vệ gói tin đảm bảo rằng tải trọng gói tin chỉ có thể được xử lý bởi các điểm cuối đã hoàn thành handshake, và các gói tin không hợp lệ sẽ bị bỏ qua bởi những điểm cuối đó.

Kẻ tấn công cũng có thể sửa đổi ranh giới giữa các packet và UDP datagram, khiến nhiều packet được kết hợp thành một datagram duy nhất hoặc tách các packet đã kết hợp thành nhiều datagram. Ngoài các datagram chứa packet Initial, vốn yêu cầu padding, việc sửa đổi cách sắp xếp packet trong datagram không có tác động chức năng đến kết nối, mặc dù nó có thể thay đổi một số đặc tính hiệu suất.

Tương tác giữa Client Migration và Preferred Address

Di chuyển kết nối (Phần 9) cung cấp cho các endpoint khả năng chuyển đổi giữa các địa chỉ IP và cổng trên nhiều đường dẫn, sử dụng một đường dẫn tại một thời điểm để truyền và nhận các frame không phải thăm dò. Xác thực đường dẫn (Phần 8.2) thiết lập rằng một peer vừa sẵn sàng vừa có khả năng nhận các gói tin được gửi trên một đường dẫn cụ thể. Điều này giúp giảm tác động của việc giả mạo địa chỉ bằng cách hạn chế số lượng gói tin được gửi đến một địa chỉ giả mạo.

Phần này mô tả các thuộc tính bảo mật dự định của việc di chuyển kết nối dưới các loại tấn công DoS khác nhau.

Sử dụng Nhãn Luồng IPv6 và Di chuyển

Kẻ tấn công có thể khiến một gói tin mà nó quan sát được không còn đến được đích đến dự định được coi là kẻ tấn công on-path. Khi một kẻ tấn công có mặt giữa client và server, các endpoint phải gửi gói tin thông qua kẻ tấn công để thiết lập kết nối trên một đường dẫn nhất định.

Kẻ tấn công trên đường truyền có thể:

  • Kiểm tra các gói tin

  • Sửa đổi header của gói tin IP và UDP

  • Tiêm các gói tin mới

  • Trì hoãn các gói tin

  • Sắp xếp lại các gói tin

  • Loại bỏ các gói tin

  • Chia tách và hợp nhất datagram theo ranh giới packet

Kẻ tấn công trên đường truyền không thể:

  • Sửa đổi một phần được xác thực của gói tin và khiến người nhận chấp nhận gói tin đó

Kẻ tấn công trên đường truyền có cơ hội sửa đổi các gói tin mà nó quan sát được; tuy nhiên, bất kỳ sửa đổi nào đối với phần được xác thực của gói tin sẽ khiến nó bị endpoint nhận loại bỏ vì không hợp lệ, do tải trọng gói tin vừa được xác thực vừa được mã hóa.

QUIC nhằm mục đích hạn chế các khả năng của kẻ tấn công trên đường truyền như sau:

  1. Kẻ tấn công trên đường truyền có thể ngăn chặn việc sử dụng một đường đi cho kết nối, khiến kết nối thất bại nếu nó không thể sử dụng một đường đi khác không chứa kẻ tấn công. Điều này có thể đạt được bằng cách loại bỏ tất cả các gói tin, sửa đổi chúng để chúng không thể giải mã, hoặc các phương pháp khác.

  2. Một kẻ tấn công trên đường dẫn có thể ngăn chặn việc di chuyển đến một đường dẫn mới mà kẻ tấn công cũng nằm trên đường dẫn đó bằng cách khiến quá trình xác thực đường dẫn thất bại trên đường dẫn mới.

  3. Kẻ tấn công trên đường truyền không thể ngăn cản client di chuyển đến một đường truyền mà kẻ tấn công không có mặt trên đó.

  4. Kẻ tấn công trên đường truyền có thể giảm throughput của kết nối bằng cách trì hoãn các gói tin hoặc loại bỏ chúng.

  5. Một kẻ tấn công trên đường truyền không thể khiến một endpoint chấp nhận một gói tin mà nó đã sửa đổi phần được xác thực của gói tin đó.

Off-Path Active Attacks

Kẻ tấn công off-path không nằm trực tiếp trên đường truyền giữa client và server nhưng có thể thu được bản sao của một số hoặc tất cả các gói tin được gửi giữa client và server. Nó cũng có khả năng gửi bản sao của những gói tin đó đến một trong hai điểm cuối.

Kẻ tấn công ngoài đường dẫn có thể:

  • Kiểm tra các gói tin

  • Chèn các gói tin mới

  • Sắp xếp lại các gói tin được chèn vào

Kẻ tấn công off-path không thể:

  • Sửa đổi các gói tin được gửi bởi các điểm cuối

  • Trì hoãn các gói tin

  • Loại bỏ các gói tin

  • Sắp xếp lại các gói tin gốc

Kẻ tấn công off-path có thể tạo ra các bản sao đã chỉnh sửa của các gói tin mà nó đã quan sát được và tiêm những bản sao đó vào mạng, có khả năng với các địa chỉ nguồn và đích giả mạo.

Với mục đích của cuộc thảo luận này, giả định rằng kẻ tấn công off-path có khả năng đưa một bản sao đã chỉnh sửa của gói tin vào mạng mà sẽ đến điểm đích trước khi gói tin gốc mà kẻ tấn công quan sát được đến nơi. Nói cách khác, kẻ tấn công có khả năng liên tục “thắng” trong cuộc đua với các gói tin hợp pháp giữa các điểm cuối, có thể khiến gói tin gốc bị người nhận bỏ qua.

Cũng được giả định rằng kẻ tấn công có đủ tài nguyên cần thiết để tác động đến trạng thái NAT. Cụ thể, kẻ tấn công có thể khiến một endpoint mất ràng buộc NAT của nó và sau đó chiếm được cùng một port để sử dụng cho lưu lượng của chính mình.

QUIC nhằm mục đích hạn chế khả năng của kẻ tấn công off-path như sau:

  1. Kẻ tấn công ngoài đường truyền có thể đua gói tin và cố gắng trở thành kẻ tấn công “hạn chế” trên đường truyền.

  2. Kẻ tấn công off-path có thể làm cho quá trình xác thực đường dẫn thành công đối với các gói tin được chuyển tiếp với địa chỉ nguồn được liệt kê là kẻ tấn công off-path miễn là nó có thể cung cấp kết nối được cải thiện giữa client và server.

  3. Kẻ tấn công off-path không thể khiến kết nối đóng sau khi quá trình bắt tay đã hoàn tất.

  4. Kẻ tấn công ngoài đường dẫn không thể khiến việc di chuyển sang đường dẫn mới bị thất bại nếu chúng không thể quan sát được đường dẫn mới.

  5. Kẻ tấn công ngoài đường dẫn có thể trở thành kẻ tấn công trên đường dẫn hạn chế trong quá trình di chuyển sang đường dẫn mới mà tại đó chúng cũng là kẻ tấn công ngoài đường dẫn.

  6. Một kẻ tấn công off-path có thể trở thành kẻ tấn công on-path hạn chế bằng cách ảnh hưởng đến trạng thái NAT chung để gửi các gói tin đến server từ cùng địa chỉ IP và port mà client ban đầu đã sử dụng.

Tổng quan về Các Thuộc tính Bảo mật

Kẻ tấn công trên đường truyền hạn chế là một kẻ tấn công ngoài đường truyền đã cung cấp việc định tuyến cải tiến các gói tin bằng cách sao chép và chuyển tiếp các gói tin gốc giữa máy chủ và máy khách, khiến những gói tin đó đến trước các bản sao gốc để các gói tin gốc bị điểm cuối đích loại bỏ.

Kẻ tấn công on-path hạn chế khác với kẻ tấn công on-path ở chỗ nó không nằm trên đường dẫn gốc giữa các điểm cuối, và do đó các gói tin gốc được gửi bởi một điểm cuối vẫn đến được đích của chúng. Điều này có nghĩa là việc thất bại trong tương lai khi định tuyến các gói tin sao chép đến đích nhanh hơn đường dẫn gốc của chúng sẽ không ngăn cản các gói tin gốc đến được đích.

Một kẻ tấn công on-path có giới hạn có thể:

  • Kiểm tra các gói tin

  • Tiêm các gói tin mới

  • Sửa đổi header gói tin không mã hóa

  • Sắp xếp lại các gói tin

Kẻ tấn công on-path có giới hạn không thể:

  • Trì hoãn các gói tin để chúng đến muộn hơn so với các gói tin được gửi trên đường dẫn gốc

  • Loại bỏ các gói tin

  • Sửa đổi phần được xác thực và mã hóa của một gói tin và khiến người nhận chấp nhận gói tin đó

Kẻ tấn công giới hạn trên đường truyền (limited on-path attacker) chỉ có thể trì hoãn các gói tin đến mức các gói tin gốc đến trước các gói tin trùng lặp, có nghĩa là nó không thể cung cấp định tuyến với độ trễ tồi tệ hơn đường truyền gốc. Nếu kẻ tấn công giới hạn trên đường truyền loại bỏ các gói tin, bản sao gốc vẫn sẽ đến điểm cuối đích.

QUIC nhằm mục đích hạn chế khả năng của một kẻ tấn công off-path hạn chế như sau:

  1. Một kẻ tấn công on-path có hạn chế không thể làm đóng một kết nối sau khi quá trình handshake đã hoàn thành.

  2. Kẻ tấn công on-path có hạn không thể làm đóng một kết nối nhàn rỗi nếu client là bên đầu tiên khôi phục hoạt động.

  3. Một kẻ tấn công on-path có giới hạn có thể khiến một kết nối nhàn rỗi bị coi là mất kết nối nếu máy chủ là bên đầu tiên khôi phục hoạt động.

Lưu ý rằng những đảm bảo này là những đảm bảo tương tự được cung cấp cho bất kỳ NAT nào, vì những lý do giống nhau.

Bắt tay

Là một giao thức truyền tải được mã hóa và xác thực, QUIC cung cấp nhiều biện pháp bảo vệ chống lại tấn công từ chối dịch vụ. Khi quá trình bắt tay mật mã hoàn tất, các endpoint QUIC sẽ loại bỏ hầu hết các gói tin không được xác thực, giới hạn đáng kể khả năng của kẻ tấn công can thiệp vào các kết nối hiện có.

Sau khi kết nối được thiết lập, các QUIC endpoint có thể chấp nhận một số gói tin ICMP không được xác thực (xem Mục 14.2.1), nhưng việc sử dụng các gói tin này rất hạn chế. Loại gói tin duy nhất khác mà một endpoint có thể chấp nhận là stateless reset (Mục 10.3), dựa trên việc token được giữ bí mật cho đến khi được sử dụng.

Trong quá trình tạo kết nối, QUIC chỉ cung cấp bảo vệ chống lại các cuộc tấn công từ bên ngoài đường dẫn mạng. Tất cả các gói tin QUIC đều chứa bằng chứng rằng người nhận đã thấy một gói tin trước đó từ đối tác của nó.

Địa chỉ không thể thay đổi trong quá trình handshake, vì vậy các endpoint có thể loại bỏ các gói tin được nhận trên một đường dẫn mạng khác.

Các trường Source và Destination Connection ID là phương tiện chính để bảo vệ chống lại cuộc tấn công off-path trong quá trình handshake; xem Phần 8.1. Chúng được yêu cầu phải khớp với những giá trị được đặt bởi peer. Ngoại trừ Initial và Stateless Resets, một endpoint chỉ chấp nhận các packet bao gồm trường Destination Connection ID khớp với giá trị mà endpoint đã chọn trước đó. Đây là biện pháp bảo vệ duy nhất được cung cấp cho các packet Version Negotiation.

Trường Destination Connection ID trong gói Initial được client lựa chọn để không thể dự đoán được, điều này phục vụ một mục đích bổ sung. Các gói mang thông tin handshake mật mã được bảo vệ bằng một khóa được tạo ra từ connection ID này và một salt cụ thể cho phiên bản QUIC. Điều này cho phép các endpoint sử dụng cùng một quy trình để xác thực các gói mà chúng nhận được như cách chúng sử dụng sau khi quá trình handshake mật mã hoàn thành. Các gói không thể được xác thực sẽ bị loại bỏ. Việc bảo vệ các gói theo cách này cung cấp sự đảm bảo mạnh mẽ rằng người gửi gói đã thấy gói Initial và hiểu được nó.

Những biện pháp bảo vệ này không được thiết kế để có hiệu quả chống lại kẻ tấn công có thể nhận các gói QUIC trước khi kết nối được thiết lập. Kẻ tấn công như vậy có thể gửi các gói tin mà các endpoint QUIC sẽ chấp nhận. Phiên bản QUIC này cố gắng phát hiện loại tấn công này, nhưng nó mong đợi rằng các endpoint sẽ thất bại trong việc thiết lập kết nối thay vì khôi phục. Phần lớn, giao thức bắt tay mật mã QUIC-TLS chịu trách nhiệm phát hiện sự can thiệp trong quá trình bắt tay.

Các endpoint được phép sử dụng các phương pháp khác để phát hiện và cố gắng khôi phục từ sự can thiệp vào quá trình handshake. Các gói tin không hợp lệ có thể được xác định và loại bỏ bằng các phương pháp khác, nhưng không có phương pháp cụ thể nào được yêu cầu trong tài liệu này.

Chống Khuếch Đại

Kẻ tấn công có thể nhận được một token xác thực địa chỉ (Mục 8) từ máy chủ và sau đó giải phóng địa chỉ IP mà nó đã sử dụng để có được token đó. Tại thời điểm sau, kẻ tấn công có thể khởi tạo kết nối 0-RTT với máy chủ bằng cách giả mạo cùng địa chỉ này, mà bây giờ có thể đang chỉ đến một endpoint khác (nạn nhân). Do đó, kẻ tấn công có khả năng khiến máy chủ gửi lượng dữ liệu tương đương với initial congestion window về phía nạn nhân.

Các server NÊN cung cấp các biện pháp giảm thiểu cho cuộc tấn công này bằng cách giới hạn việc sử dụng và thời gian tồn tại của các token xác thực địa chỉ; xem Mục 8.1.3.

DoS Phía Server

Một endpoint xác nhận các gói tin mà nó chưa nhận được có thể khiến bộ điều khiển tắc nghẽn cho phép gửi với tốc độ vượt quá khả năng hỗ trợ của mạng. Một endpoint CÓ THỂ bỏ qua các số thứ tự gói tin khi gửi gói tin để phát hiện hành vi này. Sau đó endpoint có thể ngay lập tức đóng kết nối với lỗi kết nối loại PROTOCOL_VIOLATION; xem Mục 10.2.

Chấm Dứt Bắt Tay Trên Đường Truyền

Một cuộc tấn công giả mạo yêu cầu xảy ra khi một endpoint khiến peer của nó phát ra một yêu cầu hướng tới nạn nhân, với yêu cầu được kiểm soát bởi endpoint đó. Các cuộc tấn công giả mạo yêu cầu nhằm mục đích cung cấp cho kẻ tấn công quyền truy cập vào các khả năng của peer mà có thể không khả dụng với kẻ tấn công. Đối với một giao thức mạng, cuộc tấn công giả mạo yêu cầu thường được sử dụng để khai thác bất kỳ ủy quyền ngầm nào được nạn nhân cấp cho peer do vị trí của peer trong mạng.

Để request forgery có hiệu quả, kẻ tấn công cần có khả năng ảnh hưởng đến những gói tin mà peer gửi và nơi những gói tin này được gửi đến. Nếu kẻ tấn công có thể nhắm mục tiêu vào một dịch vụ dễ bị tổn thương với một payload được kiểm soát, dịch vụ đó có thể thực hiện các hành động được quy cho peer của kẻ tấn công nhưng lại được quyết định bởi kẻ tấn công.

Ví dụ, các cuộc tấn công cross-site request forgery CSRF trên Web khiến client phát hành các yêu cầu bao gồm authorization cookies COOKIE, cho phép một trang web truy cập thông tin và thực hiện các hành động được thiết kế để chỉ dành riêng cho một trang web khác.

Vì QUIC chạy trên UDP, phương thức tấn công chính cần quan tâm là một kẻ tấn công có thể chọn địa chỉ mà peer của nó gửi các UDP datagram đến và có thể kiểm soát một số nội dung không được bảo vệ của các gói tin đó. Vì phần lớn dữ liệu được gửi bởi các QUIC endpoint đều được bảo vệ, điều này bao gồm việc kiểm soát ciphertext. Một cuộc tấn công được coi là thành công nếu kẻ tấn công có thể khiến một peer gửi UDP datagram đến một host sẽ thực hiện một hành động nào đó dựa trên nội dung trong datagram.

Phần này thảo luận về các cách thức mà QUIC có thể được sử dụng cho các cuộc tấn công giả mạo yêu cầu.

Phần này cũng mô tả các biện pháp đối phó hạn chế có thể được triển khai bởi các endpoint QUIC. Những biện pháp giảm thiểu này có thể được áp dụng đơn phương bởi một triển khai hoặc deployment QUIC, mà không cần các mục tiêu tiềm năng của các cuộc tấn công giả mạo yêu cầu phải hành động. Tuy nhiên, những biện pháp đối phó này có thể không đủ nếu các dịch vụ dựa trên UDP không ủy quyền yêu cầu một cách đúng đắn.

Bởi vì cuộc tấn công migration được mô tả trong Mục 21.5.4 khá mạnh mẽ và không có các biện pháp đối phó đầy đủ, các triển khai máy chủ QUIC nên giả định rằng kẻ tấn công có thể khiến chúng tạo ra các UDP payload tùy ý đến các đích tùy ý. Các máy chủ QUIC KHÔNG NÊN được triển khai trong các mạng không triển khai lọc ingress BCP38 và cũng có các UDP endpoint được bảo mật không đầy đủ.

Mặc dù nói chung không thể đảm bảo rằng các client không được đặt cùng vị trí với các endpoint dễ bị tấn công, phiên bản QUIC này không cho phép server di chuyển, do đó ngăn chặn các cuộc tấn công migration giả mạo đối với client. Bất kỳ phần mở rộng nào trong tương lai cho phép server migration PHẢI cũng định nghĩa các biện pháp đối phó cho các cuộc tấn công giả mạo.

Thương lượng Tham số

QUIC cung cấp một số cơ hội cho kẻ tấn công có thể ảnh hưởng hoặc kiểm soát nơi mà peer của nó gửi các datagram UDP:

  • thiết lập kết nối ban đầu (Mục 7), nơi máy chủ có thể chọn nơi client gửi datagram – ví dụ, bằng cách điền vào các bản ghi DNS;

  • địa chỉ ưu tiên (Mục 9.6), nơi mà máy chủ có thể chọn vị trí mà client gửi datagram;

  • spoofed connection migrations (Mục 9.3.1), trong đó client có thể sử dụng source address spoofing để lựa chọn nơi server gửi các datagram tiếp theo; và

  • các gói tin giả mạo khiến server gửi một gói tin Version Negotiation (Mục 21.5.5).

Trong tất cả các trường hợp, kẻ tấn công có thể khiến peer của mình gửi datagram đến nạn nhân có thể không hiểu QUIC. Tức là, những gói tin này được gửi bởi peer trước khi xác thực địa chỉ; xem Mục 8.

Bên ngoài phần mã hóa của các gói tin, QUIC cung cấp cho endpoint một số tùy chọn để kiểm soát nội dung của các UDP datagram mà peer của nó gửi. Trường Destination Connection ID cung cấp khả năng kiểm soát trực tiếp các byte xuất hiện sớm trong các gói tin được gửi bởi peer; xem Mục 5.1. Trường Token trong các gói tin Initial cung cấp cho server khả năng kiểm soát các byte khác của các gói tin Initial; xem Mục 17.2.2.

Không có biện pháp nào trong phiên bản QUIC này để ngăn chặn việc kiểm soát gián tiếp đối với các phần được mã hóa của gói tin. Cần phải giả định rằng các endpoint có khả năng kiểm soát nội dung của các frame mà một peer gửi, đặc biệt là những frame truyền tải dữ liệu ứng dụng, chẳng hạn như các STREAM frame. Mặc dù điều này phụ thuộc ở một mức độ nào đó vào các chi tiết của giao thức ứng dụng, nhưng một số kiểm soát là có thể trong nhiều bối cảnh sử dụng giao thức. Vì kẻ tấn công có quyền truy cập vào các khóa bảo vệ gói tin, họ có khả năng dự đoán cách một peer sẽ mã hóa các gói tin trong tương lai. Việc kiểm soát thành công nội dung datagram sau đó chỉ yêu cầu kẻ tấn công có thể dự đoán số thứ tự gói tin và vị trí của các frame trong gói tin với một mức độ tin cậy nhất định.

Phần này giả định rằng việc hạn chế kiểm soát nội dung datagram là không khả thi. Trọng tâm của các biện pháp giảm thiểu trong các phần tiếp theo là hạn chế các cách mà các datagram được gửi trước khi xác thực địa chỉ có thể được sử dụng để giả mạo yêu cầu.

Gói tin được Bảo vệ

Kẻ tấn công đóng vai trò như một server có thể chọn địa chỉ IP và port mà nó quảng cáo khả năng sẵn sàng của mình, vì vậy các gói Initial từ client được giả định là có thể sử dụng trong loại tấn công này. Việc xác thực địa chỉ ngầm định trong quá trình handshake đảm bảo rằng – đối với một kết nối mới – một client sẽ không gửi các loại gói khác đến một đích không hiểu QUIC hoặc không sẵn sàng chấp nhận kết nối QUIC.

Bảo vệ gói tin ban đầu (Mục 5.2 của QUIC-TLS) khiến việc server kiểm soát nội dung của các gói tin Initial được gửi bởi client trở nên khó khăn. Một client chọn Destination Connection ID không thể dự đoán sẽ đảm bảo rằng các server không thể kiểm soát bất kỳ phần được mã hóa nào của các gói tin Initial từ client.

Tuy nhiên, trường Token mở cho server kiểm soát và cho phép server sử dụng các client để thực hiện các cuộc tấn công request forgery. Việc sử dụng các token được cung cấp với frame NEW_TOKEN (Mục 8.1.3) cung cấp tùy chọn duy nhất cho request forgery trong quá trình thiết lập kết nối.

Tuy nhiên, các client không bắt buộc phải sử dụng frame NEW_TOKEN. Các cuộc tấn công giả mạo yêu cầu dựa vào trường Token có thể được tránh nếu các client gửi trường Token trống khi địa chỉ server đã thay đổi so với lúc nhận frame NEW_TOKEN.

Các client có thể tránh sử dụng NEW_TOKEN nếu địa chỉ server thay đổi. Tuy nhiên, việc không bao gồm trường Token có thể ảnh hưởng tiêu cực đến hiệu suất. Các server có thể dựa vào NEW_TOKEN để cho phép gửi dữ liệu vượt quá giới hạn ba lần khi gửi dữ liệu; xem Phần 8.1. Đặc biệt, điều này ảnh hưởng đến các trường hợp mà client sử dụng 0-RTT để yêu cầu dữ liệu từ server.

Gửi một gói Retry (Mục 17.2.5) cung cấp cho máy chủ tùy chọn thay đổi trường Token. Sau khi gửi Retry, máy chủ cũng có thể kiểm soát trường Destination Connection ID của các gói Initial tiếp theo từ client. Điều này cũng có thể cho phép kiểm soát gián tiếp nội dung được mã hóa của các gói Initial. Tuy nhiên, việc trao đổi gói Retry xác thực địa chỉ của máy chủ, từ đó ngăn chặn việc sử dụng các gói Initial tiếp theo để giả mạo yêu cầu.

Di chuyển Kết nối

Server có thể chỉ định một địa chỉ ưu tiên, sau đó client sẽ di chuyển đến địa chỉ này sau khi xác nhận quá trình handshake; xem Mục 9.6. Trường Destination Connection ID của các gói tin mà client gửi đến địa chỉ ưu tiên có thể được sử dụng để giả mạo yêu cầu.

Một client KHÔNG ĐƯỢC gửi các frame không phải probing đến địa chỉ ưa thích trước khi xác thực địa chỉ đó; xem Phần 8. Điều này làm giảm đáng kể các tùy chọn mà server có để kiểm soát phần được mã hóa của các datagram.

Tài liệu này không đề xuất bất kỳ biện pháp đối phó bổ sung nào cụ thể cho việc sử dụng các địa chỉ ưa thích và có thể được triển khai bởi các endpoint. Các biện pháp chung được mô tả trong Mục 21.5.6 có thể được sử dụng như một biện pháp giảm thiểu thêm.

Các Cuộc Tấn Công Chủ Động Trên Đường Truyền

Client có thể trình bày một địa chỉ nguồn giả mạo như một phần của quá trình di chuyển kết nối để khiến server gửi datagram đến địa chỉ đó.

Trường Destination Connection ID trong bất kỳ gói tin nào mà server sau đó gửi đến địa chỉ giả mạo này có thể được sử dụng để giả mạo yêu cầu. Client cũng có thể có khả năng ảnh hưởng đến ciphertext.

Một máy chủ chỉ gửi các gói probing (Mục 9.1) đến một địa chỉ trước khi xác thực địa chỉ chỉ cung cấp cho kẻ tấn công khả năng kiểm soát hạn chế đối với phần mã hóa của các datagram. Tuy nhiên, đặc biệt đối với NAT rebinding, điều này có thể ảnh hưởng tiêu cực đến hiệu suất. Nếu máy chủ gửi các frame chứa dữ liệu ứng dụng, kẻ tấn công có thể kiểm soát hầu hết nội dung của các datagram.

Tài liệu này không đưa ra các biện pháp đối phó cụ thể có thể được triển khai bởi các điểm cuối, ngoài các biện pháp chung được mô tả trong Mục 21.5.6. Tuy nhiên, các biện pháp đối phó với việc giả mạo địa chỉ ở cấp mạng – đặc biệt là lọc ingress BCP38 – đặc biệt hiệu quả chống lại các cuộc tấn công sử dụng giả mạo và bắt nguồn từ mạng bên ngoài.

Các Cuộc Tấn Công Chủ Động Ngoài Đường Truyền

Các client có khả năng trình bày địa chỉ nguồn giả mạo trên một packet có thể khiến server gửi một packet Version Negotiation (Mục 17.2.1) tới địa chỉ đó.

Việc không có hạn chế về kích thước đối với các trường connection ID của các gói tin có phiên bản chưa biết làm tăng lượng dữ liệu mà client có thể kiểm soát từ datagram kết quả. Byte đầu tiên của gói tin này không nằm dưới sự kiểm soát của client và bốn byte tiếp theo có giá trị zero, nhưng client có thể kiểm soát tối đa 512 byte bắt đầu từ byte thứ năm.

Không có biện pháp đối phó cụ thể nào được cung cấp cho cuộc tấn công này, mặc dù các biện pháp bảo vệ tổng quát (Mục 21.5.6) có thể áp dụng. Trong trường hợp này, ingress filtering BCP38 cũng có hiệu quả.

Các Cuộc Tấn Công Chủ Động Trên Đường Truyền Có Hạn Chế

Biện pháp phòng thủ hiệu quả nhất chống lại các cuộc tấn công giả mạo yêu cầu là sửa đổi các dịch vụ dễ bị tấn công để sử dụng xác thực mạnh. Tuy nhiên, điều này không phải lúc nào cũng nằm trong tầm kiểm soát của việc triển khai QUIC. Phần này nêu ra một số bước khác mà các endpoint QUIC có thể thực hiện một cách đơn phương. Tất cả các bước bổ sung này đều là tùy chọn vì, tùy thuộc vào hoàn cảnh, chúng có thể can thiệp hoặc ngăn cản các mục đích sử dụng hợp pháp.

Các dịch vụ được cung cấp qua giao diện loopback thường thiếu xác thực phù hợp. Các endpoint CÓ THỂ ngăn chặn các nỗ lực kết nối hoặc di chuyển đến địa chỉ loopback. Các endpoint KHÔNG NÊN cho phép kết nối hoặc di chuyển đến địa chỉ loopback nếu cùng một dịch vụ trước đó đã có sẵn tại một giao diện khác hoặc nếu địa chỉ được cung cấp bởi một dịch vụ tại địa chỉ không phải loopback. Các endpoint phụ thuộc vào những khả năng này có thể cung cấp tùy chọn để vô hiệu hóa các biện pháp bảo vệ này.

Tương tự, các endpoint có thể coi việc thay đổi địa chỉ thành địa chỉ link-local RFC4291 hoặc địa chỉ trong dải sử dụng riêng RFC1918 từ một địa chỉ global, unique-local RFC4193, hoặc địa chỉ không riêng tư là một nỗ lực giả mạo yêu cầu tiềm tàng. Các endpoint có thể từ chối sử dụng hoàn toàn những địa chỉ này, nhưng điều đó mang theo rủi ro đáng kể là can thiệp vào các mục đích sử dụng hợp pháp. Các endpoint KHÔNG NÊN từ chối sử dụng một địa chỉ trừ khi chúng có kiến thức cụ thể về mạng cho thấy rằng việc gửi datagram đến các địa chỉ chưa được xác thực trong một dải nhất định là không an toàn.

Các endpoint CÓ THỂ chọn giảm thiểu rủi ro giả mạo yêu cầu bằng cách không bao gồm các giá trị từ các frame NEW_TOKEN trong các packet Initial hoặc chỉ gửi các frame thăm dò trong các packet trước khi hoàn thành xác thực địa chỉ. Lưu ý rằng điều này không ngăn chặn kẻ tấn công sử dụng trường Destination Connection ID để thực hiện tấn công.

Các endpoint không được mong đợi có thông tin cụ thể về vị trí của các server có thể là mục tiêu dễ bị tấn công của một cuộc tấn công request forgery. Tuy nhiên, theo thời gian có thể xác định được các cổng UDP cụ thể là mục tiêu phổ biến của các cuộc tấn công hoặc các mẫu cụ thể trong datagram được sử dụng cho các cuộc tấn công. Các endpoint CÓ THỂ chọn tránh gửi datagram đến các cổng này hoặc không gửi datagram khớp với các mẫu này trước khi xác thực địa chỉ đích. Các endpoint CÓ THỂ loại bỏ các connection ID chứa các mẫu được biết là có vấn đề mà không sử dụng chúng.

Lưu ý: Việc chỉnh sửa các endpoint để áp dụng các biện pháp bảo vệ này sẽ hiệu quả hơn so với việc triển khai các biện pháp bảo vệ dựa trên mạng, vì các endpoint không cần thực hiện bất kỳ xử lý bổ sung nào khi gửi đến một địa chỉ đã được xác thực.

Từ chối Dịch vụ Handshake

Các cuộc tấn công thường được biết đến với tên Slowloris SLOWLORIS cố gắng duy trì nhiều kết nối đến endpoint đích và giữ chúng mở càng lâu càng tốt. Những cuộc tấn công này có thể được thực hiện chống lại một QUIC endpoint bằng cách tạo ra lượng hoạt động tối thiểu cần thiết để tránh bị đóng do không hoạt động. Điều này có thể bao gồm việc gửi một lượng nhỏ dữ liệu, dần dần mở các cửa sổ điều khiển luồng để kiểm soát tốc độ gửi, hoặc tạo ra các khung ACK mô phỏng tỷ lệ mất mát cao.

Các triển khai QUIC NÊN cung cấp các biện pháp giảm thiểu cho các cuộc tấn công Slowloris, chẳng hạn như tăng số lượng client tối đa mà server sẽ cho phép, giới hạn số lượng kết nối mà một địa chỉ IP được phép thực hiện, áp đặt các hạn chế về tốc độ truyền tải tối thiểu mà một kết nối được phép có, và hạn chế thời gian mà một endpoint được phép duy trì kết nối.

Tấn Công Khuếch Đại

Một người gửi thù địch có thể cố ý không gửi các phần của dữ liệu luồng, khiến bên nhận phải cam kết tài nguyên cho dữ liệu chưa được gửi. Điều này có thể gây ra việc cam kết bộ nhớ buffer nhận không tương xứng và/hoặc tạo ra một cấu trúc dữ liệu lớn và không hiệu quả tại bên nhận.

Một bên nhận thù địch có thể cố tình không xác nhận các gói tin chứa dữ liệu luồng nhằm buộc bên gửi phải lưu trữ dữ liệu luồng chưa được xác nhận để truyền lại.

Cuộc tấn công vào các receiver được giảm thiểu nếu các cửa sổ flow control tương ứng với bộ nhớ khả dụng. Tuy nhiên, một số receiver sẽ overcommit bộ nhớ và quảng cáo các offset flow control tổng hợp vượt quá bộ nhớ thực tế khả dụng. Chiến lược overcommitment có thể dẫn đến hiệu suất tốt hơn khi các endpoint hoạt động đúng cách, nhưng khiến các endpoint dễ bị tổn thương trước cuộc tấn công phân mảnh luồng.

Các triển khai QUIC NÊN cung cấp các biện pháp giảm thiểu cho các cuộc tấn công phân mảnh luồng. Các biện pháp giảm thiểu có thể bao gồm tránh cam kết quá mức bộ nhớ, giới hạn kích thước của các cấu trúc dữ liệu theo dõi, trì hoãn việc tái lắp ráp các khung STREAM, triển khai các phương pháp heuristic dựa trên tuổi và thời gian của các lỗ hổng tái lắp ráp, hoặc một số kết hợp của những biện pháp này.

Tấn công ACK lạc quan

Một endpoint thù địch có thể mở một số lượng lớn các stream, làm cạn kiệt trạng thái trên một endpoint. Endpoint thù địch có thể lặp lại quá trình này trên một số lượng lớn các kết nối, theo cách tương tự như các cuộc tấn công SYN flooding trong TCP.

Thông thường, các client sẽ mở các luồng tuần tự, như được giải thích trong Mục 2.1. Tuy nhiên, khi một số luồng được khởi tạo trong khoảng thời gian ngắn, việc mất mát hoặc sắp xếp lại có thể khiến các khung STREAM mở luồng được nhận không theo thứ tự. Khi nhận được một stream ID có số cao hơn, bộ nhận được yêu cầu phải mở tất cả các luồng trung gian cùng loại; xem Mục 3.2. Do đó, trên một kết nối mới, việc mở stream 4000000 sẽ mở 1 triệu và 1 luồng hai chiều được khởi tạo bởi client.

Số lượng stream hoạt động được giới hạn bởi các tham số transport initial_max_streams_bidi và initial_max_streams_uni được cập nhật bởi bất kỳ frame MAX_STREAMS nào nhận được, như đã giải thích trong Phần 4.6. Nếu được chọn một cách thận trọng, những giới hạn này sẽ giảm thiểu tác động của cuộc tấn công stream commitment. Tuy nhiên, việc đặt giới hạn quá thấp có thể ảnh hưởng đến hiệu suất khi các ứng dụng mong muốn mở một số lượng lớn stream.

Các Cuộc Tấn Công Giả Mạo Yêu Cầu

QUIC và TLS đều chứa các frame hoặc message có công dụng hợp lệ trong một số ngữ cảnh, nhưng các frame hoặc message này có thể bị lạm dụng để khiến peer phải tiêu tốn tài nguyên xử lý mà không có tác động có thể quan sát được nào đến trạng thái của kết nối.

Các message cũng có thể được sử dụng để thay đổi và hoàn nguyên trạng thái theo những cách nhỏ hoặc không đáng kể, chẳng hạn như bằng cách gửi các gia số nhỏ đến các giới hạn kiểm soát luồng.

Nếu chi phí xử lý lớn một cách không tương xứng so với mức tiêu thụ băng thông hoặc tác động lên trạng thái, thì điều này có thể cho phép một peer độc hại làm cạn kiệt năng lực xử lý.

Mặc dù tất cả các thông điệp đều có những mục đích sử dụng hợp lệ, các implementation NÊN theo dõi chi phí xử lý so với tiến độ và coi số lượng quá mức của bất kỳ gói tin không có tác dụng nào như một dấu hiệu của cuộc tấn công. Các endpoint CÓ THỂ phản hồi tình trạng này bằng lỗi kết nối hoặc bằng cách loại bỏ các gói tin.

Tùy Chọn Điều Khiển cho Endpoints

Kẻ tấn công trên đường truyền có thể thao túng giá trị của các trường ECN trong header IP để ảnh hưởng đến tốc độ của bên gửi. RFC3168 thảo luận chi tiết hơn về các thao túng và tác động của chúng.

Một kẻ tấn công on-path có hạn chế có thể sao chép và gửi các gói tin với trường ECN đã được sửa đổi để ảnh hưởng đến tốc độ của người gửi. Nếu các gói tin trùng lặp bị loại bỏ bởi người nhận, kẻ tấn công sẽ cần phải đua với gói tin trùng lặp chống lại gói tin gốc để thành công trong cuộc tấn công này. Do đó, các endpoint QUIC bỏ qua trường ECN trong gói tin IP trừ khi ít nhất một gói tin QUIC trong gói tin IP đó được xử lý thành công; xem Mục 13.4.

Giả mạo Yêu cầu với Gói Tin Khởi tạo từ Client

Stateless reset tạo ra một cuộc tấn công từ chối dịch vụ có thể xảy ra tương tự như TCP reset injection. Cuộc tấn công này có thể thực hiện được nếu kẻ tấn công có thể khiến một stateless reset token được tạo ra cho một kết nối với connection ID đã được chọn. Kẻ tấn công có thể khiến token này được tạo ra có thể reset một kết nối đang hoạt động với cùng connection ID.

Nếu một gói tin có thể được định tuyến đến các instance khác nhau chia sẻ một static key – ví dụ, bằng cách thay đổi địa chỉ IP hoặc port – thì kẻ tấn công có thể khiến server gửi một stateless reset. Để bảo vệ chống lại kiểu tấn công từ chối dịch vụ này, các endpoint chia sẻ static key cho stateless reset (xem Mục 10.3.2) PHẢI được sắp xếp sao cho các gói tin với một connection ID nhất định luôn đến một instance có connection state, trừ khi connection đó không còn hoạt động.

Nói chung hơn, các server KHÔNG ĐƯỢC tạo ra stateless reset nếu một kết nối với connection ID tương ứng có thể đang hoạt động trên bất kỳ endpoint nào sử dụng cùng static key.

Trong trường hợp của một cluster sử dụng cân bằng tải động, có thể xảy ra thay đổi trong cấu hình load-balancer trong khi một instance đang hoạt động vẫn giữ trạng thái kết nối. Ngay cả khi một instance giữ lại trạng thái kết nối, việc thay đổi định tuyến và kết quả là stateless reset sẽ dẫn đến việc kết nối bị chấm dứt. Nếu không có khả năng packet được định tuyến đến instance đúng, thì tốt hơn là gửi một stateless reset thay vì chờ kết nối hết thời gian chờ. Tuy nhiên, điều này chỉ chấp nhận được nếu việc định tuyến không thể bị ảnh hưởng bởi kẻ tấn công.

Giả mạo Yêu cầu với Địa chỉ Ưu tiên

Tài liệu này định nghĩa các gói tin QUIC Version Negotiation (Mục 6), có thể được sử dụng để thương lượng phiên bản QUIC được sử dụng giữa hai điểm cuối. Tuy nhiên, tài liệu này không chỉ định cách thực hiện quá trình thương lượng này giữa phiên bản hiện tại và các phiên bản tương lai tiếp theo. Đặc biệt, các gói tin Version Negotiation không chứa bất kỳ cơ chế nào để ngăn chặn các cuộc tấn công hạ cấp phiên bản. Các phiên bản tương lai của QUIC sử dụng các gói tin Version Negotiation PHẢI định nghĩa một cơ chế mạnh mẽ chống lại các cuộc tấn công hạ cấp phiên bản.

Giả mạo Yêu cầu với Migration Giả mạo

Các triển khai nên hạn chế khả năng của kẻ tấn công nhắm mục tiêu kết nối mới đến một instance máy chủ cụ thể. Lý tưởng nhất, các quyết định định tuyến được thực hiện độc lập với các giá trị do client lựa chọn, bao gồm cả địa chỉ. Khi một instance được chọn, một connection ID có thể được chọn để các gói tin sau đó được định tuyến đến cùng instance đó.

Giả mạo Yêu cầu với Thương lượng Phiên bản

Độ dài của các gói QUIC có thể tiết lộ thông tin về độ dài nội dung của những gói đó. Khung PADDING được cung cấp để các endpoint có một số khả năng che giấu độ dài nội dung gói; xem Mục 19.1.

Việc đánh bại phân tích lưu lượng là một thách thức và là chủ đề của các nghiên cứu tích cực. Độ dài không phải là cách duy nhất mà thông tin có thể bị rò rỉ. Các điểm cuối cũng có thể tiết lộ thông tin nhạy cảm thông qua các kênh phụ khác, chẳng hạn như thời gian của các gói tin.

Relay Security

Sau đây là phân tích về Relay Request, Relay Response, Relay Intro, và Hole Punch trong SSU1.

Ràng buộc: Điều quan trọng là các Relay phải nhanh. Các chuyến đi khứ hồi nên được giảm thiểu. Băng thông và CPU không quan trọng bằng.

SSU 1: Alice đầu tiên kết nối với introducer Bob, người sẽ chuyển tiếp yêu cầu đến Charlie (đang bị chặn bởi tường lửa). Sau khi hole punch, phiên được thiết lập giữa Alice và Charlie như trong một thiết lập trực tiếp.

Alice                         Bob                  Charlie
1. RelayRequest ---------------------->
2.      <-------------- RelayResponse    RelayIntro ----------->
3.      <-------------------------------------------- HolePunch
4. SessionRequest -------------------------------------------->
5.      <-------------------------------------------- SessionCreated
6. SessionConfirmed ------------------------------------------>

Xác thực: Relay Request và Relay Response không được xác thực an toàn, vì Alice và Bob thường không có phiên làm việc hiện có; những thông điệp này sử dụng các intro keys đã được công bố. Relay Request/Response trong phiên được cho phép và được ưu tiên nếu một phiên đã tồn tại.

Relay Intro từ Bob đến Charlie được yêu cầu phải trong một phiên hiện có, do đó được giả định là an toàn.

Bob có thể giả mạo Relay Intros hoặc thay đổi IP/port từ Relay Request. Không có cơ chế nào để liên kết mật mã học các yêu cầu với intros hoặc ngăn chặn hoặc phát hiện những Bob độc hại.

Hash router của Bob hiện tại không được công bố trong Router Info của Charlie, vì vậy điều này phải được thêm vào nếu chúng ta muốn các tin nhắn Alice-Bob được xác thực. Ngoài ra, các tham số SSU2 khác sẽ phải được công bố trong Router Info của Charlie, hoặc Alice sẽ phải tra cứu Router Info của Bob trong cơ sở dữ liệu mạng, làm tăng thêm độ trễ. Xác thực sẽ thêm một round-trip giữa Alice và Bob.

Bằng cách chuyển tiếp router hash của Alice cho Charlie, Charlie có thể dễ dàng xác định liệu anh ta có muốn nhận kết nối từ Alice hay không, bằng cách kiểm tra danh sách cấm cục bộ. Không có cơ chế nào để Charlie từ chối relay bằng cách gửi thông báo từ chối qua Bob đến Alice. Không có cơ chế nào để Charlie chấp nhận relay bằng cách gửi thông báo chấp nhận qua Bob đến Alice. Alice phải đợi HolePunch, hoặc đơn giản là gửi SessionRequest một cách mù quáng. HolePunch có thể đến từ một cổng khác với những gì Alice mong đợi, do NAT, điều này có thể khiến việc nhận ra HolePunch đến từ router nào trở nên khó khăn hơn.

Alice có thể gửi toàn bộ Router Info của mình trong Relay Request tới Bob, và chuyển tiếp tới Charlie trong Relay Intro.

Relay Request không chứa timestamp, do đó không có khả năng ngăn chặn replay. IP nguồn có thể bị giả mạo, khiến Charlie gửi Hole Punch đến bất kỳ IP/port nào. Relay Request không được ký, và ngay cả khi được ký và có timestamp, Charlie không có đầy đủ Router Identity để có thể xác minh chữ ký.

Giao thức định nghĩa một trường challenge có độ dài biến đổi từ 0-255 byte. Challenge trong Relay Request được chuyển đến Charlie trong Relay Intro. Tuy nhiên, giao thức không chỉ định cách tạo, sử dụng, hoặc xác minh challenge, và nó chưa được triển khai. Nếu HolePunch chứa challenge, Alice sẽ có thể dễ dàng liên kết HolePunch với Charlie.

Nonce bốn byte có thể cần được thay thế hoặc bổ sung bằng connection ID tám byte.

Thông điệp Hole Punch rỗng là duy nhất và có thể được các observer trên đường truyền sử dụng để xác định giao thức, điều này cần được thay đổi.

Thảo luận bổ sung về DPI

Sau đây là phân tích về Peer Test trong SSU1.

Ràng buộc: Việc Peer Tests có nhanh hay không, sử dụng băng thông thấp hay không, hoặc tốn ít CPU hay không đều không đặc biệt quan trọng, ngoại trừ có thể trong quá trình khởi động router, khi chúng ta mong muốn router phát hiện khả năng kết nối của nó một cách khá nhanh chóng.

SSU 1:

Alice                     Bob                  Charlie
1. PeerTest ------------------->
2.                          PeerTest-------------------->
3.                             <-------------------PeerTest
4.      <-------------------PeerTest

5.      <------------------------------------------PeerTest
6. PeerTest------------------------------------------>
7.      <------------------------------------------PeerTest

Vì đặc tả SSU1 khó theo dõi, chúng tôi ghi lại nội dung thông điệp bên dưới.

MessagePathAlice IP incl?Intro Key
1A->B sessionnoAlice
2B->C sessionyesAlice
3C->B sessionyesCharlie
4B->A sessionyesCharlie
5C->AyesCharlie
6A->CnoAlice
7C->AyesCharlie
Xác thực: Alice sẽ luôn chọn một Bob có phiên làm việc hiện có. Bob sẽ từ chối các PeerTest từ những peer không có phiên làm việc đã thiết lập. Thông điệp 1 được gửi trong phiên làm việc. Do đó, thông điệp 1 là an toàn và được xác thực.

Bob chọn một Charlie mà anh ta đã có phiên kết nối. Thông điệp 2 và 3 được gửi trong phiên. Do đó, thông điệp 2 và 3 được bảo mật và xác thực.

Message 4 nên được gửi trong phiên (in-session); tuy nhiên, đặc tả SSU 1 trước đây đã nói rằng nó được gửi với intro key đã công bố của Alice, có nghĩa là không trong phiên. Trước phiên bản 0.9.52, Java I2P đã gửi với intro key. Kể từ phiên bản 0.9.52, đặc tả quy định rằng session key nên được sử dụng, và Java I2P gửi message trong phiên kể từ phiên bản 0.9.52.

Alice không được có phiên kết nối hiện tại với Charlie để bài kiểm tra có thể tiến hành; Alice sẽ hủy bỏ bài kiểm tra nếu Bob chọn một Charlie đã có phiên kết nối với Alice. Do đó, các thông điệp 5-7 không được bảo mật và xác thực.

Tất cả các thông điệp Peer Test đều chứa một nonce 4-byte được Alice lựa chọn. Nonce này không được sử dụng cho mục đích mã hóa.

Các cuộc tấn công có thể xảy ra với tin nhắn 5-7: cần được nghiên cứu.

Hash router của Alice không được Charlie biết đến. Hash router của Charlie không được Alice biết đến. Những thông tin này phải được thêm vào giao thức nếu chúng ta muốn các thông điệp Alice-Charlie được xác thực. Ngoài ra, các tham số SSU2 khác sẽ phải được cung cấp trong các thông điệp Peer Test, hoặc Charlie sẽ phải tra cứu Router Info của Alice trong cơ sở dữ liệu mạng, gây thêm độ trễ. Việc xác thực sẽ thêm một round-trip giữa Charlie và Alice.

Bằng cách chuyển tiếp router hash của Alice cho Charlie, Charlie có thể dễ dàng xác định xem anh ta có muốn tham gia vào Peer Test với Alice hay không, bằng cách kiểm tra danh sách cấm cục bộ.

Nonce bốn byte có thể cần được thay thế hoặc bổ sung bằng connection ID tám byte.

Relay and Peer Test Design Goals

Relay và Peer Test có cấu trúc tương tự. Trong cả hai trường hợp, Alice yêu cầu Bob chuyển tiếp một yêu cầu dịch vụ đến Charlie, và Charlie sau đó thực hiện yêu cầu đó.

Các vấn đề hiện tại của SSU1 Peer Test:

  • Peer Test không có biện pháp bảo vệ nào chống lại Bob độc hại
  • Peer Test không có cách nào để Bob hoặc Charlie từ chối một yêu cầu
  • Peer Test không có cách nào để Alice biết danh tính của Charlie hoặc để Alice từ chối một Charlie
  • Peer Test không có cách nào để Charlie biết danh tính của Alice hoặc để Charlie từ chối một Alice
  • Peer Test có sơ đồ truyền lại tùy ý riêng của nó
  • Peer Test yêu cầu một máy trạng thái phức tạp để biết tin nhắn nào dành cho trạng thái nào
  • Mà không biết rằng Charlie đã từ chối cô ấy, Alice sẽ coi bài kiểm tra là thất bại.

Các vấn đề hiện tại với SSU1 Relay:

Hầu hết các vấn đề Peer Test được liệt kê ở trên cũng áp dụng cho Peer Test.

Chúng tôi có các mục tiêu sau đây trong việc cải thiện bảo mật của Relay và Peer Test:

  • Charlie nên công bố đủ thông tin về các introducer (Bob) của mình trong netDb để Alice có thể xác thực thông tin nếu cần thiết. Ví dụ, việc công bố router hash cho mỗi introducer sẽ cho phép Alice, nếu thời gian cho phép, lấy thông tin router từ netDb.

  • Bảo vệ chống lại việc giả mạo địa chỉ hoặc các mối đe dọa trên đường truyền có thể giả mạo, thay đổi, làm giả, hoặc phát lại các yêu cầu từ Alice đến Bob. Bob phải đảm bảo rằng Alice là một router I2P thực sự và rằng yêu cầu cũng như địa chỉ kiểm tra được trình bày là hợp lệ.

  • Bảo vệ chống lại các Bob độc hại có thể giả mạo, thay đổi, làm giả hoặc phát lại các yêu cầu được chuyển tiếp đến Charlie. Charlie phải đảm bảo rằng cả Alice và Bob đều là các router I2P thực sự và rằng yêu cầu và địa chỉ kiểm tra được trình bày là hợp lệ.

  • Bob phải nhận đủ thông tin từ Alice để có thể xác thực yêu cầu và sau đó chấp nhận hoặc từ chối nó. Bob phải có cơ chế để gửi lại sự chấp nhận hoặc từ chối cho Alice. Bob không bao giờ được yêu cầu thực hiện hành động được yêu cầu.

  • Charlie phải nhận được đủ thông tin từ Bob để có thể xác thực yêu cầu và sau đó chấp nhận hoặc từ chối nó. Charlie phải có cơ chế để gửi sự chấp nhận hoặc từ chối trở lại cho Bob, để chuyển tiếp tới Alice. Charlie không bao giờ được yêu cầu phải thực hiện hành động được yêu cầu.

  • Alice phải có khả năng xác thực rằng phản hồi được chuyển tiếp qua Bob thực sự có nguồn gốc từ Charlie.

  • Alice và Charlie phải có khả năng xác thực rằng các tin nhắn trực tiếp tiếp theo của họ (không được chuyển tiếp qua Bob) đến từ nguồn được mong đợi và là các I2P router thực tế.

Các cơ chế sau đây có thể hỗ trợ trong việc đạt được những mục tiêu này:

  • Dấu thời gian

  • Chữ ký sử dụng khóa ký của router

  • Sử dụng dữ liệu thử thách được bao gồm trong yêu cầu

  • Mã hóa sử dụng khóa mã hóa của router

  • Gửi các router hash, Router Identity, hoặc Router Info, không chỉ là IP và port.

  • Xác thực thông tin router bằng cách truy vấn cơ sở dữ liệu mạng

  • Kiểm tra thông tin router, IP và cổng với danh sách cấm

  • Giới hạn tốc độ

  • Yêu cầu thiết lập phiên

Các cơ chế có thể này có thể làm tăng thời gian xử lý và độ trễ của các chức năng Relay hoặc Peer Test. Tất cả các tác động phải được đánh giá.

Relay giữa các phiên bản và kiểm tra peer cũng nên được hỗ trợ nếu có thể. Điều này sẽ tạo điều kiện cho việc chuyển đổi từ từ từ SSU 1 sang SSU 2. Các kết hợp phiên bản có thể là:

Alice/BobBob/CharlieAlice/CharlieSupported
111SSU 1
112no, use 1/1/1
121Relay: yes? Peer Test: no
122no, use 1/2/1
211Relay: yes? Peer Test: no
212Relay: yes? Peer Test: no
221no, use 2/2/2
222yes

Mục Tiêu Bảo Mật

Summary

Chúng tôi dựa vào một số giao thức hiện có, cả trong I2P và các tiêu chuẩn bên ngoài, để lấy cảm hứng, hướng dẫn và tái sử dụng mã nguồn:

  • Các mô hình đe dọa: Từ NTCP2 NTCP2, với các đe dọa bổ sung đáng kể liên quan đến truyền tải UDP như được phân tích bởi QUIC RFC 9000 RFC 9001.

  • Lựa chọn mã hóa: Từ NTCP2.

  • Handshake: Noise XK từ NTCP2NOISE. Các đơn giản hóa đáng kể cho NTCP2 có thể thực hiện được do tính đóng gói (ranh giới thông điệp vốn có) được cung cấp bởi UDP.

  • Làm rối khóa tạm thời handshake: Điều chỉnh từ NTCP2 nhưng sử dụng ChaCha20 từ ECIES thay vì AES.

  • Header gói tin: Được điều chỉnh từ WireGuard WireGuard và QUIC RFC 9000 RFC 9001.

  • Che giấu header gói tin: Được điều chỉnh từ NTCP2 nhưng sử dụng ChaCha20 từ ECIES thay vì AES.

  • Bảo vệ header gói tin: Được điều chỉnh từ QUIC RFC 9001Nonces

  • Headers được sử dụng làm AEAD associated data như trong ECIES.

  • Đánh số gói tin: Được điều chỉnh từ WireGuard WireGuard và QUIC RFC 9000 RFC 9001.

  • Tin nhắn: Được chuyển thể từ SSU

  • I2NP Fragmentation: Chuyển đổi từ SSU

  • Relay và Peer Testing: Chuyển thể từ SSU

  • Chữ ký của dữ liệu Relay và Peer Test: Từ đặc tả cấu trúc chung Common

  • Định dạng khối: Từ NTCP2ECIES.

  • Padding và options: Từ NTCP2ECIES.

  • Acks, nacks: Được điều chỉnh từ QUIC RFC 9000.

  • Điều khiển luồng: TBD

Không có các primitive mã hóa mới nào chưa từng được sử dụng trong I2P trước đây.

Xác Thực Địa Chỉ

Giống như các giao thức vận chuyển I2P khác NTCP, NTCP2, và SSU 1, giao thức vận chuyển này không phải là một phương tiện đa mục đích để truyền tải luồng byte theo thứ tự. Nó được thiết kế để vận chuyển các thông điệp I2NP. Không có khái niệm trừu tượng “luồng” nào được cung cấp.

Ngoài ra, giống như SSU, nó chứa các tính năng bổ sung cho việc vượt qua NAT được hỗ trợ bởi peer và kiểm tra khả năng tiếp cận (các kết nối đến).

Đối với SSU 1, nó KHÔNG cung cấp việc phân phối các thông điệp I2NP theo thứ tự. Nó cũng không cung cấp việc phân phối được đảm bảo các thông điệp I2NP. Vì hiệu quả, hoặc do việc phân phối các gói dữ liệu UDP không theo thứ tự hoặc mất các gói dữ liệu đó, các thông điệp I2NP có thể được phân phối đến đầu cuối xa không theo thứ tự, hoặc có thể không được phân phối chút nào. Một thông điệp I2NP có thể được truyền lại nhiều lần nếu cần thiết, nhưng việc phân phối có thể cuối cùng thất bại mà không gây ra việc ngắt kết nối toàn bộ. Ngoài ra, các thông điệp I2NP mới có thể tiếp tục được gửi ngay cả khi việc truyền lại (khôi phục mất mát) đang xảy ra cho các thông điệp I2NP khác.

Giao thức này KHÔNG hoàn toàn ngăn chặn việc gửi trùng lặp các thông điệp I2NP. Router nên thực thi thời hạn hết hạn I2NP và sử dụng bộ lọc Bloom hoặc cơ chế khác dựa trên ID thông điệp I2NP. Xem phần I2NP Message Duplication bên dưới.

Noise Protocol Framework

Đề xuất này cung cấp các yêu cầu dựa trên Noise Protocol Framework NOISE (Revision 33, 2017-10-04). Noise có các đặc tính tương tự như giao thức Station-To-Station (STS), là cơ sở cho giao thức SSU. Trong thuật ngữ của Noise, Alice là bên khởi tạo và Bob là bên phản hồi.

SSU2 dựa trên giao thức Noise Noise_XK_25519_ChaChaPoly_SHA256. (Định danh thực tế cho hàm dẫn xuất khóa ban đầu là “Noise_XKchaobfse+hs1+hs2+hs3_25519_ChaChaPoly_SHA256” để chỉ ra các mở rộng I2P - xem phần KDF 1 bên dưới)

LƯU Ý: Định danh này khác với định danh được sử dụng cho NTCP2, bởi vì cả ba thông điệp bắt tay đều sử dụng header làm dữ liệu liên kết.

Giao thức Noise này sử dụng các thành phần cơ bản sau:

  • Handshake Pattern: XK Alice truyền khóa của mình cho Bob (X) Alice đã biết khóa tĩnh của Bob (K)

  • DH Function: X25519 X25519 DH với độ dài khóa 32 bytes như được quy định trong RFC 7748.

  • Hàm Cipher: ChaChaPoly AEAD_CHACHA20_POLY1305 như được quy định trong RFC 7539 mục 2.8. Nonce 12 byte, với 4 byte đầu được đặt thành zero.

  • Hash Function: SHA256 Hash function chuẩn 32-byte, đã được sử dụng rộng rãi trong I2P.

Additions to the Framework

Đề xuất này định nghĩa các cải tiến sau đây cho Noise_XK_25519_ChaChaPoly_SHA256. Những cải tiến này thường tuân theo các hướng dẫn trong NOISE mục 13.

  1. Các thông điệp handshake (Session Request, Created, Confirmed) bao gồm một header 16 hoặc 32 byte.

  2. Các header cho các thông điệp handshake (Session Request, Created, Confirmed) được sử dụng làm đầu vào cho mixHash() trước khi mã hóa/giải mã để liên kết các header với thông điệp.

  3. Headers được mã hóa và bảo vệ.

  4. Các khóa tạm thời dạng văn bản rõ được làm xáo trộn bằng mã hóa ChaCha20 sử dụng khóa và IV đã biết. Điều này nhanh hơn so với elligator2.

  5. Định dạng payload được định nghĩa cho các thông điệp 1, 2, và giai đoạn dữ liệu. Tất nhiên, điều này không được định nghĩa trong Noise.

Giai đoạn dữ liệu sử dụng mã hóa tương tự nhưng không tương thích với giai đoạn dữ liệu Noise.

Processing overhead estimate

Sẽ được bổ sung

Definitions

Chúng tôi định nghĩa các hàm sau tương ứng với các khối xây dựng mật mã được sử dụng.

ZEROLEN

zero-length byte array

H(p, d)

SHA-256 hash function that takes a personalization string p and data d, and
produces an output of length 32 bytes.
As defined in [NOISE](https://noiseprotocol.org/noise.html).
|| below means append.

Use SHA-256 as follows::

    H(p, d) := SHA-256(p || d)

MixHash(d)

SHA-256 hash function that takes a previous hash h and new data d,
and produces an output of length 32 bytes.
|| below means append.

Use SHA-256 as follows::

    MixHash(d) := h = SHA-256(h || d)

STREAM

The ChaCha20/Poly1305 AEAD as specified in [RFC 7539](https://tools.ietf.org/html/rfc7539).
S_KEY_LEN = 32 and S_IV_LEN = 12.

ENCRYPT(k, n, plaintext, ad)
    Encrypts plaintext using the cipher key k, and nonce n which MUST be unique for
    the key k.
    Associated data ad is optional.
    Returns a ciphertext that is the size of the plaintext + 16 bytes for the HMAC.

    The entire ciphertext must be indistinguishable from random if the key is secret.

DECRYPT(k, n, ciphertext, ad)
    Decrypts ciphertext using the cipher key k, and nonce n.
    Associated data ad is optional.
    Returns the plaintext.

DH

X25519 public key agreement system. Private keys of 32 bytes, public keys of 32
bytes, produces outputs of 32 bytes. It has the following
functions:

GENERATE_PRIVATE()
    Generates a new private key.

DERIVE_PUBLIC(privkey)
    Returns the public key corresponding to the given private key.

DH(privkey, pubkey)
    Generates a shared secret from the given private and public keys.

HKDF(salt, ikm, info, n)

A cryptographic key derivation function which takes some input key material ikm (which
should have good entropy but is not required to be a uniformly random string), a salt
of length 32 bytes, and a context-specific 'info' value, and produces an output
of n bytes suitable for use as key material.

Use HKDF as specified in [RFC 5869](https://tools.ietf.org/html/rfc5869), using the HMAC hash function SHA-256
as specified in [RFC 2104](https://tools.ietf.org/html/rfc2104). This means that SALT_LEN is 32 bytes max.

MixKey(d)

Use HKDF() with a previous chainKey and new data d, and
sets the new chainKey and k.
As defined in [NOISE](https://noiseprotocol.org/noise.html).

Use HKDF as follows::

    MixKey(d) := output = HKDF(chainKey, d, "", 64)
                 chainKey = output[0:31]
                 k = output[32:63]

Messages

Mỗi datagram UDP chứa chính xác một message. Độ dài của datagram (sau header IP và UDP) chính là độ dài của message. Padding, nếu có, được chứa trong một khối padding bên trong message. Trong tài liệu này, chúng tôi sử dụng các thuật ngữ “datagram” và “packet” phần lớn có thể thay thế cho nhau. Mỗi datagram (hoặc packet) chứa một message duy nhất (khác với QUIC, nơi một datagram có thể chứa nhiều packet QUIC). “Packet header” là phần sau header IP/UDP.

Ngoại lệ: Thông điệp Session Confirmed là duy nhất ở chỗ nó có thể được phân mảnh qua nhiều gói tin. Xem phần Session Confirmed Fragmentation bên dưới để biết thêm thông tin.

Tất cả thông điệp SSU2 có độ dài ít nhất 40 byte. Bất kỳ thông điệp nào có độ dài từ 1-39 byte đều không hợp lệ. Tất cả thông điệp SSU2 có độ dài nhỏ hơn hoặc bằng 1472 (IPv4) hoặc 1452 (IPv6) byte. Định dạng thông điệp dựa trên thông điệp Noise, với các sửa đổi cho việc đóng khung và tính không phân biệt được. Các triển khai sử dụng thư viện Noise tiêu chuẩn phải tiền xử lý các thông điệp nhận được thành định dạng thông điệp Noise tiêu chuẩn. Tất cả các trường được mã hóa đều là bản mã AEAD.

Các thông điệp sau được định nghĩa:

TypeMessageHeader LengthHeader Encr. Length
0SessionRequest3264
1SessionCreated3264
2SessionConfirmed1616
6Data1616
7PeerTest3232
9Retry3232
10Token Request3232
11HolePunch3232

Session Establishment

Trình tự thiết lập chuẩn, khi Alice có một token hợp lệ đã nhận trước đó từ Bob, như sau:

Alice                           Bob

SessionRequest ------------------->
<------------------- SessionCreated
SessionConfirmed ----------------->

Khi Alice không có token hợp lệ, chuỗi thiết lập kết nối diễn ra như sau:

Alice                           Bob

TokenRequest --------------------->
<---------------------------  Retry
SessionRequest ------------------->
<------------------- SessionCreated
SessionConfirmed ----------------->

Khi Alice nghĩ rằng cô ấy có một token hợp lệ, nhưng Bob từ chối nó (có thể vì Bob đã khởi động lại), trình tự thiết lập như sau:

Alice                           Bob

SessionRequest ------------------->
<---------------------------  Retry
SessionRequest ------------------->
<------------------- SessionCreated
SessionConfirmed ----------------->

Bob có thể từ chối một Session hoặc Token Request bằng cách phản hồi với một thông điệp Retry có chứa khối Termination với mã lý do. Dựa trên mã lý do, Alice không nên thực hiện yêu cầu khác trong một khoảng thời gian:

Alice                           Bob

SessionRequest ------------------->
<---------------------------  Retry containing a Termination block

or

TokenRequest --------------------->
<---------------------------  Retry containing a Termination block

Sử dụng thuật ngữ Noise, chuỗi thiết lập và dữ liệu như sau: (Thuộc tính Bảo mật Payload)

XK(s, rs):           Authentication   Confidentiality
    <- s
    ...
    -> e, es                  0                2
    <- e, ee                  2                1
    -> s, se                  2                5
    <-                        2                5

Khi một phiên đã được thiết lập, Alice và Bob có thể trao đổi các thông điệp Data.

Packet Header

Tất cả các gói tin đều bắt đầu với một header bị làm rối (mã hóa). Có hai loại header, dài và ngắn. Lưu ý rằng 13 byte đầu tiên (Destination Connection ID, số gói tin, và loại) đều giống nhau cho tất cả các header.

Các Biện Pháp Đối Phó với Generic Request Forgery

Header dài có 32 byte. Nó được sử dụng trước khi phiên được tạo, cho Token Request, SessionRequest, SessionCreated, và Retry. Nó cũng được sử dụng cho các thông điệp Peer Test và Hole Punch ngoài phiên.

Trước khi mã hóa header:


+----+----+----+----+----+----+----+----+
  |      Destination Connection ID        |
  +----+----+----+----+----+----+----+----+
  |   Packet Number   |type| ver| id |flag|
  +----+----+----+----+----+----+----+----+
  |        Source Connection ID           |
  +----+----+----+----+----+----+----+----+
  |                 Token                 |
  +----+----+----+----+----+----+----+----+

  Destination Connection ID :: 8 bytes, unsigned big endian integer

  Packet Number :: 4 bytes, unsigned big endian integer

  type :: The message type = 0, 1, 7, 9, 10, or 11

  ver :: The protocol version, equal to 2

  id :: 1 byte, the network ID (currently 2, except for test networks)

  flag :: 1 byte, unused, set to 0 for future compatibility

  Source Connection ID :: 8 bytes, unsigned big endian integer

  Token :: 8 bytes, unsigned big endian integer

Tấn công Slowloris

Short header có độ dài 16 byte. Nó được sử dụng cho các thông điệp Session Created và Data. Các thông điệp không được xác thực như Session Request, Retry, và Peer Test sẽ luôn sử dụng long header.

16 byte là bắt buộc, bởi vì bên nhận phải giải mã 16 byte đầu tiên để lấy loại thông điệp, và sau đó phải giải mã thêm 16 byte nữa nếu đó thực sự là một header dài, như được chỉ ra bởi loại thông điệp.

Đối với Session Confirmed, trước khi mã hóa header:


+----+----+----+----+----+----+----+----+
  |      Destination Connection ID        |
  +----+----+----+----+----+----+----+----+
  |   Packet Number   |type|frag|  flags  |
  +----+----+----+----+----+----+----+----+

  Destination Connection ID :: 8 bytes, unsigned big endian integer

  Packet Number :: 4 bytes, all zeros

  type :: The message type = 2

  frag :: 1 byte fragment info:
         bit order: 76543210 (bit 7 is MSB)
         bits 7-4: fragment number 0-14, big endian
         bits 3-0: total fragments 1-15, big endian

  flags :: 2 bytes, unused, set to 0 for future compatibility

Xem phần Session Confirmed Fragmentation bên dưới để biết thêm thông tin về trường frag.

Đối với các thông điệp Data, trước khi mã hóa header:


+----+----+----+----+----+----+----+----+
  |      Destination Connection ID        |
  +----+----+----+----+----+----+----+----+
  |   Packet Number   |type|flag|moreflags|
  +----+----+----+----+----+----+----+----+

  Destination Connection ID :: 8 bytes, unsigned big endian integer

  Packet Number :: 4 bytes, unsigned big endian integer

  type :: The message type = 6

  flag :: 1 byte flags:
         bit order: 76543210 (bit 7 is MSB)
         bits 7-1: unused, set to 0 for future compatibility
         bits 0: when set to 1, immediate ack requested

  moreflags :: 2 bytes, unused, set to 0 for future compatibility

Tấn Công Phân Mảnh và Tái Lắp Ráp Luồng Dữ Liệu

ID kết nối phải được tạo ngẫu nhiên. Source ID và Destination ID KHÔNG được giống nhau, để một kẻ tấn công trên đường truyền không thể bắt và gửi lại một gói tin cho người gửi trông có vẻ hợp lệ. KHÔNG sử dụng bộ đếm để tạo ID kết nối, để một kẻ tấn công trên đường truyền không thể tạo ra một gói tin trông có vẻ hợp lệ.

Khác với QUIC, chúng tôi không thay đổi connection ID trong quá trình hoặc sau khi handshake, ngay cả sau một thông điệp Retry. Các ID vẫn giữ nguyên từ thông điệp đầu tiên (Token Request hoặc Session Request) đến thông điệp cuối cùng (Data với Termination). Ngoài ra, connection ID không thay đổi trong quá trình hoặc sau path challenge hoặc connection migration.

Cũng khác với QUIC là các connection ID trong header luôn được mã hóa header. Xem bên dưới.

Tấn Công Cam Kết Luồng (Stream Commitment Attack)

Nếu không có khối First Packet Number nào được gửi trong quá trình handshake, các gói tin được đánh số trong một phiên duy nhất, cho mỗi hướng, bắt đầu từ 0, đến tối đa (2**32 -1). Một phiên phải được kết thúc và một phiên mới được tạo ra, trước khi số lượng gói tin tối đa được gửi.

Nếu một khối First Packet Number được gửi trong quá trình handshake, các gói tin sẽ được đánh số trong một phiên duy nhất, theo hướng đó, bắt đầu từ số gói tin đó. Số gói tin có thể quay vòng trong suốt phiên. Khi tối đa 2**32 gói tin đã được gửi, làm cho số gói tin quay vòng trở lại số gói tin đầu tiên, phiên đó sẽ không còn hợp lệ. Một phiên phải được kết thúc, và một phiên mới được tạo ra, trước khi số gói tin tối đa được gửi.

CẦN LÀM xoay khóa, giảm số packet tối đa?

Các gói tin handshake được xác định là bị mất sẽ được truyền lại toàn bộ, với header giống hệt bao gồm cả packet number. Các thông điệp handshake Session Request, Session Created, và Session Confirmed PHẢI được truyền lại với cùng packet number và nội dung mã hóa giống hệt, để cùng một chained hash sẽ được sử dụng để mã hóa phản hồi. Thông điệp Retry không bao giờ được truyền.

Các gói tin pha dữ liệu được xác định là bị mất sẽ không bao giờ được truyền lại toàn bộ (trừ trường hợp kết thúc, xem bên dưới). Điều này cũng áp dụng cho các khối được chứa trong các gói tin bị mất. Thay vào đó, thông tin có thể được mang trong các khối sẽ được gửi lại trong các gói tin mới khi cần thiết. Các Gói Dữ liệu không bao giờ được truyền lại với cùng một số gói tin. Bất kỳ việc truyền lại nội dung gói tin nào (bất kể nội dung có giữ nguyên hay không) đều phải sử dụng số gói tin chưa sử dụng tiếp theo.

Việc truyền lại một gói tin hoàn chỉnh không thay đổi như cũ, với cùng một packet number, không được phép vì nhiều lý do. Để hiểu rõ bối cảnh, hãy xem QUIC RFC 9000 phần 12.3.

  • Việc lưu trữ các gói tin để truyền lại là không hiệu quả
  • Dữ liệu gói tin mới trông khác với người quan sát trên đường truyền, không thể biết đó là gói tin được truyền lại
  • Gói tin mới nhận được một ack block cập nhật được gửi cùng, không phải ack block cũ
  • Bạn chỉ truyền lại những gì cần thiết. một số fragment có thể đã được truyền lại một lần và đã được ack
  • Bạn có thể nhét nhiều như cần thiết vào mỗi gói tin được truyền lại nếu có thêm dữ liệu đang chờ
  • Các endpoint theo dõi tất cả các gói tin riêng lẻ nhằm mục đích phát hiện bản sao có nguy cơ tích lũy quá nhiều trạng thái. Dữ liệu cần thiết để phát hiện bản sao có thể được giới hạn bằng cách duy trì số gói tin tối thiểu mà dưới đó tất cả các gói tin sẽ bị loại bỏ ngay lập tức.
  • Sơ đồ này linh hoạt hơn nhiều

Các gói tin mới được sử dụng để mang thông tin được xác định là đã bị mất. Nói chung, thông tin được gửi lại khi một gói tin chứa thông tin đó được xác định là đã mất, và việc gửi sẽ dừng lại khi một gói tin chứa thông tin đó được xác nhận (remain the same).

Ngoại lệ: Một gói tin data phase chứa khối Termination có thể, nhưng không bắt buộc phải được truyền lại nguyên vẹn, như hiện tại. Xem phần Session Termination bên dưới.

Các gói tin sau đây chứa một số gói tin ngẫu nhiên bị bỏ qua:

  • Yêu Cầu Phiên
  • Phiên Đã Tạo
  • Yêu Cầu Token
  • Thử Lại
  • Kiểm Tra Peer
  • Hole Punch

Đối với Alice, việc đánh số packet gửi đi bắt đầu từ 0 với Session Confirmed. Đối với Bob, việc đánh số packet gửi đi bắt đầu từ 0 với packet Data đầu tiên, đây nên là một ACK của Session Confirmed. Các số packet trong một ví dụ handshake tiêu chuẩn sẽ là:

Alice                           Bob

SessionRequest (r)    ------------>
<-------------   SessionCreated (r)
SessionConfirmed (0)  ------------>
<-------------             Data (0) (Ack-only)
Data (1)              ------------> (May be sent before Ack is received)
<-------------             Data (1)
Data (2)              ------------>
Data (3)              ------------>
Data (4)              ------------>
<-------------             Data (2)

r = random packet number (ignored)
Token Request, Retry, and Peer Test
also have random packet numbers.

Bất kỳ việc truyền lại nào của các thông điệp handshake (SessionRequest, SessionCreated, hoặc SessionConfirmed) đều phải được gửi lại không thay đổi, với cùng số gói tin. Không sử dụng các khóa tạm thời khác nhau hoặc thay đổi payload khi truyền lại các thông điệp này.

Tấn công từ chối dịch vụ từ Peer

Header (trước khi bị làm xáo trộn và bảo vệ) luôn được bao gồm trong dữ liệu liên kết cho hàm AEAD, để ràng buộc mật mã học header với dữ liệu.

Các Cuộc Tấn Công Thông Báo Tắc Nghẽn Rõ Ràng

Mã hóa header có một số mục tiêu. Xem phần “Thảo luận DPI bổ sung” ở trên để hiểu rõ bối cảnh và các giả định.

  • Ngăn chặn DPI trực tuyến nhận diện giao thức
  • Ngăn chặn các mẫu trong chuỗi tin nhắn trong cùng một kết nối, ngoại trừ việc truyền lại handshake
  • Ngăn chặn các mẫu trong tin nhắn cùng loại ở các kết nối khác nhau
  • Ngăn chặn giải mã header handshake mà không có kiến thức về introduction key được tìm thấy trong netDb
  • Ngăn chặn nhận diện X25519 ephemeral keys mà không có kiến thức về introduction key được tìm thấy trong netDb
  • Ngăn chặn giải mã số thứ tự và loại gói tin data phase bởi bất kỳ kẻ tấn công trực tuyến hay ngoại tuyến nào
  • Ngăn chặn tiêm các gói tin handshake hợp lệ bởi kẻ quan sát trên đường truyền hoặc ngoài đường truyền mà không có kiến thức về introduction key được tìm thấy trong netDb
  • Ngăn chặn tiêm các gói tin data hợp lệ bởi kẻ quan sát trên đường truyền hoặc ngoài đường truyền
  • Cho phép phân loại nhanh chóng và hiệu quả các gói tin đến
  • Cung cấp khả năng chống “probing” để không có phản hồi với Session Request xấu, hoặc nếu có phản hồi Retry, phản hồi đó không thể nhận diện được là I2P mà không có kiến thức về introduction key được tìm thấy trong netDb
  • Destination Connection ID không phải là dữ liệu quan trọng, và không sao nếu nó có thể được giải mã bởi kẻ quan sát có kiến thức về introduction key được tìm thấy trong netDb
  • Số thứ tự gói tin của gói tin data phase là AEAD nonce và là dữ liệu quan trọng. Nó không được giải mã bởi kẻ quan sát ngay cả khi có kiến thức về introduction key được tìm thấy trong netDb. Xem Nonces.

Header được mã hóa bằng các khóa đã biết được xuất bản trong network database hoặc được tính toán sau đó. Trong giai đoạn handshake, điều này chỉ nhằm mục đích chống DPI, vì khóa này là công khai và khóa cùng nonces được tái sử dụng, vậy nên về cơ bản nó chỉ là sự che giấu. Lưu ý rằng việc mã hóa header cũng được sử dụng để che giấu các khóa ephemeral X (trong Session Request) và Y (trong Session Created).

Xem phần Xử lý Gói tin Đến bên dưới để có thêm hướng dẫn.

Byte 0-15 của tất cả header được mã hóa sử dụng một sơ đồ bảo vệ header bằng cách XOR với dữ liệu được tính toán từ các khóa đã biết, sử dụng ChaCha20, tương tự như QUIC RFC 9001Nonces. Điều này đảm bảo rằng short header được mã hóa và phần đầu của long header sẽ xuất hiện như là ngẫu nhiên.

Đối với Session Request và Session Created, các byte 16-31 của long header và 32-byte Noise ephemeral key được mã hóa bằng ChaCha20. Dữ liệu chưa mã hóa là ngẫu nhiên, do đó dữ liệu được mã hóa sẽ có vẻ như là ngẫu nhiên.

Đối với Retry, các byte 16-31 của long header được mã hóa bằng ChaCha20. Dữ liệu chưa mã hóa là ngẫu nhiên, do đó dữ liệu đã mã hóa sẽ có vẻ ngẫu nhiên.

Khác với sơ đồ bảo vệ header của QUIC RFC 9001, TẤT CẢ các phần của mọi header, bao gồm ID kết nối đích và nguồn, đều được mã hóa. QUIC RFC 9001Nonces chủ yếu tập trung vào việc mã hóa phần “quan trọng” của header, tức là số thứ tự gói tin (ChaCha20 nonce). Trong khi việc mã hóa session ID làm cho việc phân loại gói tin đến phức tạp hơn một chút, nó lại làm cho một số cuộc tấn công trở nên khó khăn hơn. QUIC định nghĩa các connection ID khác nhau cho các giai đoạn khác nhau, và cho path challenge và connection migration. Ở đây chúng tôi sử dụng cùng các connection ID xuyên suốt, vì chúng được mã hóa.

Có bảy giai đoạn khóa bảo vệ header:

  • Session Request và Token Request
  • Session Created
  • Retry
  • Session Confirmed
  • Data Phase
  • Peer Test
  • Hole Punch
MessageKey k_header_1Key k_header_2
Token RequestBob Intro KeyBob Intro Key
Session RequestBob Intro KeyBob Intro Key
Session CreatedBob Intro KeySee Session Request K
Session ConfirmedBob Intro KeySee Session Created K
RetryBob Intro KeyBob Intro Key
DataAlice/Bob Intro KeySee data phase KDF
Peer Test 5,7Alice Intro KeyAlice Intro Key
Peer Test 6Charlie Intro KeyCharlie Intro Key
Hole PunchAlice Intro KeyAlice Intro Key
Mã hóa header được thiết kế để cho phép phân loại nhanh chóng các gói tin đến mà không cần heuristics phức tạp hoặc các phương án dự phòng. Điều này được thực hiện bằng cách sử dụng cùng một khóa k_header_1 cho hầu hết tất cả các thông điệp đến. Ngay cả khi IP nguồn hoặc cổng của một kết nối thay đổi do thay đổi IP thực tế hoặc hành vi NAT, gói tin vẫn có thể được ánh xạ nhanh chóng đến một phiên với một lần tra cứu duy nhất của connection ID.

Lưu ý rằng Session Created và Retry là những tin nhắn DUY NHẤT yêu cầu xử lý dự phòng cho k_header_1 để giải mã Connection ID, vì chúng sử dụng intro key của người gửi (Bob). TẤT CẢ các tin nhắn khác sử dụng intro key của người nhận cho k_header_1. Xử lý dự phòng chỉ cần tra cứu các kết nối outbound đang chờ theo source IP/port.

Nếu quá trình dự phòng theo địa chỉ IP/cổng nguồn không tìm thấy kết nối outbound đang chờ xử lý, có thể có một số nguyên nhân:

  • Không phải là một thông điệp SSU2
  • Một thông điệp SSU2 bị hỏng
  • Phản hồi bị giả mạo hoặc sửa đổi bởi kẻ tấn công
  • Bob có symmetric NAT
  • Bob đã thay đổi IP hoặc port trong quá trình xử lý thông điệp
  • Bob đã gửi phản hồi qua một giao diện khác

Mặc dù có thể thực hiện xử lý dự phòng bổ sung để cố gắng tìm kết nối outbound đang chờ xử lý và giải mã connection ID bằng cách sử dụng k_header_1 cho kết nối đó, nhưng điều này có lẽ không cần thiết. Nếu Bob gặp vấn đề với NAT hoặc packet routing của mình, có lẽ tốt hơn là để kết nối thất bại. Thiết kế này dựa vào việc các endpoint duy trì một địa chỉ ổn định trong suốt thời gian handshake.

Xem phần Xử lý Gói tin Đến bên dưới để biết thêm hướng dẫn.

Xem các phần KDF riêng lẻ bên dưới để biết cách suy dẫn các khóa mã hóa header cho giai đoạn đó.

Stateless Reset Oracle

// incoming encrypted packet
  packet = incoming encrypted packet
  len = packet.length

  // take the next-to-last 12 bytes of the packet
  iv = packet[len-24:len-13]
  k_header_1 = header encryption key 1
  data = {0, 0, 0, 0, 0, 0, 0, 0}
  mask = ChaCha20.encrypt(k_header_1, iv, data)

  // encrypt the first part of the header by XORing with the mask
  packet[0:7] ^= mask[0:7]

  // take the last 12 bytes of the packet
  iv = packet[len-12:len-1]
  k_header_2 = header encryption key 2
  data = {0, 0, 0, 0, 0, 0, 0, 0}
  mask = ChaCha20.encrypt(k_header_2, iv, data)

  // encrypt the second part of the header by XORing with the mask
  packet[8:15] ^= mask[0:7]


  // For Session Request and Session Created only:
  iv = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}

  // encrypt the third part of the header and the ephemeral key
  packet[16:63] = ChaCha20.encrypt(k_header_2, iv, packet[16:63])


  // For Retry, Token Request, Peer Test, and Hole Punch only:
  iv = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}

  // encrypt the third part of the header
  packet[16:31] = ChaCha20.encrypt(k_header_2, iv, packet[16:31])

KDF này sử dụng 24 byte cuối cùng của gói tin làm IV cho hai thao tác ChaCha20. Vì tất cả các gói tin đều kết thúc bằng một MAC 16 byte, điều này yêu cầu tất cả các payload của gói tin phải có tối thiểu 8 byte. Yêu cầu này cũng được ghi chú thêm trong các phần thông điệp bên dưới.

Hạ Cấp Phiên Bản

Sau khi giải mã 8 byte đầu tiên của header, bên nhận sẽ biết được Destination Connection ID. Từ đó, bên nhận sẽ biết sử dụng khóa mã hóa header nào cho phần còn lại của header, dựa trên key phase của phiên làm việc.

Giải mã 8 byte tiếp theo của header sẽ tiết lộ loại thông điệp và có thể xác định xem đó là header ngắn hay dài. Nếu đó là header dài, bên nhận phải xác thực các trường version và netid. Nếu version != 2, hoặc netid != giá trị mong đợi (thường là 2, ngoại trừ trong mạng thử nghiệm), bên nhận nên loại bỏ thông điệp.

Packet Integrity

Tất cả thông điệp đều chứa ba hoặc bốn phần:

  • Header của thông điệp
  • Chỉ dành cho Session Request và Session Created, một khóa tạm thời
  • Payload được mã hóa ChaCha20
  • Một Poly1305 MAC

Trong tất cả các trường hợp, header (và nếu có, ephemeral key) được ràng buộc với authentication MAC để đảm bảo toàn bộ thông điệp còn nguyên vẹn.

  • Đối với các thông điệp handshake Session Request, Session Created, và Session Confirmed, header thông điệp được mixHash() trước giai đoạn xử lý Noise
  • Ephemeral key, nếu có, được bảo vệ bởi một Noise misHash() tiêu chuẩn
  • Đối với các thông điệp ngoài Noise handshake, header được sử dụng như Associated Data cho mã hóa ChaCha20/Poly1305.

Các bộ xử lý packet inbound phải luôn giải mã payload ChaCha20 và xác thực MAC trước khi xử lý thông điệp, với một ngoại lệ: Để giảm thiểu các cuộc tấn công DoS từ các packet giả mạo địa chỉ chứa các thông điệp Session Request có vẻ hợp lệ với token không đúng, một bộ xử lý KHÔNG CẦN cố gắng giải mã và xác thực toàn bộ thông điệp (đòi hỏi một thao tác DH tốn kém ngoài việc giải mã ChaCha20/Poly1305). Bộ xử lý có thể phản hồi bằng thông điệp Retry sử dụng các giá trị tìm thấy trong header của thông điệp Session Request.

Authenticated Encryption

Có ba instance mã hóa được xác thực riêng biệt (CipherStates). Một instance trong giai đoạn handshake, và hai instance (truyền và nhận) cho giai đoạn dữ liệu. Mỗi instance có khóa riêng từ một KDF.

Dữ liệu được mã hóa/xác thực sẽ được biểu diễn như

+----+----+----+----+----+----+----+----+
  |                                       |
  +                                       +
  |   Encrypted and authenticated data    |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+

Các Cuộc Tấn Công Có Mục Tiêu Thông Qua Routing

Định dạng dữ liệu được mã hóa và xác thực.

Đầu vào cho các hàm mã hóa/giải mã:


k :: 32 byte cipher key, as generated from KDF

  nonce :: Counter-based nonce, 12 bytes.
           Starts at 0 and incremented for each message.
           First four bytes are always zero.
           Last eight bytes are the counter, little-endian encoded.
           Maximum value is 2**64 - 2.
           Connection must be dropped and restarted after
           it reaches that value.
           The value 2**64 - 1 must never be sent.

  ad :: In handshake phase:
        Associated data, 32 bytes.
        The SHA256 hash of all preceding data.
        In data phase:
        The packet header, 16 bytes.

  data :: Plaintext data, 0 or more bytes

Đầu ra của hàm mã hóa, đầu vào của hàm giải mã:


+----+----+----+----+----+----+----+----+
  |                                       |
  +                                       +
  |       ChaCha20 encrypted data         |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+
  |  Poly1305 Message Authentication Code |
  +              (MAC)                    +
  |             16 bytes                  |
  +----+----+----+----+----+----+----+----+

  encrypted data :: Same size as plaintext data, 0 - 65519 bytes

  MAC :: Poly1305 message authentication code, 16 bytes

Đối với ChaCha20, những gì được mô tả ở đây tương ứng với RFC 7539, cũng được sử dụng tương tự trong TLS RFC 7905.

Phân Tích Lưu Lượng

  • Vì ChaCha20 là một stream cipher (mã hóa luồng), plaintext không cần được padding. Các byte keystream bổ sung sẽ bị loại bỏ.

  • Khóa cho mật mã (256 bit) được thỏa thuận thông qua SHA256 KDF. Chi tiết của KDF cho từng thông điệp được trình bày trong các phần riêng biệt bên dưới.

AEAD Error Handling

  • Trong tất cả các thông điệp, kích thước thông điệp AEAD được biết trước. Khi xác thực AEAD thất bại, bên nhận phải dừng xử lý thông điệp và loại bỏ thông điệp đó.

  • Bob nên duy trì một blacklist các IP có lỗi lặp lại.

KDF for Session Request

Key Derivation Function (KDF) tạo ra một khóa mật mã giai đoạn bắt tay k từ kết quả DH, sử dụng HMAC-SHA256(key, data) như được định nghĩa trong RFC 2104. Đây là các hàm InitializeSymmetric(), MixHash(), và MixKey(), chính xác như được định nghĩa trong đặc tả Noise.

KDF for Initial ChainKey


// Define protocol_name.
  Set protocol_name = "Noise_XKchaobfse+hs1+hs2+hs3_25519_ChaChaPoly_SHA256"
   (52 bytes, US-ASCII encoded, no NULL termination).

  // Define Hash h = 32 bytes
  h = SHA256(protocol_name);

  Define ck = 32 byte chaining key. Copy the h data to ck.
  Set ck = h

  // MixHash(null prologue)
  h = SHA256(h);

  // up until here, can all be precalculated by Alice for all outgoing connections

  // Bob's X25519 static keys
  // bpk is published in routerinfo
  bsk = GENERATE_PRIVATE()
  bpk = DERIVE_PUBLIC(bsk)

  // Bob static key
  // MixHash(bpk)
  // || below means append
  h = SHA256(h || bpk);

  // Bob introduction key
  // bik is published in routerinfo
  bik = RANDOM(32)

  // up until here, can all be precalculated by Bob for all incoming connections

KDF for Session Request


// MixHash(header)
  h = SHA256(h || header)

  This is the "e" message pattern:

  // Alice's X25519 ephemeral keys
  aesk = GENERATE_PRIVATE()
  aepk = DERIVE_PUBLIC(aesk)

  // Alice ephemeral key X
  // MixHash(aepk)
  h = SHA256(h || aepk);

  // h is used as the associated data for the AEAD in Session Request
  // Retain the Hash h for the Session Created KDF


  End of "e" message pattern.

  This is the "es" message pattern:

  // DH(e, rs) == DH(s, re)
  sharedSecret = DH(aesk, bpk) = DH(bsk, aepk)

  // MixKey(DH())
  //[chainKey, k] = MixKey(sharedSecret)
  // ChaChaPoly parameters to encrypt/decrypt
  keydata = HKDF(chainKey, sharedSecret, "", 64)
  chainKey = keydata[0:31]

  // AEAD parameters
  k = keydata[32:63]
  n = 0
  ad = h
  ciphertext = ENCRYPT(k, n, payload, ad)

  // retain the chainKey for Session Created KDF


  End of "es" message pattern.

  // Header encryption keys for this message
  // bik = Bob's intro key
  k_header_1 = bik
  k_header_2 = bik

  // Header encryption keys for next message (Session Created)
  k_header_1 = bik
  k_header_2 = HKDF(chainKey, ZEROLEN, "SessCreateHeader", 32)

  // Header encryption keys for next message (Retry)
  k_header_1 = bik
  k_header_2 = bik

SessionRequest (Type 0)

Alice gửi cho Bob, có thể là tin nhắn đầu tiên trong quá trình handshake, hoặc để phản hồi một tin nhắn Retry. Bob phản hồi bằng một tin nhắn Session Created. Kích thước: 80 + kích thước payload. Kích thước tối thiểu: 88

Nếu Alice không có token hợp lệ, Alice nên gửi thông điệp Token Request thay vì Session Request, để tránh chi phí mã hóa bất đối xứng khi tạo Session Request.

Header dài. Nội dung Noise: Khóa tạm thời X của Alice Payload Noise: DateTime và các khối khác Kích thước payload tối đa: MTU - 108 (IPv4) hoặc MTU - 128 (IPv6). Với MTU 1280: Payload tối đa là 1172 (IPv4) hoặc 1152 (IPv6). Với MTU 1500: Payload tối đa là 1392 (IPv4) hoặc 1372 (IPv6).

Thuộc tính Bảo mật Payload:

XK(s, rs):           Authentication   Confidentiality
    -> e, es                  0                2

    Authentication: None (0).
    This payload may have been sent by any party, including an active attacker.

    Confidentiality: 2.
    Encryption to a known recipient, forward secrecy for sender compromise
    only, vulnerable to replay.  This payload is encrypted based only on DHs
    involving the recipient's static key pair.  If the recipient's static
    private key is compromised, even at a later date, this payload can be
    decrypted.  This message can also be replayed, since there's no ephemeral
    contribution from the recipient.

    "e": Alice generates a new ephemeral key pair and stores it in the e
         variable, writes the ephemeral public key as cleartext into the
         message buffer, and hashes the public key along with the old h to
         derive a new h.

    "es": A DH is performed between the Alice's ephemeral key pair and the
          Bob's static key pair.  The result is hashed along with the old ck to
          derive a new ck and k, and n is set to zero.

Giá trị X được mã hóa để đảm bảo tính không thể phân biệt và tính duy nhất của payload, đây là các biện pháp đối phó DPI cần thiết. Chúng tôi sử dụng mã hóa ChaCha20 để đạt được điều này, thay vì các phương án phức tạp và chậm hơn như elligator2. Mã hóa bất đối xứng với khóa công khai của router Bob sẽ quá chậm. Mã hóa ChaCha20 sử dụng intro key của Bob như được công bố trong network database.

Mã hóa ChaCha20 chỉ dành cho việc chống DPI. Bất kỳ bên nào biết introduction key của Bob, được công bố trong cơ sở dữ liệu mạng, đều có thể giải mã header và giá trị X trong thông điệp này.

Nội dung thô:

+----+----+----+----+----+----+----+----+
  |  Long Header bytes 0-15, ChaCha20     |
  +  encrypted with Bob intro key         +
  |    See Header Encryption KDF          |
  +----+----+----+----+----+----+----+----+
  |  Long Header bytes 16-31, ChaCha20    |
  +  encrypted with Bob intro key n=0     +
  |                                       |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +       X, ChaCha20 encrypted           +
  |       with Bob intro key n=0          |
  +              (32 bytes)               +
  |                                       |
  +                                       +
  |                                       |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +                                       +
  |   ChaCha20 encrypted data             |
  +          (length varies)              +
  |  k defined in KDF for Session Request |
  +  n = 0                                +
  |  see KDF for associated data          |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +        Poly1305 MAC (16 bytes)        +
  |                                       |
  +----+----+----+----+----+----+----+----+

  X :: 32 bytes, ChaCha20 encrypted X25519 ephemeral key, little endian
          key: Bob's intro key
          n: 1
          data: 48 bytes (bytes 16-31 of the header, followed by encrypted X)

Dữ liệu không mã hóa (thẻ xác thực Poly1305 không được hiển thị):

+----+----+----+----+----+----+----+----+
  |      Destination Connection ID        |
  +----+----+----+----+----+----+----+----+
  |   Packet Number   |type| ver| id |flag|
  +----+----+----+----+----+----+----+----+
  |        Source Connection ID           |
  +----+----+----+----+----+----+----+----+
  |                 Token                 |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +                                       +
  |                   X                   |
  +              (32 bytes)               +
  |                                       |
  +                                       +
  |                                       |
  +----+----+----+----+----+----+----+----+
  |     Noise payload (block data)        |
  +          (length varies)              +
  |     see below for allowed blocks      |
  +----+----+----+----+----+----+----+----+


  Destination Connection ID :: Randomly generated by Alice

  id :: 1 byte, the network ID (currently 2, except for test networks)

  ver :: 2

  type :: 0

  flag :: 1 byte, unused, set to 0 for future compatibility

  Packet Number :: Random 4 byte number generated by Alice, ignored

  Source Connection ID :: Randomly generated by Alice,
                          must not be equal to Destination Connection ID

  Token :: 0 if not previously received from Bob

  X :: 32 bytes, X25519 ephemeral key, little endian

Payload

  • Khối DateTime
  • Khối Options (tùy chọn)
  • Khối Relay Tag Request (tùy chọn)
  • Khối Padding (tùy chọn)

Kích thước payload tối thiểu là 8 bytes. Vì khối DateTime chỉ có 7 bytes, nên phải có ít nhất một khối khác.

Notes

  • Giá trị X duy nhất trong khối ChaCha20 ban đầu đảm bảo rằng bản mã hóa là khác nhau cho mỗi phiên.

  • Để cung cấp khả năng chống thăm dò, Bob không nên gửi thông điệp Retry để phản hồi thông điệp Session Request trừ khi các trường loại thông điệp, phiên bản giao thức, và ID mạng trong thông điệp Session Request là hợp lệ.

  • Bob phải từ chối các kết nối mà giá trị timestamp quá xa so với thời gian hiện tại. Gọi khoảng thời gian tối đa này là “D”. Bob phải duy trì một cache cục bộ các giá trị handshake đã được sử dụng trước đó và từ chối các giá trị trùng lặp, để ngăn chặn các cuộc tấn công replay. Các giá trị trong cache phải có thời gian sống ít nhất là 2*D. Các giá trị cache phụ thuộc vào cách triển khai, tuy nhiên có thể sử dụng giá trị X 32-byte (hoặc tương đương đã mã hóa của nó). Từ chối bằng cách gửi một thông điệp Retry chứa một token bằng không và một termination block.

  • Các khóa tạm thời Diffie-Hellman không bao giờ được tái sử dụng để ngăn chặn các cuộc tấn công mật mã, và việc tái sử dụng sẽ bị từ chối như một cuộc tấn công replay.

  • Các tùy chọn “KE” và “auth” phải tương thích, tức là khóa bí mật dùng chung K phải có kích thước phù hợp. Nếu thêm các tùy chọn “auth” khác, điều này có thể thay đổi ngầm định ý nghĩa của cờ “KE” để sử dụng một KDF khác hoặc kích thước cắt bớt khác.

  • Bob phải xác thực rằng ephemeral key của Alice là một điểm hợp lệ trên đường cong tại đây.

  • Padding nên được giới hạn ở mức hợp lý. Bob có thể từ chối các kết nối có padding quá mức. Bob sẽ chỉ định các tùy chọn padding của mình trong Session Created. Hướng dẫn tối thiểu/tối đa TBD. Kích thước ngẫu nhiên từ 0 đến 31 byte tối thiểu? (Phân phối sẽ được xác định, xem Phụ lục A.) TODO TRỪ KHI kích thước packet tối thiểu được thực thi cho PMTU.

  • Với hầu hết các lỗi, bao gồm AEAD, DH, replay rõ ràng, hoặc lỗi xác thực khóa, Bob nên dừng việc xử lý thông điệp và bỏ thông điệp mà không phản hồi.

  • Bob CÓ THỂ gửi một thông điệp Retry chứa token bằng không và một khối Termination với mã lý do clock skew nếu timestamp trong khối DateTime bị lệch quá xa.

  • Giảm thiểu DoS: DH là một thao tác tương đối tốn kém. Giống như với giao thức NTCP trước đó, các router nên thực hiện mọi biện pháp cần thiết để ngăn chặn tình trạng cạn kiệt CPU hoặc kết nối. Đặt giới hạn số lượng kết nối hoạt động tối đa và số lượng thiết lập kết nối đang tiến hành tối đa. Áp dụng timeout đọc (cả cho từng lần đọc và tổng thời gian cho “slowloris”). Giới hạn các kết nối lặp lại hoặc đồng thời từ cùng một nguồn. Duy trì blacklist cho các nguồn thường xuyên thất bại. Không phản hồi lại lỗi AEAD. Hoặc thay vào đó, phản hồi bằng thông điệp Retry trước thao tác DH và xác thực AEAD.

  • Trường “ver”: Giao thức Noise tổng thể, các tiện ích mở rộng, và giao thức SSU2 bao gồm các đặc tả payload, chỉ ra SSU2. Trường này có thể được sử dụng để chỉ ra sự hỗ trợ cho các thay đổi trong tương lai.

  • Trường network ID được sử dụng để nhanh chóng xác định các kết nối xuyên mạng. Nếu trường này không khớp với network ID của Bob, Bob nên ngắt kết nối và chặn các kết nối trong tương lai.

  • Bob phải loại bỏ thông điệp nếu Source Connection ID bằng với Destination Connection ID.

KDF for Session Created and Session Confirmed part 1


// take h saved from Session Request KDF
  // MixHash(ciphertext)
  h = SHA256(h || encrypted Noise payload from Session Request)

  // MixHash(header)
  h = SHA256(h || header)

  This is the "e" message pattern:

  // Bob's X25519 ephemeral keys
  besk = GENERATE_PRIVATE()
  bepk = DERIVE_PUBLIC(besk)

  // h is from KDF for Session Request
  // Bob ephemeral key Y
  // MixHash(bepk)
  h = SHA256(h || bepk);

  // h is used as the associated data for the AEAD in Session Created
  // Retain the Hash h for the Session Confirmed KDF

  End of "e" message pattern.

  This is the "ee" message pattern:

  // MixKey(DH())
  //[chainKey, k] = MixKey(sharedSecret)
  sharedSecret = DH(aesk, bepk) = DH(besk, aepk)
  keydata = HKDF(chainKey, sharedSecret, "", 64)
  chainKey = keydata[0:31]

  // AEAD parameters
  k = keydata[32:63]
  n = 0
  ad = h
  ciphertext = ENCRYPT(k, n, payload, ad)

  // retain the chaining key ck for Session Confirmed KDF

  End of "ee" message pattern.

  // Header encryption keys for this message
  // bik = Bob's intro key
  k_header_1 = bik
  k_header_2: See Session Request KDF above

  // Header protection keys for next message (Session Confirmed)
  k_header_1 = bik
  k_header_2 = HKDF(chainKey, ZEROLEN, "SessionConfirmed", 32)

Di chuyển Kết nối

Bob gửi cho Alice, để phản hồi thông điệp Session Request. Alice phản hồi bằng thông điệp Session Confirmed. Kích thước: 80 + kích thước payload. Kích thước tối thiểu: 88

Nội dung Noise: Khóa tạm thời Y của Bob Payload Noise: DateTime, Address, và các khối khác Kích thước payload tối đa: MTU - 108 (IPv4) hoặc MTU - 128 (IPv6). Với MTU 1280: Payload tối đa là 1172 (IPv4) hoặc 1152 (IPv6). Với MTU 1500: Payload tối đa là 1392 (IPv4) hoặc 1372 (IPv6).

Thuộc tính Bảo mật Payload:

XK(s, rs):           Authentication   Confidentiality
    <- e, ee                  2                1

    Authentication: 2.
    Sender authentication resistant to key-compromise impersonation (KCI).
    The sender authentication is based on an ephemeral-static DH ("es" or "se")
    between the sender's static key pair and the recipient's ephemeral key pair.
    Assuming the corresponding private keys are secure, this authentication cannot be forged.

    Confidentiality: 1.
    Encryption to an ephemeral recipient.
    This payload has forward secrecy, since encryption involves an ephemeral-ephemeral DH ("ee").
    However, the sender has not authenticated the recipient,
    so this payload might be sent to any party, including an active attacker.


    "e": Bob generates a new ephemeral key pair and stores it in the e variable,
    writes the ephemeral public key as cleartext into the message buffer,
    and hashes the public key along with the old h to derive a new h.

    "ee": A DH is performed between the Bob's ephemeral key pair and the Alice's ephemeral key pair.
    The result is hashed along with the old ck to derive a new ck and k, and n is set to zero.

Giá trị Y được mã hóa để đảm bảo tính không thể phân biệt và tính duy nhất của payload, đây là những biện pháp đối phó DPI cần thiết. Chúng tôi sử dụng mã hóa ChaCha20 để đạt được điều này, thay vì các lựa chọn phức tạp và chậm hơn như elligator2. Mã hóa bất đối xứng với khóa công khai router của Alice sẽ quá chậm. Mã hóa ChaCha20 sử dụng intro key của Bob, như được công bố trong network database.

Mã hóa ChaCha20 chỉ dùng để chống DPI. Bất kỳ bên nào biết intro key của Bob, được công bố trong network database, và bắt được 32 byte đầu tiên của Session Request, có thể giải mã giá trị Y trong thông điệp này.

Nội dung thô:

+----+----+----+----+----+----+----+----+
  |  Long Header bytes 0-15, ChaCha20     |
  +  encrypted with Bob intro key and     +
  | derived key, see Header Encryption KDF|
  +----+----+----+----+----+----+----+----+
  |  Long Header bytes 16-31, ChaCha20    |
  +  encrypted with derived key n=0       +
  |  See Header Encryption KDF            |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +       Y, ChaCha20 encrypted           +
  |       with derived key n=0            |
  +              (32 bytes)               +
  |       See Header Encryption KDF       |
  +                                       +
  |                                       |
  +----+----+----+----+----+----+----+----+
  |   ChaCha20 data                       |
  +   Encrypted and authenticated data    +
  |  length varies                        |
  +  k defined in KDF for Session Created +
  |  n = 0; see KDF for associated data   |
  +                                       +
  |                                       |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +        Poly1305 MAC (16 bytes)        +
  |                                       |
  +----+----+----+----+----+----+----+----+

  Y :: 32 bytes, ChaCha20 encrypted X25519 ephemeral key, little endian
          key: Bob's intro key
          n: 1
          data: 48 bytes (bytes 16-31 of the header, followed by encrypted Y)

Dữ liệu không mã hóa (auth tag Poly1305 không được hiển thị):

+----+----+----+----+----+----+----+----+
  |      Destination Connection ID        |
  +----+----+----+----+----+----+----+----+
  |   Packet Number   |type| ver| id |flag|
  +----+----+----+----+----+----+----+----+
  |        Source Connection ID           |
  +----+----+----+----+----+----+----+----+
  |                 Token                 |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +                                       +
  |                  Y                    |
  +              (32 bytes)               +
  |                                       |
  +                                       +
  |                                       |
  +----+----+----+----+----+----+----+----+
  |     Noise payload (block data)        |
  +          (length varies)              +
  |      see below for allowed blocks     |
  +----+----+----+----+----+----+----+----+

  Destination Connection ID :: The Source Connection ID
                               received from Alice in Session Request

  id :: 1 byte, the network ID (currently 2, except for test networks)

  ver :: 2

  type :: 0

  flag :: 1 byte, unused, set to 0 for future compatibility

  Packet Number :: Random 4 byte number generated by Bob, ignored

  Source Connection ID :: The Destination Connection ID
                          received from Alice in Session Request

  Token :: 0 (unused)

  Y :: 32 bytes, X25519 ephemeral key, little endian

Payload

  • Khối DateTime
  • Khối Address
  • Khối Relay Tag (tùy chọn)
  • Khối New Token (tùy chọn)
  • Khối First Packet Number (tùy chọn)
  • Khối Options (tùy chọn)
  • Khối Termination (không được khuyến nghị, thay vào đó hãy gửi trong thông điệp retry)
  • Khối Padding (tùy chọn)

Kích thước payload tối thiểu là 8 byte. Vì các khối DateTime và Address có tổng kích thước lớn hơn con số đó, yêu cầu được đáp ứng chỉ với hai khối này.

Notes

  • Alice phải xác thực rằng khóa tạm thời của Bob là một điểm hợp lệ trên đường cong ở đây.

  • Padding nên được giới hạn ở mức hợp lý. Alice có thể từ chối các kết nối có padding quá mức. Alice sẽ chỉ định các tùy chọn padding của mình trong Session Confirmed. Hướng dẫn min/max sẽ được xác định sau. Kích thước ngẫu nhiên từ 0 đến 31 byte tối thiểu? (Phân phối sẽ được xác định, xem Phụ lục A.) TODO TRỪ KHI kích thước gói tối thiểu được áp dụng cho PMTU.

  • Khi có bất kỳ lỗi nào, bao gồm AEAD, DH, timestamp, phát hiện replay rõ ràng, hoặc lỗi xác thực khóa, Alice phải dừng xử lý thông điệp và đóng kết nối mà không phản hồi.

  • Alice phải từ chối các kết nối có giá trị timestamp quá xa so với thời gian hiện tại. Gọi khoảng thời gian tối đa là “D”. Alice phải duy trì một bộ nhớ đệm cục bộ các giá trị handshake đã sử dụng trước đó và từ chối các giá trị trùng lặp, để ngăn chặn các cuộc tấn công replay. Các giá trị trong bộ nhớ đệm phải có thời gian tồn tại ít nhất là 2*D. Các giá trị bộ nhớ đệm phụ thuộc vào cách triển khai, tuy nhiên có thể sử dụng giá trị Y 32-byte (hoặc phiên bản mã hóa tương đương của nó).

  • Alice phải loại bỏ thông điệp nếu IP nguồn và port không khớp với IP đích và port của Session Request.

  • Alice phải loại bỏ thông điệp nếu Destination và Source Connection IDs không khớp với Source và Destination Connection IDs của Session Request.

  • Bob gửi một relay tag block nếu được Alice yêu cầu trong Session Request.

Issues

  • Bao gồm các tùy chọn padding tối thiểu/tối đa ở đây?

KDF for Session Confirmed part 1, using Session Created KDF


// take h saved from Session Created KDF
  // MixHash(ciphertext)
  h = SHA256(h || encrypted Noise payload from Session Created)

  // MixHash(header)
  h = SHA256(h || header)
  // h is used as the associated data for the AEAD in Session Confirmed part 1, below

  This is the "s" message pattern:

  // Alice's X25519 static keys
  ask = GENERATE_PRIVATE()
  apk = DERIVE_PUBLIC(ask)

  // AEAD parameters
  // k is from Session Request
  n = 1
  ad = h
  ciphertext = ENCRYPT(k, n++, apk, ad)

  // MixHash(ciphertext)
  h = SHA256(h || ciphertext);

  // h is used as the associated data for the AEAD in Session Confirmed part 2

  End of "s" message pattern.

  // Header encryption keys for this message
  See Session Confirmed part 2 below

KDF for Session Confirmed part 2


This is the "se" message pattern:

  // DH(ask, bepk) == DH(besk, apk)
  sharedSecret = DH(ask, bepk) = DH(besk, apk)

  // MixKey(DH())
  //[chainKey, k] = MixKey(sharedSecret)
  keydata = HKDF(chainKey, sharedSecret, "", 64)
  chainKey = keydata[0:31]

  // AEAD parameters
  k = keydata[32:63]
  n = 0
  ad = h
  ciphertext = ENCRYPT(k, n, payload, ad)

  // h from Session Confirmed part 1 is used as the associated data for the AEAD in Session Confirmed part 2
  // MixHash(ciphertext)
  h = SHA256(h || ciphertext);

  // retain the chaining key ck for the data phase KDF
  // retain the hash h for the data phase KDF

  End of "se" message pattern.

  // Header encryption keys for this message
  // bik = Bob's intro key
  k_header_1 = bik
  k_header_2: See Session Created KDF above

  // Header protection keys for data phase
  See data phase KDF below

SessionConfirmed (Type 2)

Alice gửi đến Bob, để phản hồi thông điệp Session Created. Bob phản hồi ngay lập tức với thông điệp Data chứa khối ACK. Kích thước: 80 + kích thước payload. Kích thước tối thiểu: Khoảng 500 (kích thước khối router info tối thiểu là khoảng 420 bytes)

Nội dung Noise: Static key của Alice Phần payload Noise 1: Không có Phần payload Noise 2: RouterInfo của Alice, và các khối khác Kích thước payload tối đa: MTU - 108 (IPv4) hoặc MTU - 128 (IPv6). Với MTU 1280: Payload tối đa là 1172 (IPv4) hoặc 1152 (IPv6). Với MTU 1500: Payload tối đa là 1392 (IPv4) hoặc 1372 (IPv6).

Thuộc tính Bảo mật Payload:

XK(s, rs):           Authentication   Confidentiality
    -> s, se                  2                5

    Authentication: 2.
    Sender authentication resistant to key-compromise impersonation (KCI).  The
    sender authentication is based on an ephemeral-static DH ("es" or "se")
    between the sender's static key pair and the recipient's ephemeral key
    pair.  Assuming the corresponding private keys are secure, this
    authentication cannot be forged.

    Confidentiality: 5.
    Encryption to a known recipient, strong forward secrecy.  This payload is
    encrypted based on an ephemeral-ephemeral DH as well as an ephemeral-static
    DH with the recipient's static key pair.  Assuming the ephemeral private
    keys are secure, and the recipient is not being actively impersonated by an
    attacker that has stolen its static private key, this payload cannot be
    decrypted.

    "s": Alice writes her static public key from the s variable into the
    message buffer, encrypting it, and hashes the output along with the old h
    to derive a new h.

    "se": A DH is performed between the Alice's static key pair and the Bob's
    ephemeral key pair.  The result is hashed along with the old ck to derive a
    new ck and k, and n is set to zero.

Điều này chứa hai ChaChaPoly frame. Frame đầu tiên là static public key được mã hóa của Alice. Frame thứ hai là Noise payload: RouterInfo được mã hóa của Alice, các tùy chọn không bắt buộc, và padding không bắt buộc. Chúng sử dụng các khóa khác nhau, vì hàm MixKey() được gọi ở giữa.

Nội dung thô:

+----+----+----+----+----+----+----+----+
  |  Short Header 16 bytes, ChaCha20      |
  +  encrypted with Bob intro key and     +
  | derived key, see Header Encryption KDF|
  +----+----+----+----+----+----+----+----+
  |   ChaCha20 frame (32 bytes)           |
  +   Encrypted and authenticated data    +
  +   Alice static key S                  +
  | k defined in KDF for Session Created  |
  +     n = 1                             +
  |                                       |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +        Poly1305 MAC (16 bytes)        +
  |                                       |
  +----+----+----+----+----+----+----+----+
  |                                       |
  + Length varies (remainder of packet)   +
  |                                       |
  +   ChaChaPoly frame                    +
  |   Encrypted and authenticated         |
  +   see below for allowed blocks        +
  |                                       |
  +     k defined in KDF for              +
  |     Session Confirmed part 2          |
  +     n = 0                             +
  |     see KDF for associated data       |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +        Poly1305 MAC (16 bytes)        +
  |                                       |
  +----+----+----+----+----+----+----+----+

  S :: 32 bytes, ChaChaPoly encrypted Alice's X25519 static key, little endian
       inside 48 byte ChaChaPoly frame

Dữ liệu không mã hóa (không hiển thị Poly1305 auth tags):

+----+----+----+----+----+----+----+----+
  |      Destination Connection ID        |
  +----+----+----+----+----+----+----+----+
  |   Packet Number   |type|frag|  flags  |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +                                       +
  |              S                        |
  +       Alice static key                +
  |          (32 bytes)                   |
  +                                       +
  |                                       |
  +                                       +
  +----+----+----+----+----+----+----+----+
  |                                       |
  +                                       +
  |        Noise Payload                  |
  +        (length varies)                +
  |        see below for allowed blocks   |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+

  Destination Connection ID :: As sent in Session Request,
                               or one received in Session Confirmed?

  Packet Number :: 0 always, for all fragments, even if retransmitted

  type :: 2

  frag :: 1 byte fragment info:
         bit order: 76543210 (bit 7 is MSB)
         bits 7-4: fragment number 0-14, big endian
         bits 3-0: total fragments 1-15, big endian

  flags :: 2 bytes, unused, set to 0 for future compatibility

  S :: 32 bytes, Alice's X25519 static key, little endian

Payload

  • Khối RouterInfo (phải là khối đầu tiên)
  • Khối Options (tùy chọn)
  • Khối New Token (tùy chọn)
  • Khối Relay Request (tùy chọn)
  • Khối Peer Test (tùy chọn)
  • Khối First Packet Number (tùy chọn)
  • Các khối I2NP, First Fragment, hoặc Follow-on Fragment (tùy chọn, nhưng có thể không có chỗ)
  • Khối Padding (tùy chọn)

Kích thước payload tối thiểu là 8 byte. Vì block RouterInfo sẽ lớn hơn nhiều so với mức đó, yêu cầu này đã được đáp ứng chỉ với block đó.

Notes

  • Bob phải thực hiện xác thực Router Info thông thường. Đảm bảo loại chữ ký được hỗ trợ, xác minh chữ ký, xác minh timestamp nằm trong giới hạn cho phép, và bất kỳ kiểm tra cần thiết nào khác. Xem bên dưới để biết ghi chú về xử lý Router Info bị phân mảnh.

  • Bob phải xác minh rằng khóa tĩnh của Alice nhận được trong frame đầu tiên khớp với khóa tĩnh trong Router Info. Bob trước tiên phải tìm kiếm trong Router Info để tìm một NTCP hoặc SSU2 Router Address có tùy chọn phiên bản (v) khớp. Xem các phần Published Router Info và Unpublished Router Info bên dưới. Xem bên dưới để biết ghi chú về cách xử lý Router Infos bị phân mảnh.

  • Nếu Bob có phiên bản cũ hơn của RouterInfo của Alice trong netdb của mình, hãy xác minh rằng static key trong router info là giống nhau ở cả hai, nếu có, và nếu phiên bản cũ hơn ít hơn XXX tuổi (xem thời gian xoay key bên dưới)

  • Bob phải xác thực rằng khóa tĩnh của Alice là một điểm hợp lệ trên đường cong ở đây.

  • Các tùy chọn nên được bao gồm để chỉ định các tham số padding.

  • Khi có bất kỳ lỗi nào, bao gồm lỗi xác thực AEAD, RI, DH, timestamp, hoặc key validation, Bob phải dừng xử lý thông điệp và đóng kết nối mà không cần phản hồi.

  • Nội dung frame phần 2 của Message 3: Định dạng của frame này giống với định dạng của các frame trong giai đoạn dữ liệu, ngoại trừ việc độ dài của frame được Alice gửi trong Session Request. Xem bên dưới để biết định dạng frame giai đoạn dữ liệu. Frame phải chứa từ 1 đến 4 block theo thứ tự sau:

    1. Block Router Info của Alice (bắt buộc)
    2. Block Options (tùy chọn)
    3. Các block I2NP (tùy chọn)
    4. Block Padding (tùy chọn) Frame này không bao giờ được chứa bất kỳ loại block nào khác. TODO: còn relay và peer test thì sao?
  • Khối đệm phần 2 của Message 3 được khuyến nghị.

  • Có thể không có không gian, hoặc chỉ có một lượng nhỏ không gian, có sẵn cho các khối I2NP, tùy thuộc vào MTU và kích thước Router Info. KHÔNG bao gồm các khối I2NP nếu Router Info bị phân mảnh. Cách triển khai đơn giản nhất có thể là không bao giờ bao gồm các khối I2NP trong thông điệp Session Confirmed, và gửi tất cả các khối I2NP trong các thông điệp Data tiếp theo. Xem phần khối Router Info bên dưới để biết kích thước khối tối đa.

Session Confirmed Fragmentation

Thông báo Session Confirmed phải chứa Router Info đã ký đầy đủ từ Alice để Bob có thể thực hiện một số kiểm tra bắt buộc:

  • Khóa tĩnh “s” trong RI khớp với khóa tĩnh trong handshake
  • Khóa giới thiệu “i” trong RI phải được trích xuất và hợp lệ, để sử dụng trong giai đoạn dữ liệu
  • Chữ ký RI hợp lệ

Thật không may, Router Info, ngay cả khi được nén gzip trong khối RI, có thể vượt quá MTU. Do đó, Session Confirmed có thể bị phân mảnh thành hai hoặc nhiều gói tin. Đây là trường hợp DUY NHẤT trong giao thức SSU2 mà payload được bảo vệ AEAD bị phân mảnh thành hai hoặe nhiều gói tin.

Các header cho mỗi packet được xây dựng như sau:

  • TẤT CẢ các header đều là short headers với cùng packet number 0
  • TẤT CẢ các header đều chứa trường “frag”, với số thứ tự fragment và tổng số fragments
  • Header không mã hóa của fragment 0 là associated data (AD) cho thông điệp “jumbo”
  • Mỗi header được mã hóa sử dụng 24 byte cuối cùng của dữ liệu trong packet ĐÓ

Xây dựng chuỗi các gói tin như sau:

  • Tạo một khối RI duy nhất (fragment 0 trong số 1 trong trường frag của khối RI). Chúng ta không sử dụng phân mảnh khối RI, điều đó dành cho một phương pháp thay thế để giải quyết cùng một vấn đề.
  • Tạo một payload “jumbo” với khối RI và bất kỳ khối nào khác cần được bao gồm
  • Tính toán tổng kích thước dữ liệu (không bao gồm header), đó là kích thước payload + 64 bytes cho static key và hai MAC
  • Tính toán không gian khả dụng trong mỗi packet, đó là MTU trừ đi IP header (20 hoặc 40), trừ đi UDP header (8), trừ đi SSU2 short header (16). Tổng overhead mỗi packet là 44 (IPv4) hoặc 64 (IPv6).
  • Tính toán số lượng packet.
  • Tính toán kích thước dữ liệu trong packet cuối cùng. Nó phải lớn hơn hoặc bằng 24 bytes, để mã hóa header có thể hoạt động. Nếu nó quá nhỏ, hoặc thêm một khối padding, HOẶC tăng kích thước của khối padding nếu đã có sẵn, HOẶC giảm kích thước của một trong các packet khác để packet cuối cùng đủ lớn.
  • Tạo header chưa mã hóa cho packet đầu tiên, với tổng số fragment trong trường frag, và mã hóa “jumbo” payload bằng Noise, sử dụng header làm AD, như thường lệ.
  • Chia nhỏ jumbo packet đã mã hóa thành các fragment
  • Thêm header chưa mã hóa cho mỗi fragment 1-n
  • Mã hóa header cho mỗi fragment 0-n. Mỗi header sử dụng CÙNG k_header_1 và k_header_2 như được định nghĩa ở trên trong Session Confirmed KDF.
  • Truyền tất cả các fragment

Quá trình tái lắp ráp:

Khi Bob nhận được bất kỳ thông điệp Session Confirmed nào, anh ta giải mã header, kiểm tra trường frag, và xác định rằng Session Confirmed đã được phân mảnh. Anh ta không (và không thể) giải mã thông điệp cho đến khi tất cả các mảnh được nhận và tái lắp ráp.

  • Giữ nguyên header cho fragment 0, vì nó được sử dụng làm Noise AD
  • Loại bỏ các header của các fragment khác trước khi reassembly
  • Reassemble “jumbo” payload, với header của fragment 0 làm AD, và decrypt bằng Noise
  • Validate RI block như thường lệ
  • Tiến hành đến data phase và gửi ACK 0, như thường lệ

Không có cơ chế để Bob ack từng fragment riêng lẻ. Khi Bob nhận được tất cả các fragment, tái lắp ráp, giải mã và xác thực nội dung, Bob thực hiện split() như thường lệ, vào giai đoạn dữ liệu và gửi ACK của packet số 0.

Nếu Alice không nhận được ACK của gói tin số 0, cô ấy phải truyền lại tất cả các gói tin session confirmed như cũ.

Ví dụ:

Đối với MTU 1500 qua IPv6, payload tối đa là 1372, overhead của khối RI là 5, kích thước dữ liệu RI tối đa (nén gzip) là 1367 (giả định không có khối nào khác). Với hai gói tin, overhead của gói tin thứ 2 là 64, nên nó có thể chứa thêm 1436 byte payload. Vậy hai gói tin là đủ cho một RI nén lên đến 2803 byte.

RI nén lớn nhất được thấy trong mạng hiện tại khoảng 1400 byte; do đó, trong thực tế, hai fragment sẽ đủ, ngay cả với MTU tối thiểu 1280. Giao thức cho phép tối đa 15 fragment.

Phân tích bảo mật:

Tính toàn vẹn và bảo mật của một Session Confirmed bị phân mảnh giống như của một Session Confirmed không bị phân mảnh. Bất kỳ thay đổi nào đối với bất kỳ fragment nào sẽ khiến Noise AEAD thất bại sau khi tái lắp ráp. Các header của các fragment sau fragment 0 chỉ được sử dụng để xác định fragment. Ngay cả khi một kẻ tấn công trên đường truyền có khóa k_header_2 được sử dụng để mã hóa header (không chắc, được tạo ra từ handshake), điều này sẽ không cho phép kẻ tấn công thay thế một fragment hợp lệ.

KDF for data phase

Giai đoạn dữ liệu sử dụng header cho dữ liệu liên kết.

KDF tạo ra hai cipher key k_ab và k_ba từ chaining key ck, sử dụng HMAC-SHA256(key, data) như được định nghĩa trong RFC 2104. Đây là hàm split(), chính xác như được định nghĩa trong đặc tả Noise.

// split()
  // chainKey = from handshake phase
  keydata = HKDF(chainKey, ZEROLEN, "", 64)
  k_ab = keydata[0:31]
  k_ba = keydata[32:63]

  // key is k_ab for Alice to Bob
  // key is k_ba for Bob to Alice

  keydata = HKDF(key, ZEROLEN, "HKDFSSU2DataKeys", 64)
  k_data = keydata[0:31]
  k_header_2 = keydata[32:63]


  // AEAD parameters
  k = k_data
  n = 4 byte packet number from header
  ad = 16 byte header, before header encryption
  ciphertext = ENCRYPT(k, n, payload, ad)

  // Header encryption keys for data phase
  // aik = Alice's intro key
  // bik = Bob's intro key
  k_header_1 = Receiver's intro key (aik or bik)
  k_header_2: from above

Data Message (Type 6)

Noise payload: Tất cả các loại block đều được phép. Kích thước payload tối đa: MTU - 60 (IPv4) hoặc MTU - 80 (IPv6). Đối với MTU 1500: Payload tối đa là 1440 (IPv4) hoặc 1420 (IPv6).

Bắt đầu từ phần thứ 2 của Session Confirmed, tất cả các thông điệp đều nằm trong một payload ChaChaPoly được xác thực và mã hóa. Tất cả padding đều nằm bên trong thông điệp. Bên trong payload là một định dạng tiêu chuẩn với không hoặc nhiều “block”. Mỗi block có một loại một byte và độ dài hai byte. Các loại bao gồm date/time, I2NP message, options, termination và padding.

Lưu ý: Bob có thể, nhưng không bắt buộc, gửi RouterInfo của mình cho Alice như là thông điệp đầu tiên gửi đến Alice trong giai đoạn dữ liệu.

Thuộc Tính Bảo Mật Payload:

XK(s, rs):           Authentication   Confidentiality
    <-                        2                5
    ->                        2                5

    Authentication: 2.
    Sender authentication resistant to key-compromise impersonation (KCI).
    The sender authentication is based on an ephemeral-static DH ("es" or "se")
    between the sender's static key pair and the recipient's ephemeral key pair.
    Assuming the corresponding private keys are secure, this authentication cannot be forged.

    Confidentiality: 5.
    Encryption to a known recipient, strong forward secrecy.
    This payload is encrypted based on an ephemeral-ephemeral DH as well as
    an ephemeral-static DH with the recipient's static key pair.
    Assuming the ephemeral private keys are secure, and the recipient is not being actively impersonated
    by an attacker that has stolen its static private key, this payload cannot be decrypted.

Notes

  • Router phải loại bỏ thông điệp có lỗi AEAD.
+----+----+----+----+----+----+----+----+
  |  Short Header 16 bytes, ChaCha20      |
  +  encrypted with intro key and         +
  |  derived key, see Data Phase KDF      |
  +----+----+----+----+----+----+----+----+
  |   ChaCha20 data                       |
  +   Encrypted and authenticated data    +
  |  length varies                        |
  +  k defined in Data Phase KDF          +
  |  n = packet number from header        |
  +                                       +
  |                                       |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +        Poly1305 MAC (16 bytes)        +
  |                                       |
  +----+----+----+----+----+----+----+----+

Dữ liệu không được mã hóa (không hiển thị auth tag Poly1305):

+----+----+----+----+----+----+----+----+
  |      Destination Connection ID        |
  +----+----+----+----+----+----+----+----+
  |   Packet Number   |type|    flags     |
  +----+----+----+----+----+----+----+----+
  |     Noise payload (block data)        |
  +          (length varies)              +
  |                                       |
  +----+----+----+----+----+----+----+----+

  Destination Connection ID :: As specified in session setup

  Packet Number :: 4 byte big endian integer

  type :: 6

  flags :: 3 bytes, unused, set to 0 for future compatibility

Notes

  • Kích thước payload tối thiểu là 8 byte. Yêu cầu này sẽ được đáp ứng bởi bất kỳ block ACK, I2NP, First Fragment, hoặc Follow-on Fragment nào. Nếu yêu cầu không được đáp ứng, một block Padding phải được bao gồm.

  • Mỗi số gói tin chỉ được sử dụng một lần. Khi truyền lại các thông điệp I2NP hoặc các phần đoạn, phải sử dụng một số gói tin mới.

KDF for Peer Test


// AEAD parameters
  // bik = Bob's intro key
  k = bik
  n = 4 byte packet number from header
  ad = 32 byte header, before header encryption
  ciphertext = ENCRYPT(k, n, payload, ad)

  // Header encryption keys for this message
  k_header_1 = bik
  k_header_2 = bik

Peer Test (Type 7)

Charlie gửi đến Alice, và Alice gửi đến Charlie, chỉ cho các giai đoạn 5-7 của Peer Test. Các giai đoạn 1-4 của Peer Test phải được gửi trong phiên bằng cách sử dụng khối Peer Test trong thông điệp Data. Xem các phần Peer Test Block và Peer Test Process bên dưới để biết thêm thông tin.

Kích thước: 48 + kích thước payload.

Noise payload: Xem bên dưới.

Nội dung thô:

+----+----+----+----+----+----+----+----+
  |  Long Header bytes 0-15, ChaCha20     |
  +  encrypted with Alice or Charlie      +
  |  intro key                            |
  +----+----+----+----+----+----+----+----+
  |  Long Header bytes 16-31, ChaCha20    |
  +  encrypted with Alice or Charlie      +
  |  intro key                            |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +                                       +
  |   ChaCha20 encrypted data             |
  +          (length varies)              +
  |                                       |
  +  see KDF for key and n                +
  |  see KDF for associated data          |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +        Poly1305 MAC (16 bytes)        +
  |                                       |
  +----+----+----+----+----+----+----+----+

Dữ liệu không mã hóa (thẻ xác thực Poly1305 không được hiển thị):

+----+----+----+----+----+----+----+----+
  |      Destination Connection ID        |
  +----+----+----+----+----+----+----+----+
  |   Packet Number   |type| ver| id |flag|
  +----+----+----+----+----+----+----+----+
  |        Source Connection ID           |
  +----+----+----+----+----+----+----+----+
  |                 Token                 |
  +----+----+----+----+----+----+----+----+
  |    ChaCha20 payload (block data)      |
  +          (length varies)              +
  |    see below for allowed blocks       |
  +----+----+----+----+----+----+----+----+


  Destination Connection ID :: See below

  type :: 7

  ver :: 2

  id :: 1 byte, the network ID (currently 2, except for test networks)

  flag :: 1 byte, unused, set to 0 for future compatibility

  Packet Number :: Random number generated by Alice or Charlie

  Source Connection ID :: See below

  Token :: Randomly generated by Alice or Charlie, ignored

Header Dài

  • Khối DateTime
  • Khối Address (bắt buộc cho các thông điệp 6 và 7, xem ghi chú bên dưới)
  • Khối Peer Test
  • Khối Padding (tùy chọn)

Kích thước payload tối thiểu là 8 byte. Vì khối Peer Test có tổng cộng nhiều hơn thế, yêu cầu này được đáp ứng chỉ với khối này.

Trong các thông điệp 5 và 7, khối Peer Test có thể giống hệt với khối từ các thông điệp trong phiên 3 và 4, chứa thỏa thuận được ký bởi Charlie, hoặc có thể được tạo lại. Chữ ký là tùy chọn.

Trong thông điệp 6, khối Peer Test có thể giống hệt với khối từ các thông điệp trong phiên 1 và 2, chứa yêu cầu được ký bởi Alice, hoặc có thể được tạo lại. Chữ ký là tùy chọn.

Connection ID: Hai connection ID được tạo ra từ test nonce. Đối với các thông điệp 5 và 7 được gửi từ Charlie đến Alice, Destination Connection ID là hai bản sao của 4-byte big-endian test nonce, tức là ((nonce « 32) | nonce). Source Connection ID là nghịch đảo của Destination Connection ID, tức là ~((nonce « 32) | nonce). Đối với thông điệp 6 được gửi từ Alice đến Charlie, hoán đổi hai connection ID này.

Nội dung khối địa chỉ:

  • Trong thông điệp 5: Không bắt buộc.
  • Trong thông điệp 6: IP và port của Charlie được chọn từ RI của Charlie.
  • Trong thông điệp 7: IP và port thực tế của Alice mà thông điệp 6 được nhận từ đó.

KDF for Retry

Yêu cầu đối với thông điệp Retry là Bob không bắt buộc phải giải mã thông điệp Session Request để tạo ra thông điệp Retry để phản hồi. Ngoài ra, thông điệp này phải được tạo ra nhanh chóng, chỉ sử dụng mã hóa đối xứng.


// AEAD parameters
  // bik = Bob's intro key
  k = bik
  n = 4 byte packet number from header
  ad = 32 byte header, before header encryption
  ciphertext = ENCRYPT(k, n, payload, ad)

  // Header encryption keys for this message
  k_header_1 = bik
  k_header_2 = bik

Retry (Type 9)

Bob gửi cho Alice, để phản hồi thông điệp Session Request hoặc Token Request. Alice phản hồi bằng một Session Request mới. Kích thước: 48 + kích thước payload.

Cũng đóng vai trò là thông điệp Termination (tức là “Không Thử Lại”) nếu có bao gồm khối Termination.

Noise payload: Xem bên dưới.

Nội dung thô:

+----+----+----+----+----+----+----+----+
  |  Long Header bytes 0-15, ChaCha20     |
  +  encrypted with Bob intro key         +
  |                                       |
  +----+----+----+----+----+----+----+----+
  |  Long Header bytes 16-31, ChaCha20    |
  +  encrypted with Bob intro key         +
  |                                       |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +                                       +
  |   ChaCha20 encrypted data             |
  +          (length varies)              +
  |                                       |
  +  see KDF for key and n                +
  |  see KDF for associated data          |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +        Poly1305 MAC (16 bytes)        +
  |                                       |
  +----+----+----+----+----+----+----+----+

Dữ liệu không được mã hóa (thẻ xác thực Poly1305 không được hiển thị):

+----+----+----+----+----+----+----+----+
  |      Destination Connection ID        |
  +----+----+----+----+----+----+----+----+
  |   Packet Number   |type| ver| id |flag|
  +----+----+----+----+----+----+----+----+
  |        Source Connection ID           |
  +----+----+----+----+----+----+----+----+
  |                 Token                 |
  +----+----+----+----+----+----+----+----+
  |    ChaCha20 payload (block data)      |
  +          (length varies)              +
  |    see below for allowed blocks       |
  +----+----+----+----+----+----+----+----+


  Destination Connection ID :: The Source Connection ID
                               received from Alice in Token Request
                               or Session Request

  Packet Number :: Random number generated by Bob

  type :: 9

  ver :: 2

  id :: 1 byte, the network ID (currently 2, except for test networks)

  flag :: 1 byte, unused, set to 0 for future compatibility

  Source Connection ID :: The Destination Connection ID
                          received from Alice in Token Request
                          or Session Request

  Token :: 8 byte unsigned integer, randomly generated by Bob, nonzero,
           or zero if session is rejected and a termination block is included

Tiêu đề Ngắn

  • Khối DateTime
  • Khối Address
  • Khối Options (tùy chọn)
  • Khối Termination (tùy chọn, nếu phiên bị từ chối)
  • Khối Padding (tùy chọn)

Kích thước payload tối thiểu là 8 byte. Vì các khối DateTime và Address tổng cộng lớn hơn con số đó, yêu cầu được đáp ứng chỉ với hai khối này.

Đánh số Connection ID

  • Để cung cấp khả năng chống thăm dò, một router không nên gửi thông điệp Retry để đáp ứng thông điệp Session Request hoặc Token Request trừ khi loại thông điệp, phiên bản giao thức và các trường network ID trong thông điệp Request đều hợp lệ.

  • Để hạn chế mức độ của bất kỳ cuộc tấn công khuếch đại nào có thể được thực hiện bằng cách sử dụng địa chỉ nguồn giả mạo, thông điệp Retry không được chứa lượng lớn padding. Khuyến nghị rằng thông điệp Retry không lớn hơn ba lần kích thước của thông điệp mà nó đang phản hồi. Thay vào đó, sử dụng một phương pháp đơn giản như thêm một lượng padding ngẫu nhiên trong khoảng 1-64 byte.

KDF for Token Request

Thông điệp này phải được tạo ra nhanh chóng, chỉ sử dụng mã hóa đối xứng.


// AEAD parameters
  // bik = Bob's intro key
  k = bik
  n = 4 byte packet number from header
  ad = 32 byte header, before header encryption
  ciphertext = ENCRYPT(k, n, payload, ad)

  // Header encryption keys for this message
  k_header_1 = bik
  k_header_2 = bik

Token Request (Type 10)

Alice gửi cho Bob. Bob phản hồi bằng thông điệp Retry. Kích thước: 48 + kích thước payload.

Nếu Alice không có token hợp lệ, Alice nên gửi thông điệp này thay vì Session Request, để tránh chi phí mã hóa bất đối xứng khi tạo Session Request.

Noise payload: Xem bên dưới.

Nội dung thô:

+----+----+----+----+----+----+----+----+
  |  Long Header bytes 0-15, ChaCha20     |
  +  encrypted with Bob intro key         +
  |                                       |
  +----+----+----+----+----+----+----+----+
  |  Long Header bytes 16-31, ChaCha20    |
  +  encrypted with Bob intro key         +
  |                                       |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +                                       +
  |   ChaCha20 encrypted data             |
  +          (length varies)              +
  |                                       |
  +  see KDF for key and n                +
  |  see KDF for associated data          |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +        Poly1305 MAC (16 bytes)        +
  |                                       |
  +----+----+----+----+----+----+----+----+

Dữ liệu không mã hóa (thẻ xác thực Poly1305 không được hiển thị):

+----+----+----+----+----+----+----+----+
  |      Destination Connection ID        |
  +----+----+----+----+----+----+----+----+
  |   Packet Number   |type| ver| id |flag|
  +----+----+----+----+----+----+----+----+
  |        Source Connection ID           |
  +----+----+----+----+----+----+----+----+
  |                 Token                 |
  +----+----+----+----+----+----+----+----+
  |    ChaCha20 payload (block data)      |
  +          (length varies)              +
  |    see below for allowed blocks       |
  +----+----+----+----+----+----+----+----+


  Destination Connection ID :: Randomly generated by Alice

  Packet Number :: Random number generated by Alice

  type :: 10

  ver :: 2

  id :: 1 byte, the network ID (currently 2, except for test networks)

  flag :: 1 byte, unused, set to 0 for future compatibility

  Source Connection ID :: Randomly generated by Alice,
                          must not be equal to Destination Connection ID

  Token :: zero

Đánh Số Gói Tin

  • Khối DateTime
  • Khối Padding

Kích thước payload tối thiểu là 8 byte.

Ràng Buộc Header

  • Để cung cấp khả năng chống thăm dò, một router không nên gửi thông báo Retry để phản hồi thông báo Token Request trừ khi các trường loại thông báo, phiên bản giao thức và ID mạng trong thông báo Token Request là hợp lệ.

  • Đây KHÔNG phải là thông điệp Noise tiêu chuẩn và không phải là một phần của quá trình handshake. Nó không được liên kết với thông điệp Session Request ngoại trừ thông qua các connection ID.

  • Đối với hầu hết các lỗi, bao gồm AEAD, hoặc replay rõ ràng Bob nên dừng việc xử lý tin nhắn tiếp theo và loại bỏ tin nhắn mà không phản hồi.

  • Bob phải từ chối các kết nối mà giá trị timestamp quá xa so với thời gian hiện tại. Gọi delta thời gian tối đa là “D”. Bob phải duy trì một bộ nhớ đệm cục bộ của các giá trị handshake đã sử dụng trước đó và từ chối các giá trị trùng lặp, để ngăn chặn các cuộc tấn công replay. Các giá trị trong bộ nhớ đệm phải có thời gian tồn tại ít nhất 2*D. Các giá trị bộ nhớ đệm phụ thuộc vào cách triển khai, tuy nhiên có thể sử dụng giá trị X 32-byte (hoặc tương đương đã mã hóa của nó).

  • Bob CÓ THỂ gửi một thông điệp Retry chứa một token bằng không và một khối Termination với một mã lý do clock skew nếu timestamp trong khối DateTime bị lệch quá xa.

  • Kích thước tối thiểu: TBD, cùng quy tắc như Session Created?

KDF for Hole Punch

Thông điệp này phải được tạo ra nhanh chóng, chỉ sử dụng mã hóa đối xứng.


// AEAD parameters
  // aik = Alice's intro key
  k = aik
  n = 4 byte packet number from header
  ad = 32 byte header, before header encryption
  ciphertext = ENCRYPT(k, n, payload, ad)

  // Header encryption keys for this message
  k_header_1 = aik
  k_header_2 = aik

Hole Punch (Type 11)

Charlie gửi đến Alice, để phản hồi một Relay Intro đã nhận từ Bob. Alice phản hồi bằng một Session Request mới. Kích thước: 48 + kích thước payload.

Noise payload: Xem bên dưới.

Nội dung thô:

+----+----+----+----+----+----+----+----+
  |  Long Header bytes 0-15, ChaCha20     |
  +  encrypted with Alice intro key       +
  |                                       |
  +----+----+----+----+----+----+----+----+
  |  Long Header bytes 16-31, ChaCha20    |
  +  encrypted with Alice intro key       +
  |                                       |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +                                       +
  |   ChaCha20 encrypted data             |
  +          (length varies)              +
  |                                       |
  +  see KDF for key and n                +
  |  see KDF for associated data          |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +        Poly1305 MAC (16 bytes)        +
  |                                       |
  +----+----+----+----+----+----+----+----+

Dữ liệu không mã hóa (thẻ xác thực Poly1305 không được hiển thị):

+----+----+----+----+----+----+----+----+
  |      Destination Connection ID        |
  +----+----+----+----+----+----+----+----+
  |   Packet Number   |type| ver| id |flag|
  +----+----+----+----+----+----+----+----+
  |        Source Connection ID           |
  +----+----+----+----+----+----+----+----+
  |                 Token                 |
  +----+----+----+----+----+----+----+----+
  |    ChaCha20 payload (block data)      |
  +          (length varies)              +
  |    see below for allowed blocks       |
  +----+----+----+----+----+----+----+----+


  Destination Connection ID :: See below

  Packet Number :: Random number generated by Charlie

  type :: 11

  ver :: 2

  id :: 1 byte, the network ID (currently 2, except for test networks)

  flag :: 1 byte, unused, set to 0 for future compatibility

  Source Connection ID :: See below

  Token :: 8 byte unsigned integer, randomly generated by Charlie, nonzero.

Mã hóa Header

  • Khối DateTime
  • Khối Address
  • Khối Relay Response
  • Khối Padding (tùy chọn)

Kích thước payload tối thiểu là 8 byte. Vì các khối DateTime và Address tổng cộng lớn hơn con số đó, yêu cầu được đáp ứng chỉ với hai khối này.

Connection ID: Hai connection ID được tạo ra từ relay nonce. Destination Connection ID là hai bản sao của relay nonce 4-byte big-endian, tức là ((nonce « 32) | nonce). Source Connection ID là nghịch đảo của Destination Connection ID, tức là ~((nonce « 32) | nonce).

Alice nên bỏ qua token trong header. Token được sử dụng trong Session Request nằm trong khối Relay Response.

Noise Payload

Mỗi Noise payload chứa không hoặc nhiều “blocks”.

Điều này sử dụng cùng định dạng block như đã định nghĩa trong các đặc tả NTCP2ECIES. Các loại block riêng lẻ được định nghĩa khác nhau. Thuật ngữ tương đương trong QUIC RFC 9000 là “frames”.

Có những lo ngại rằng việc khuyến khích các nhà phát triển chia sẻ code có thể dẫn đến các vấn đề phân tích cú pháp. Các nhà phát triển nên cân nhắc cẩn thận lợi ích và rủi ro của việc chia sẻ code, và đảm bảo rằng thứ tự và quy tắc block hợp lệ là khác nhau cho hai ngữ cảnh này.

Các Cân nhắc về Bảo mật

Có một hoặc nhiều khối trong tải trọng được mã hóa. Một khối có định dạng Tag-Length-Value (TLV) đơn giản. Mỗi khối chứa một định danh một byte, một độ dài hai byte, và không hoặc nhiều byte dữ liệu. Định dạng này giống hệt với định dạng trong NTCP2ECIES, tuy nhiên các định nghĩa khối thì khác nhau.

Để có tính mở rộng, các receiver phải bỏ qua các block có định danh không xác định và coi chúng như padding.

(Thẻ xác thực Poly1305 không được hiển thị):

+----+----+----+----+----+----+----+----+
  |blk |  size   |       data             |
  +----+----+----+                        +
  |                                       |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+
  |blk |  size   |       data             |
  +----+----+----+                        +
  |                                       |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+
  ~               .   .   .               ~

  blk :: 1 byte, see below
  size :: 2 bytes, big endian, size of data to follow, 0 - TBD
  data :: the data

Mã hóa header sử dụng 24 byte cuối cùng của gói tin làm IV cho hai phép toán ChaCha20. Vì tất cả các gói tin đều kết thúc bằng MAC 16 byte, điều này yêu cầu tất cả payload của gói tin phải có tối thiểu 8 byte. Nếu payload không đáp ứng yêu cầu này, một khối Padding phải được bao gồm.

Tải trọng ChaChaPoly tối đa thay đổi dựa trên loại thông điệp, MTU, và loại địa chỉ IPv4 hoặc IPv6. Tải trọng tối đa là MTU - 60 đối với IPv4 và MTU - 80 đối với IPv6. Dữ liệu tải trọng tối đa là MTU - 63 đối với IPv4 và MTU - 83 đối với IPv6. Giới hạn trên khoảng 1440 byte đối với IPv4, MTU 1500, thông điệp Data. Kích thước khối tổng tối đa là kích thước tải trọng tối đa. Kích thước khối đơn tối đa là kích thước khối tổng tối đa. Loại khối là 1 byte. Độ dài khối là 2 byte. Kích thước dữ liệu khối đơn tối đa là kích thước khối đơn tối đa trừ đi 3.

Ghi chú:

  • Các nhà phát triển phải đảm bảo rằng khi đọc một block, dữ liệu bị lỗi hoặc độc hại sẽ không gây ra việc đọc vượt quá block tiếp theo hoặc ra ngoài ranh giới payload.

  • Các triển khai nên bỏ qua các loại block không xác định để tương thích tiến về phía trước.

Các loại block:

Payload Block TypeType NumberBlock Length
DateTime07
Options115+
Router Info2varies
I2NP Message3varies
First Fragment4varies
Follow-on Fragment5varies
Termination69 typ.
Relay Request7varies
Relay Response8varies
Relay Intro9varies
Peer Test10varies
Next Nonce11TBD
ACK12varies
Address139 or 21
reserved14
Relay Tag Request153
Relay Tag167
New Token1715
Path Challenge18varies
Path Response19varies
First Packet Number207
Congestion214
reserved for experimental features224-253
Padding254varies
reserved for future extension255

Block Ordering Rules

Trong Session Confirmed, Router Info phải là block đầu tiên.

Trong tất cả các thông điệp khác, thứ tự không được chỉ định, ngoại trừ các yêu cầu sau: Padding, nếu có, phải là khối cuối cùng. Termination, nếu có, phải là khối cuối cùng ngoại trừ Padding. Không được phép có nhiều khối Padding trong một payload duy nhất.

Block Specifications

Header Encryption KDF

Để đồng bộ thời gian:

+----+----+----+----+----+----+----+
  | 0  |    4    |     timestamp     |
  +----+----+----+----+----+----+----+

  blk :: 0
  size :: 2 bytes, big endian, value = 4
  timestamp :: Unix timestamp, unsigned seconds.
               Wraps around in 2106

Ghi chú:

  • Không giống như trong SSU 1, không có timestamp trong packet header cho data phase trong SSU 2.
  • Các implementation nên định kỳ gửi DateTime blocks trong data phase.
  • Các implementation phải làm tròn đến giây gần nhất để ngăn clock bias trong mạng.

Xác thực Header

Truyền các tùy chọn đã cập nhật. Các tùy chọn bao gồm: Padding tối thiểu và tối đa.

Khối options sẽ có độ dài thay đổi.

+----+----+----+----+----+----+----+----+
  | 1  |  size   |tmin|tmax|rmin|rmax|tdmy|
  +----+----+----+----+----+----+----+----+
  |tdmy|  rdmy   |  tdelay |  rdelay |    |
  ~----+----+----+----+----+----+----+    ~
  |              more_options             |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+

  blk :: 1
  size :: 2 bytes, big endian, size of options to follow, 12 bytes minimum

  tmin, tmax, rmin, rmax :: requested padding limits
      tmin and rmin are for desired resistance to traffic analysis.
      tmax and rmax are for bandwidth limits.
      tmin and tmax are the transmit limits for the router sending this options block.
      rmin and rmax are the receive limits for the router sending this options block.
      Each is a 4.4 fixed-point float representing 0 to 15.9375
      (or think of it as an unsigned 8-bit integer divided by 16.0).
      This is the ratio of padding to data. Examples:
      Value of 0x00 means no padding
      Value of 0x01 means add 6 percent padding
      Value of 0x10 means add 100 percent padding
      Value of 0x80 means add 800 percent (8x) padding
      Alice and Bob will negotiate the minimum and maximum in each direction.
      These are guidelines, there is no enforcement.
      Sender should honor receiver's maximum.
      Sender may or may not honor receiver's minimum, within bandwidth constraints.

  tdmy: Max dummy traffic willing to send, 2 bytes big endian, bytes/sec average
  rdmy: Requested dummy traffic, 2 bytes big endian, bytes/sec average
  tdelay: Max intra-message delay willing to insert, 2 bytes big endian, msec average
  rdelay: Requested intra-message delay, 2 bytes big endian, msec average

  Padding distribution specified as additional parameters?
  Random delay specified as additional parameters?

  more_options :: Format TBD

Vấn đề về Tùy chọn:

  • Đàm phán tùy chọn vẫn đang được xác định.

RouterInfo

Truyền RouterInfo của Alice cho Bob. Chỉ được sử dụng trong phần payload của Session Confirmed part 2. Không được sử dụng trong giai đoạn data; thay vào đó hãy sử dụng I2NP DatabaseStore Message.

Kích thước tối thiểu: khoảng 420 byte, trừ khi danh tính router và chữ ký trong thông tin router có thể nén được, điều này không có khả năng xảy ra.

LƯU Ý: Khối Router Info không bao giờ bị phân mảnh. Trường frag luôn là 0/1. Xem phần Session Confirmed Fragmentation ở trên để biết thêm thông tin.

+----+----+----+----+----+----+----+----+
  | 2  |  size   |flag|frag|              |
  +----+----+----+----+----+              +
  |                                       |
  +       Router Info fragment            +
  | (Alice RI in Session Confirmed)       |
  + (Alice, Bob, or third-party           +
  |  RI in data phase)                    |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+

  blk :: 2
  size :: 2 bytes, big endian, 2 + fragment size
  flag :: 1 byte flags
         bit order: 76543210 (bit 7 is MSB)
         bit 0: 0 for local store, 1 for flood request
         bit 1: 0 for uncompressed, 1 for gzip compressed
         bits 7-2: Unused, set to 0 for future compatibility
  frag :: 1 byte fragment info:
         bit order: 76543210 (bit 7 is MSB)
         bits 7-4: fragment number, always 0
         bits 3-0: total fragments, always 1, big endian

  routerinfo :: Alice's or Bob's RouterInfo

Ghi chú:

  • Router Info có thể được nén bằng gzip (tùy chọn), như được chỉ định bởi flag bit 1. Điều này khác với NTCP2, nơi nó không bao giờ được nén, và khác với DatabaseStore Message, nơi nó luôn được nén. Nén là tùy chọn vì thường ít có lợi ích đối với các Router Info nhỏ, nơi có ít nội dung có thể nén, nhưng rất có lợi cho các Router Info lớn với nhiều Router Address có thể nén được. Nén được khuyến nghị nếu nó cho phép một Router Info vừa vặn trong một Session Confirmed packet duy nhất mà không cần phân mảnh.

  • Kích thước tối đa của fragment đầu tiên hoặc duy nhất trong thông điệp Session Confirmed: MTU - 113 cho IPv4 hoặc MTU - 133 cho IPv6. Giả sử MTU mặc định 1500 byte và không có khối nào khác trong thông điệp, 1387 cho IPv4 hoặc 1367 cho IPv6. 97% các router info hiện tại có kích thước nhỏ hơn 1367 mà không cần nén gzip. 99.9% các router info hiện tại có kích thước nhỏ hơn 1367 khi được nén gzip. Giả sử MTU tối thiểu 1280 byte và không có khối nào khác trong thông điệp, 1167 cho IPv4 hoặc 1147 cho IPv6. 94% các router info hiện tại có kích thước nhỏ hơn 1147 mà không cần nén gzip. 97% các router info hiện tại có kích thước nhỏ hơn 1147 khi được nén gzip.

  • Byte frag hiện tại không được sử dụng, khối Router Info không bao giờ bị phân mảnh. Byte frag phải được đặt thành fragment 0, tổng số fragment là 1. Xem phần Session Confirmed Fragmentation ở trên để biết thêm thông tin.

  • Flooding không được yêu cầu trừ khi có các RouterAddresses đã được công bố trong RouterInfo. Router nhận phải không flood RouterInfo trừ khi có các RouterAddresses đã được công bố trong đó.

  • Giao thức này không cung cấp xác nhận rằng RouterInfo đã được lưu trữ hoặc flood. Nếu muốn có xác nhận, và bên nhận là floodfill, bên gửi nên gửi một I2NP DatabaseStoreMessage tiêu chuẩn với reply token.

I2NP Message

Một thông điệp I2NP hoàn chỉnh với header đã được chỉnh sửa.

Cách này sử dụng cùng 9 byte cho header I2NP như trong NTCP2 (type, message id, short expiration).

+----+----+----+----+----+----+----+----+
  | 3  |  size   |type|    msg id         |
  +----+----+----+----+----+----+----+----+
  |   short exp       |     message       |
  +----+----+----+----+                   +
  |                                       |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+

  blk :: 3
  size :: 2 bytes, big endian, size of type + msg id + exp + message to follow
          I2NP message body size is (size - 9).
  type :: 1 byte, I2NP msg type, see I2NP spec
  msg id :: 4 bytes, big endian, I2NP message ID
  short exp :: 4 bytes, big endian, I2NP message expiration, Unix timestamp, unsigned seconds.
               Wraps around in 2106
  message :: I2NP message body

Ghi chú:

  • Đây là cùng định dạng header I2NP 9-byte được sử dụng trong NTCP2.

  • Đây là định dạng hoàn toàn giống với khối First Fragment, nhưng loại khối cho biết rằng đây là một thông điệp hoàn chỉnh.

  • Kích thước tối đa bao gồm header I2NP 9-byte là MTU - 63 cho IPv4 và MTU - 83 cho IPv6.

ChaCha20/Poly1305

Fragment đầu tiên (fragment #0) của một thông điệp I2NP với header đã được sửa đổi.

Cái này sử dụng cùng 9 byte cho header I2NP như trong NTCP2 (type, message id, short expiration).

Tổng số fragment không được chỉ định.

+----+----+----+----+----+----+----+----+
  | 4  |  size   |type|    msg id         |
  +----+----+----+----+----+----+----+----+
  |   short exp       |                   |
  +----+----+----+----+                   +
  |          partial message              |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+

  blk :: 4
  size :: 2 bytes, big endian, size of data to follow
          Fragment size is (size - 9).
  type :: 1 byte, I2NP msg type, see I2NP spec
  msg id :: 4 bytes, big endian, I2NP message ID
  short exp :: 4 bytes, big endian, I2NP message expiration, Unix timestamp, unsigned seconds.
               Wraps around in 2106
  message :: Partial I2NP message body, bytes 0 - (size - 10)

Ghi chú:

  • Đây là cùng định dạng header I2NP 9-byte được sử dụng trong NTCP2.

  • Đây chính xác là cùng định dạng với khối I2NP Message, nhưng loại khối cho biết rằng đây là đoạn đầu tiên của một thông điệp.

  • Độ dài thông điệp một phần phải lớn hơn không.

  • Như trong SSU 1, được khuyến nghị gửi fragment cuối cùng trước, để bên nhận biết tổng số fragment và có thể phân bổ buffer nhận một cách hiệu quả.

  • Kích thước tối đa bao gồm header I2NP 9-byte là MTU - 63 cho IPv4 và MTU - 83 cho IPv6.

Ghi chú

Một fragment bổ sung (số fragment lớn hơn không) của một thông điệp I2NP.

+----+----+----+----+----+----+----+----+
  | 5  |  size   |frag|    msg id         |
  +----+----+----+----+----+----+----+----+
  |                                       |
  +                                       +
  |          partial message              |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+

  blk :: 5
  size :: 2 bytes, big endian, size of data to follow
          Fragment size is (size - 5).
  frag :: Fragment info:
          Bit order: 76543210 (bit 7 is MSB)
          bits 7-1: fragment number 1 - 127 (0 not allowed)
          bit 0: isLast (1 = true)
  msg id :: 4 bytes, big endian, I2NP message ID
  message :: Partial I2NP message body

Ghi chú:

  • Độ dài tin nhắn một phần phải lớn hơn không.

  • Như trong SSU 1, được khuyến nghị gửi fragment cuối cùng trước tiên, để bên nhận biết tổng số fragment và có thể phân bổ buffer nhận một cách hiệu quả.

  • Như trong SSU 1, số fragment tối đa là 127, nhưng giới hạn thực tế là 63 hoặc ít hơn. Các triển khai có thể giới hạn tối đa xuống mức thực tế cho kích thước I2NP message tối đa khoảng 64 KB, tức là khoảng 55 fragment với MTU tối thiểu 1280. Xem phần Max I2NP Message Size bên dưới.

  • Kích thước tin nhắn một phần tối đa (không bao gồm frag và message id) là MTU - 68 đối với IPv4 và MTU - 88 đối với IPv6.

Xử lý Lỗi AEAD

Ngắt kết nối. Đây phải là khối không phải padding cuối cùng trong payload.

+----+----+----+----+----+----+----+----+
  | 6  |  size   |    valid data packets  |
  +----+----+----+----+----+----+----+----+
      received   | rsn|     addl data     |
  +----+----+----+----+                   +
  ~               .   .   .               ~
  +----+----+----+----+----+----+----+----+

  blk :: 6
  size :: 2 bytes, big endian, value = 9 or more
  valid data packets received :: The number of valid packets received
                                (current receive nonce value)
                                0 if error occurs in handshake phase
                                8 bytes, big endian
  rsn :: reason, 1 byte:
         0: normal close or unspecified
         1: termination received
         2: idle timeout
         3: router shutdown
         4: data phase AEAD failure
         5: incompatible options
         6: incompatible signature type
         7: clock skew
         8: padding violation
         9: AEAD framing error
         10: payload format error
         11: Session Request error
         12: Session Created error
         13: Session Confirmed error
         14: Timeout
         15: RI signature verification fail
         16: s parameter missing, invalid, or mismatched in RouterInfo
         17: banned
         18: bad token
         19: connection limits
         20: incompatible version
         21: wrong net ID
         22: replaced by new session
  addl data :: optional, 0 or more bytes, for future expansion, debugging,
               or reason text.
               Format unspecified and may vary based on reason code.

Ghi chú:

  • Không phải tất cả các lý do đều thực sự được sử dụng, phụ thuộc vào implementation. Hầu hết các lỗi thường dẫn đến việc message bị drop chứ không phải termination. Xem ghi chú trong các phần handshake message ở trên. Các lý do bổ sung được liệt kê là để đảm bảo tính nhất quán, logging, debugging, hoặc nếu policy thay đổi.
  • Khuyến nghị nên bao gồm một ACK block cùng với Termination block.
  • Trong data phase, với bất kỳ lý do nào khác ngoài “termination received”, peer nên phản hồi với một termination block có lý do “termination received”.

RelayRequest

Được gửi trong một thông điệp Data trong phiên, từ Alice đến Bob. Xem phần Quy trình Relay bên dưới.

+----+----+----+----+----+----+----+----+
  |  7 |  size   |flag|       nonce       |
  +----+----+----+----+----+----+----+----+
  |     relay tag     |     timestamp     |
  +----+----+----+----+----+----+----+----+
  | ver| asz|AlicePort|  Alice IP address |
  +----+----+----+----+----+----+----+----+
  |              signature                |
  +            length varies              +
  |         64 bytes for Ed25519          |
  ~                                       ~
  |                 . . .                 |
  +----+----+----+----+----+----+----+----+

  blk :: 7
  size :: 2 bytes, big endian, size of data to follow
  flag :: 1 byte flags, Unused, set to 0 for future compatibility

  The data below here is covered
  by the signature, and Bob forwards it unmodified.

  nonce :: 4 bytes, randomly generated by Alice
  relay tag :: 4 bytes, the itag from Charlie's RI
  timestamp :: Unix timestamp, unsigned seconds.
               Wraps around in 2106
  ver ::  1 byte SSU version to be used for the introduction:
         1: SSU 1
         2: SSU 2
  asz :: 1 byte endpoint (port + IP) size (6 or 18)
  AlicePort :: 2 byte Alice's port number, big endian
  Alice IP :: (asz - 2) byte representation of Alice's IP address,
              network byte order
  signature :: length varies, 64 bytes for Ed25519.
               Signature of prologue, Bob's hash,
               and signed data above, as signed by
               Alice.

Ghi chú:

  • Địa chỉ IP luôn được bao gồm (không giống như trong SSU 1) và có thể khác với IP được sử dụng cho phiên làm việc.

Chữ ký:

Alice ký yêu cầu và bao gồm nó trong khối này; Bob chuyển tiếp nó trong khối Relay Intro tới Charlie. Thuật toán chữ ký: Ký dữ liệu sau đây với khóa ký router của Alice:

  • prologue: 16 bytes “RelayRequestData”, không kết thúc bằng null (không bao gồm trong thông điệp)
  • bhash: 32-byte router hash của Bob (không bao gồm trong thông điệp)
  • chash: 32-byte router hash của Charlie (không bao gồm trong thông điệp)
  • nonce: 4 byte nonce
  • relay tag: 4 byte relay tag
  • timestamp: 4 byte timestamp (giây)
  • ver: 1 byte phiên bản SSU
  • asz: 1 byte kích thước endpoint (port + IP) (6 hoặc 18)
  • AlicePort: 2 byte số port của Alice
  • Alice IP: (asz - 2) byte địa chỉ IP của Alice

KDF cho ChainKey Ban đầu

Được gửi trong một thông điệp Data trong phiên, từ Charlie đến Bob hoặc từ Bob đến Alice, VÀ trong thông điệp Hole Punch từ Charlie đến Alice. Xem phần Relay Process bên dưới.

+----+----+----+----+----+----+----+----+
  |  8 |  size   |flag|code|    nonce
  +----+----+----+----+----+----+----+----+
       |     timestamp     | ver| csz|Char
  +----+----+----+----+----+----+----+----+
   Port|   Charlie IP addr |              |
  +----+----+----+----+----+              +
  |              signature                |
  +            length varies              +
  |         64 bytes for Ed25519          |
  ~                                       ~
  |                 . . .                 |
  +----+----+----+----+----+----+----+----+
  |                 Token                 |
  +----+----+----+----+----+----+----+----+

  blk :: 8
  size :: 2 bytes, 6
  flag :: 1 byte flags, Unused, set to 0 for future compatibility
  code :: 1 byte status code:
         0: accept
         1: rejected by Bob, reason unspecified
         2: rejected by Bob, Charlie is banned
         3: rejected by Bob, limit exceeded
         4: rejected by Bob, signature failure
         5: rejected by Bob, relay tag not found
         6: rejected by Bob, Alice RI not found
         7-63: other rejected by Bob codes TBD
         64: rejected by Charlie, reason unspecified
         65: rejected by Charlie, unsupported address
         66: rejected by Charlie, limit exceeded
         67: rejected by Charlie, signature failure
         68: rejected by Charlie, Alice is already connected
         69: rejected by Charlie, Alice is banned
         70: rejected by Charlie, Alice is unknown
         71-127: other rejected by Charlie codes TBD
         128: reject, source and reason unspecified
         129-255: other reject codes TBD

  The data below is covered by the signature if the code is 0 (accept).
  Bob forwards it unmodified.

  nonce :: 4 bytes, as received from Bob or Alice

  The data below is present only if the code is 0 (accept).

  timestamp :: Unix timestamp, unsigned seconds.
               Wraps around in 2106
  ver ::  1 byte SSU version to be used for the introduction:
         1: SSU 1
         2: SSU 2
  csz :: 1 byte endpoint (port + IP) size (0 or 6 or 18)
         may be 0 for some rejection codes
  CharliePort :: 2 byte Charlie's port number, big endian
                 not present if csz is 0
  Charlie IP :: (csz - 2) byte representation of Charlie's IP address,
                network byte order
                not present if csz is 0
  signature :: length varies, 64 bytes for Ed25519.
               Signature of prologue, Bob's hash,
               and signed data above, as signed by
               Charlie.
               Not present if rejected by Bob.
  token :: Token generated by Charlie for Alice to use
           in the Session Request.
           Only present if code is 0 (accept)

Ghi chú:

Token phải được Alice sử dụng ngay lập tức trong Session Request.

Chữ ký:

Nếu Charlie đồng ý (mã phản hồi 0) hoặc từ chối (mã phản hồi 64 trở lên), Charlie ký phản hồi và bao gồm nó trong khối này; Bob chuyển tiếp nó trong khối Relay Response tới Alice. Thuật toán chữ ký: Ký dữ liệu sau bằng signing key của router Charlie:

  • prologue: 16 byte “RelayAgreementOK”, không kết thúc bằng null (không được bao gồm trong thông điệp)
  • bhash: Router hash 32-byte của Bob (không được bao gồm trong thông điệp)
  • nonce: 4 byte nonce
  • timestamp: 4 byte timestamp (giây)
  • ver: 1 byte phiên bản SSU
  • csz: 1 byte kích thước endpoint (port + IP) (0 hoặc 6 hoặc 18)
  • CharliePort: 2 byte số port của Charlie (không có nếu csz là 0)
  • Charlie IP: (csz - 2) byte địa chỉ IP của Charlie (không có nếu csz là 0)

Nếu Bob từ chối (response code 1-63), Bob ký phản hồi và bao gồm nó trong block này. Thuật toán chữ ký: Ký dữ liệu sau với khóa ký router của Bob:

  • prologue: 16 bytes “RelayAgreementOK”, không kết thúc bằng null (không được bao gồm trong thông điệp)
  • bhash: Hash router 32-byte của Bob (không được bao gồm trong thông điệp)
  • nonce: 4 byte nonce
  • timestamp: 4 byte timestamp (giây)
  • ver: 1 byte phiên bản SSU
  • csz: 1 byte = 0

KDF cho Session Request

Được gửi trong một thông điệp Data trong phiên, từ Bob đến Charlie. Xem phần Relay Process bên dưới.

Phải được đặt trước bởi một khối RouterInfo, hoặc khối thông điệp I2NP DatabaseStore (hoặc đoạn), chứa Router Info của Alice, có thể trong cùng một payload (nếu có chỗ), hoặc trong một thông điệp trước đó.

+----+----+----+----+----+----+----+----+
  |  9 |  size   |flag|                   |
  +----+----+----+----+                   +
  |                                       |
  +                                       +
  |         Alice Router Hash             |
  +             32 bytes                  +
  |                                       |
  +                   +----+----+----+----+
  |                   |      nonce        |
  +----+----+----+----+----+----+----+----+
  |     relay tag     |     timestamp     |
  +----+----+----+----+----+----+----+----+
  | ver| asz|AlicePort|  Alice IP address |
  +----+----+----+----+----+----+----+----+
  |              signature                |
  +            length varies              +
  |         64 bytes for Ed25519          |
  ~                                       ~
  |                 . . .                 |
  +----+----+----+----+----+----+----+----+

  blk :: 9
  size :: 2 bytes, big endian, size of data to follow
  flag :: 1 byte flags, Unused, set to 0 for future compatibility
  hash :: Alice's 32-byte router hash,

  The data below here is covered
  by the signature, as received from Alice in the Relay Request,
  and Bob forwards it unmodified.

  nonce :: 4 bytes, as received from Alice
  relay tag :: 4 bytes, the itag from Charlie's RI
  timestamp :: Unix timestamp, unsigned seconds.
               Wraps around in 2106
  ver ::  1 byte SSU version to be used for the introduction:
         1: SSU 1
         2: SSU 2
  asz :: 1 byte endpoint (port + IP) size (6 or 18)
  AlicePort :: 2 byte Alice's port number, big endian
  Alice IP :: (asz - 2) byte representation of Alice's IP address,
              network byte order
  signature :: length varies, 64 bytes for Ed25519.
               Signature of prologue, Bob's hash,
               and signed data above, as signed by
               Alice.

Ghi chú:

  • Đối với IPv4, địa chỉ IP của Alice luôn là 4 byte, bởi vì Alice đang cố gắng kết nối với Charlie thông qua IPv4. IPv6 được hỗ trợ, và địa chỉ IP của Alice có thể là 16 byte.

  • Đối với IPv4, thông điệp này phải được gửi qua một kết nối IPv4 đã được thiết lập, vì đó là cách duy nhất để Bob biết địa chỉ IPv4 của Charlie để trả về cho Alice trong RelayResponse_. IPv6 được hỗ trợ, và thông điệp này có thể được gửi qua một kết nối IPv6 đã được thiết lập.

  • Bất kỳ địa chỉ SSU nào được công bố với các introducers phải chứa “4” hoặc “6” trong tùy chọn “caps”.

Chữ ký:

Alice ký yêu cầu và Bob chuyển tiếp nó trong khối này đến Charlie. Thuật toán xác minh: Xác minh dữ liệu sau với khóa ký của router Alice:

  • prologue: 16 bytes “RelayRequestData”, không kết thúc bằng null (không bao gồm trong thông điệp)
  • bhash: 32-byte router hash của Bob (không bao gồm trong thông điệp)
  • chash: 32-byte router hash của Charlie (không bao gồm trong thông điệp)
  • nonce: 4 byte nonce
  • relay tag: 4 byte relay tag
  • timestamp: 4 byte timestamp (giây)
  • ver: 1 byte phiên bản SSU
  • asz: 1 byte kích thước endpoint (port + IP) (6 hoặc 18)
  • AlicePort: 2 byte số port của Alice
  • Alice IP: (asz - 2) byte địa chỉ IP của Alice

PeerTest

Được gửi trong tin nhắn Data trong phiên, hoặc tin nhắn Peer Test ngoài phiên. Xem phần Quy trình Peer Test bên dưới.

Đối với thông điệp 2, phải được đi trước bởi một khối RouterInfo, hoặc khối thông điệp I2NP DatabaseStore (hoặc mảnh), chứa Router Info của Alice, có thể trong cùng một payload (nếu có đủ chỗ), hoặc trong một thông điệp trước đó.

Đối với thông điệp 4, nếu relay được chấp nhận (mã lý do 0), phải được đi trước bởi một khối RouterInfo, hoặc khối thông điệp I2NP DatabaseStore (hoặc đoạn), chứa Router Info của Charlie, có thể trong cùng một payload (nếu có đủ chỗ), hoặc trong một thông điệp trước đó.

+----+----+----+----+----+----+----+----+
  | 10 |  size   | msg|code|flag|         |
  +----+----+----+----+----+----+         +
  | Alice router hash (message 2 only)    |
  +             or                        +
  | Charlie router hash (message 4 only)  |
  + or all zeros if rejected by Bob       +
  | Not present in messages 1,3,5,6,7     |
  +                             +----+----+
  |                             | ver|
  +----+----+----+----+----+----+----+----+
     nonce       |     timestamp     | asz|
  +----+----+----+----+----+----+----+----+
  |AlicePort|  Alice IP address |         |
  +----+----+----+----+----+----+         +
  |              signature                |
  +            length varies              +
  |         64 bytes for Ed25519          |
  ~                                       ~
  |                 . . .                 |
  +----+----+----+----+----+----+----+----+

  blk :: 10
  size :: 2 bytes, big endian, size of data to follow
  msg :: 1 byte message number 1-7
  code :: 1 byte status code:
         0: accept
         1: rejected by Bob, reason unspecified
         2: rejected by Bob, no Charlie available
         3: rejected by Bob, limit exceeded
         4: rejected by Bob, signature failure
         5: rejected by Bob, address unsupported
         6-63: other rejected by Bob codes TBD
         64: rejected by Charlie, reason unspecified
         65: rejected by Charlie, unsupported address
         66: rejected by Charlie, limit exceeded
         67: rejected by Charlie, signature failure
         68: rejected by Charlie, Alice is already connected
         69: rejected by Charlie, Alice is banned
         70: rejected by Charlie, Alice is unknown
         70-127: other rejected by Charlie codes TBD
         128: reject, source and reason unspecified
         129-255: other reject codes TBD
         reject codes only allowed in messages 3 and 4
  flag :: 1 byte flags, Unused, set to 0 for future compatibility
  hash :: Alice's or Charlie's 32-byte router hash,
          only present in messages 2 and 4.
          All zeros (fake hash) in message 4 if rejected by Bob.

  For messages 1-4, the data below here is covered
  by the signature, if present, and Bob forwards it unmodified.

  ver :: 1 byte SSU version:
         1: SSU 1 (not supported)
         2: SSU 2 (required)
  nonce :: 4 byte test nonce, big endian
  timestamp :: Unix timestamp, unsigned seconds.
               Wraps around in 2106
  asz :: 1 byte endpoint (port + IP) size (6 or 18)
  AlicePort :: 2 byte Alice's port number, big endian
  Alice IP :: (asz - 2) byte representation of Alice's IP address,
              network byte order
  signature :: length varies, 64 bytes for Ed25519.
               Signature of prologue, Bob's hash,
               and signed data above, as signed by
               Alice or Charlie.
               Only present for messages 1-4.
               Optional in message 5-7.

Ghi chú:

  • Không giống như trong SSU 1, thông điệp 1 phải bao gồm địa chỉ IP và port của Alice.

  • Việc thử nghiệm các địa chỉ IPv6 được hỗ trợ, và việc giao tiếp Alice-Bob và Alice-Charlie có thể thông qua IPv6, nếu Bob và Charlie cho biết hỗ trợ với khả năng ‘B’ trong địa chỉ IPv6 đã công bố của họ. Xem Proposal 126 để biết chi tiết.

Alice gửi yêu cầu đến Bob sử dụng một phiên hiện có qua lớp vận chuyển (IPv4 hoặc IPv6) mà cô ấy muốn kiểm tra. Khi Bob nhận được yêu cầu từ Alice qua IPv4, Bob phải chọn một Charlie quảng bá địa chỉ IPv4. Khi Bob nhận được yêu cầu từ Alice qua IPv6, Bob phải chọn một Charlie quảng bá địa chỉ IPv6. Việc giao tiếp thực tế Bob-Charlie có thể qua IPv4 hoặc IPv6 (tức là, độc lập với loại địa chỉ của Alice).

  • Thông điệp 1-4 phải được chứa trong một thông điệp Data trong một phiên làm việc hiện có.

  • Bob phải gửi RI của Alice cho Charlie trước khi gửi tin nhắn 2.

  • Bob phải gửi RI của Charlie cho Alice trước khi gửi tin nhắn 4, nếu được chấp nhận (mã lý do 0).

  • Các thông điệp 5-7 phải được chứa trong một thông điệp Peer Test ngoài phiên.

  • Các thông điệp 5 và 7 có thể chứa cùng dữ liệu đã ký như đã gửi trong các thông điệp 3 và 4, hoặc có thể được tạo lại với timestamp mới. Signature là tùy chọn.

  • Thông điệp 6 có thể chứa cùng dữ liệu đã ký như đã gửi trong thông điệp 1 và 2, hoặc có thể được tạo lại với timestamp mới. Chữ ký là tùy chọn.

Chữ ký:

Alice ký yêu cầu và bao gồm nó trong thông điệp 1; Bob chuyển tiếp nó trong thông điệp 2 tới Charlie. Charlie ký phản hồi và bao gồm nó trong thông điệp 3; Bob chuyển tiếp nó trong thông điệp 4 tới Alice. Thuật toán chữ ký: Ký hoặc xác minh dữ liệu sau với khóa ký của Alice hoặc Charlie:

  • prologue: 16 bytes “PeerTestValidate”, không kết thúc bằng null (không được bao gồm trong message)
  • bhash: router hash 32-byte của Bob (không được bao gồm trong message)
  • ahash: router hash 32-byte của Alice (Chỉ được sử dụng trong chữ ký cho message 3 và 4; không được bao gồm trong message 3 hoặc 4)
  • ver: 1 byte phiên bản SSU
  • nonce: 4 byte test nonce
  • timestamp: 4 byte timestamp (giây)
  • asz: 1 byte kích thước endpoint (port + IP) (6 hoặc 18)
  • AlicePort: 2 byte số port của Alice
  • Alice IP: (asz - 2) byte địa chỉ IP của Alice

Tải trọng

TODO chỉ khi chúng ta xoay khóa

+----+----+----+----+----+----+----+----+
  | 11 |  size   |      TBD               |
  +----+----+----+                        +
  |                                       |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+

  blk :: 11
  size :: 2 bytes, big endian, size of data to follow

Ghi chú

4 byte ack through, theo sau bởi một ack count và không hoặc nhiều nack/ack ranges.

Thiết kế này được điều chỉnh và đơn giản hóa từ QUIC. Các mục tiêu thiết kế như sau:

  • Chúng ta muốn mã hóa hiệu quả một “bitfield”, đây là một chuỗi các bit đại diện cho các packet đã được ack.
  • Bitfield chủ yếu là các bit 1. Cả bit 1 và bit 0 thường xuất hiện thành các “cụm” tuần tự.
  • Lượng không gian có sẵn trong packet cho các ack là thay đổi.
  • Bit quan trọng nhất là bit có số thứ tự cao nhất. Các bit có số thứ tự thấp hơn ít quan trọng hơn. Dưới một khoảng cách nhất định từ bit cao nhất, những bit cũ nhất sẽ bị “quên” và không bao giờ được gửi lại.

Phương pháp mã hóa được chỉ định dưới đây thực hiện những mục tiêu thiết kế này bằng cách gửi số của bit cao nhất được đặt thành 1, cùng với các bit liên tiếp bổ sung thấp hơn bit đó cũng được đặt thành 1. Sau đó, nếu còn chỗ, một hoặc nhiều “phạm vi” chỉ định số bit 0 liên tiếp và bit 1 liên tiếp thấp hơn đó. Xem QUIC RFC 9000 phần 13.2.3 để biết thêm thông tin nền.

+----+----+----+----+----+----+----+----+
  | 12 |  size   |    Ack Through    |acnt|
  +----+----+----+----+----+----+----+----+
  |  range  |  range  |     .   .   .     |
  +----+----+----+----+                   +
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+

  blk :: 12
  size :: 2 bytes, big endian, size of data to follow,
          5 minimum
  ack through :: highest packet number acked
  acnt :: number of acks lower than ack through also acked,
          0-255
  range :: If present,
           1 byte nack count followed by 1 byte ack count,
           0-255 each

Ví dụ:

Chúng tôi chỉ muốn ACK packet 10:

  • Ack Through: 10
  • acnt: 0
  • không có phạm vi nào được bao gồm

Chúng ta muốn ACK các gói tin 8-10 chỉ:

  • Ack Through: 10
  • acnt: 2
  • không có phạm vi nào được bao gồm

Chúng ta muốn ACK 10 9 8 6 5 2 1 0, và NACK 7 4 3. Mã hóa của ACK Block là:

  • Ack Through: 10
  • acnt: 2 (ack 9 8)
  • range: 1 2 (nack 7, ack 6 5)
  • range: 2 3 (nack 4 3, ack 2 1 0)

Ghi chú:

  • Các dải có thể không có mặt. Số lượng tối đa của các dải không được chỉ định, có thể có nhiều như sẽ vừa trong gói tin.
  • Range nack có thể bằng không nếu ack hơn 255 gói tin liên tiếp.
  • Range ack có thể bằng không nếu nack hơn 255 gói tin liên tiếp.
  • Range nack và ack không thể đồng thời bằng không.
  • Sau dải cuối cùng, các gói tin không được ack cũng không được nack. Độ dài của ack block và cách xử lý các ack/nack cũ là tùy thuộc vào người gửi ack block. Xem các phần ack bên dưới để thảo luận.
  • Ack through nên là số gói tin cao nhất đã nhận được, và bất kỳ gói tin nào cao hơn đều chưa được nhận. Tuy nhiên, trong các tình huống hạn chế, nó có thể thấp hơn, chẳng hạn như ack một gói tin duy nhất “lấp đầy lỗ hổng”, hoặc một triển khai đơn giản hóa không duy trì trạng thái của tất cả các gói tin đã nhận. Trên mức cao nhất đã nhận, các gói tin không được ack cũng không được nack, nhưng sau vài ack block, có thể thích hợp để chuyển vào chế độ truyền lại nhanh.
  • Định dạng này là phiên bản đơn giản hóa của định dạng trong QUIC. Nó được thiết kế để mã hóa hiệu quả một số lượng lớn ACK, cùng với các cụm NACK.
  • ACK block được sử dụng để xác nhận các gói tin giai đoạn dữ liệu. Chúng chỉ được bao gồm cho các gói tin giai đoạn dữ liệu trong phiên.

Address

2 byte port và 4 hoặc 16 byte địa chỉ IP. Địa chỉ của Alice, được Bob gửi cho Alice, hoặc địa chỉ của Bob, được Alice gửi cho Bob.

+----+----+----+----+----+----+----+----+
  | 13 | 6 or 18 |   Port  | IP Address    
  +----+----+----+----+----+----+----+----+
       |
  +----+

  blk :: 13
  size :: 2 bytes, big endian, 6 or 18
  port :: 2 bytes, big endian
  ip :: 4 byte IPv4 or 16 byte IPv6 address,
        big endian (network byte order)

Relay Tag Request

Điều này có thể được gửi bởi Alice trong tin nhắn Session Request, Session Confirmed, hoặc Data. Không được hỗ trợ trong tin nhắn Session Created, vì Bob chưa có RI của Alice, và không biết liệu Alice có hỗ trợ relay hay không. Ngoài ra, nếu Bob đang nhận một kết nối đến, anh ta có thể không cần introducers (ngoại trừ có lẽ cho loại khác ipv4/ipv6).

Khi được gửi trong Session Request, Bob có thể phản hồi bằng một Relay Tag trong thông điệp Session Created, hoặc có thể chọn đợi cho đến khi nhận được RouterInfo của Alice trong Session Confirmed để xác thực danh tính của Alice trước khi phản hồi trong thông điệp Data. Nếu Bob không muốn relay cho Alice, anh ta không gửi khối Relay Tag.

+----+----+----+
  | 15 |    0    |
  +----+----+----+

  blk :: 15
  size :: 2 bytes, big endian, value = 0

Tải trọng

Điều này có thể được gửi bởi Bob trong một thông điệp Session Confirmed hoặc Data, để phản hồi một Relay Tag Request từ Alice.

Khi Relay Tag Request được gửi trong Session Request, Bob có thể phản hồi bằng Relay Tag trong thông điệp Session Created, hoặc có thể chọn đợi cho đến khi nhận được RouterInfo của Alice trong Session Confirmed để xác thực danh tính của Alice trước khi phản hồi trong thông điệp Data. Nếu Bob không muốn relay cho Alice, anh ta sẽ không gửi Relay Tag block.

+----+----+----+----+----+----+----+
  | 16 |    4    |    relay tag      |
  +----+----+----+----+----+----+----+

  blk :: 16
  size :: 2 bytes, big endian, value = 4
  relay tag :: 4 bytes, big endian, nonzero

Ghi chú

Dành cho kết nối tiếp theo. Thường được bao gồm trong các thông điệp Session Created và Session Confirmed. Cũng có thể được gửi lại trong thông điệp Data của một phiên dài hạn nếu token trước đó hết hạn.

+----+----+----+----+----+----+----+----+
  | 17 |   12    |     expires       |
  +----+----+----+----+----+----+----+----+
                  token              |
  +----+----+----+----+----+----+----+

  blk :: 17
  size :: 2 bytes, big endian, value = 12
  expires :: Unix timestamp, unsigned seconds.
             Wraps around in 2106
  token :: 8 bytes, big endian

Vấn đề

Một Ping với dữ liệu tùy ý được trả về trong Path Response, được sử dụng như keep-alive hoặc để xác thực thay đổi IP/Port.

+----+----+----+----+----+----+----+----+
  | 18 |  size   |    Arbitrary Data      |
  +----+----+----+                        +
  |                                       |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+

  blk :: 18
  size :: 2 bytes, big endian, size of data to follow
  data :: Arbitrary data to be returned in a Path Response
          length as selected by sender

Ghi chú:

Khuyến nghị sử dụng kích thước dữ liệu tối thiểu là 8 byte, chứa dữ liệu ngẫu nhiên, nhưng không bắt buộc.

Path Response

Một Pong với dữ liệu nhận được trong Path Challenge, như phản hồi cho Path Challenge, được sử dụng làm keep-alive hoặc để xác thực thay đổi IP/Port.

+----+----+----+----+----+----+----+----+
  | 19 |  size   |                        |
  +----+----+----+                        +
  |    Data received in Path Challenge    |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+

  blk :: 19
  size :: 2 bytes, big endian, size of data to follow
  data :: As received in a Path Challenge

First Packet Number

Tùy chọn được bao gồm trong quá trình bắt tay theo mỗi hướng, để chỉ định số gói tin đầu tiên sẽ được gửi. Điều này cung cấp thêm bảo mật cho việc mã hóa header, tương tự như TCP.

Chưa được chỉ định đầy đủ, hiện tại không được hỗ trợ.

+----+----+----+----+----+----+----+
  | 20 |  size   |  First pkt number |
  +----+----+----+----+----+----+----+

  blk :: 20
  size :: 4
  pkt num :: The first packet number to be sent in the data phase

Congestion

Khối này được thiết kế như một phương thức có thể mở rộng để trao đổi thông tin kiểm soát tắc nghẽn. Kiểm soát tắc nghẽn có thể phức tạp và có thể phát triển khi chúng ta có thêm kinh nghiệm với giao thức trong quá trình thử nghiệm thực tế, hoặc sau khi triển khai đầy đủ.

Điều này giữ cho mọi thông tin tắc nghẽn tách khỏi các block I2NP, First Fragment, Followon Fragment, và ACK có mức sử dụng cao, nơi không có không gian được phân bổ cho các flag. Trong khi có ba byte flag không sử dụng trong header của Data packet, điều đó cũng chỉ cung cấp không gian hạn chế cho khả năng mở rộng và bảo vệ mã hóa yếu hơn.

Mặc dù việc sử dụng một block 4-byte cho hai bit thông tin có phần lãng phí, nhưng bằng cách đặt điều này trong một block riêng biệt, chúng ta có thể dễ dàng mở rộng nó với dữ liệu bổ sung như kích thước cửa sổ hiện tại, RTT đo được, hoặc các flag khác. Kinh nghiệm đã cho thấy rằng chỉ riêng các bit flag thường không đủ và khó xử lý cho việc triển khai các scheme kiểm soát tắc nghẽn tiên tiến. Việc cố gắng thêm hỗ trợ cho bất kỳ tính năng kiểm soát tắc nghẽn có thể nào trong, ví dụ như ACK block, sẽ lãng phí không gian và tăng thêm độ phức tạp cho việc phân tích block đó.

Các implementation không nên giả định rằng router khác hỗ trợ bất kỳ flag bit hoặc tính năng cụ thể nào được bao gồm ở đây, trừ khi việc implementation được yêu cầu bởi phiên bản tương lai của đặc tả này.

Block này có thể sẽ là block không phải padding cuối cùng trong payload.

+----+----+----+----+
  | 21 |  size   |flag|
  +----+----+----+----+

  blk :: 21
  size :: 1 (or more if extended)
  flag :: 1 byte flags
         bit order: 76543210 (bit 7 is MSB)
         bit 0: 1 to request immediate ack
         bit 1: 1 for explicit congestion notification (ECN)
         bits 7-2: Unused, set to 0 for future compatibility

Payload

Đây là để đệm bên trong các payload AEAD. Việc đệm cho tất cả các thông điệp đều nằm bên trong các payload AEAD.

Padding nên tuân thủ gần đúng các tham số đã thỏa thuận. Bob đã gửi các tham số tx/rx min/max được yêu cầu của mình trong Session Created. Alice đã gửi các tham số tx/rx min/max được yêu cầu của cô ấy trong Session Confirmed. Các tùy chọn được cập nhật có thể được gửi trong giai đoạn dữ liệu. Xem thông tin khối tùy chọn ở trên.

Nếu có mặt, đây phải là khối cuối cùng trong payload.

+----+----+----+----+----+----+----+----+
  |254 |  size   |      padding           |
  +----+----+----+                        +
  |                                       |
  ~               .   .   .               ~
  |                                       |
  +----+----+----+----+----+----+----+----+

  blk :: 254
  size :: 2 bytes, big endian, size of padding to follow
  padding :: random data

Ghi chú:

  • Size = 0 được cho phép.

  • Chiến lược padding TBD.

  • Padding tối thiểu TBD.

  • Payload chỉ có padding được cho phép.

  • Padding mặc định TBD.

  • Xem khối options để đàm phán tham số padding

  • Xem khối options cho các tham số padding min/max

  • Không vượt quá MTU. Nếu cần thêm padding, hãy gửi nhiều tin nhắn.

  • Phản hồi của router khi vi phạm padding đã đàm phán phụ thuộc vào implementation.

  • Độ dài padding sẽ được quyết định dựa trên từng thông điệp cụ thể và ước tính phân bố độ dài, hoặc thêm độ trễ ngẫu nhiên. Những biện pháp đối phó này được bao gồm để chống lại DPI, vì kích thước thông điệp có thể tiết lộ rằng lưu lượng I2P đang được truyền tải bởi giao thức vận chuyển. Sơ đồ padding chính xác là một lĩnh vực nghiên cứu trong tương lai, Phụ lục A của NTCP2 cung cấp thêm thông tin về chủ đề này.

Replay Prevention

SSU2 được thiết kế để giảm thiểu tác động của các thông điệp bị tấn công phát lại bởi kẻ tấn công.

Các thông điệp Token Request, Retry, Session Request, Session Created, Hole Punch, và out-of-session Peer Test phải chứa các khối DateTime.

Cả Alice và Bob đều xác thực rằng thời gian của những thông điệp này nằm trong khoảng độ lệch hợp lệ (khuyến nghị +/- 2 phút). Để “chống thăm dò”, Bob không nên phản hồi các thông điệp Token Request hoặc Session Request nếu độ lệch thời gian không hợp lệ, vì những thông điệp này có thể là một cuộc tấn công replay hoặc thăm dò.

Bob có thể chọn từ chối các Token Request và Retry message trùng lặp, ngay cả khi skew hợp lệ, thông qua Bloom filter hoặc cơ chế khác. Tuy nhiên, kích thước và chi phí CPU để phản hồi các message này là thấp. Trong trường hợp xấu nhất, một Token Request message bị phát lại có thể làm vô hiệu hóa một token đã được gửi trước đó.

Hệ thống token giảm thiểu đáng kể tác động của các thông điệp Session Request bị phát lại. Vì các token chỉ có thể được sử dụng một lần, một thông điệp Session Request bị phát lại sẽ không bao giờ có token hợp lệ. Bob có thể chọn từ chối các thông điệp Session Request trùng lặp, ngay cả khi skew hợp lệ, thông qua Bloom filter hoặc cơ chế khác. Tuy nhiên, kích thước và chi phí CPU để trả lời bằng thông điệp Retry là thấp. Trong trường hợp tồi tệ nhất, việc gửi thông điệp Retry có thể vô hiệu hóa một token đã được gửi trước đó.

Các thông điệp Session Created và Session Confirmed trùng lặp sẽ không được xác thực bởi vì trạng thái Noise handshake sẽ không ở trạng thái chính xác để giải mã chúng. Trong trường hợp xấu nhất, một peer có thể truyền lại Session Confirmed để phản hồi một Session Created trùng lặp có vẻ như xuất hiện.

Các thông điệp Hole Punch và Peer Test được phát lại sẽ có tác động ít hoặc không có tác động gì.

Các router phải sử dụng số gói tin thông điệp dữ liệu để phát hiện và loại bỏ các thông điệp giai đoạn dữ liệu trùng lặp. Mỗi số gói tin chỉ nên được sử dụng một lần. Các thông điệp phát lại phải được bỏ qua.

Handshake Retransmission

Session Request

Nếu Alice không nhận được Session Created hoặc Retry:

Giữ nguyên source và connection ID, ephemeral key và packet number 0. Hoặc chỉ cần giữ lại và truyền lại cùng một gói mã hóa. Packet number không được tăng lên, vì điều đó sẽ thay đổi giá trị hash liên kết được sử dụng để mã hóa thông điệp Session Created.

Khoảng thời gian truyền lại được khuyến nghị: 1,25, 2,5 và 5 giây (1,25, 3,75 và 8,75 giây sau lần gửi đầu tiên). Timeout được khuyến nghị: Tổng cộng 15 giây

Session Created

Nếu Bob không nhận được Session Confirmed:

Duy trì cùng ID nguồn và ID kết nối, khóa tạm thời, và số gói tin 0. Hoặc, chỉ giữ lại gói tin đã mã hóa. Số gói tin không được tăng, vì điều đó sẽ thay đổi giá trị hash móc nối được sử dụng để mã hóa thông điệp Session Confirmed.

Khoảng thời gian truyền lại được khuyến nghị: 1, 2, và 4 giây (1, 3, và 7 giây sau lần gửi đầu tiên). Thời gian chờ được khuyến nghị: tổng cộng 12 giây

Session Confirmed

Trong SSU 1, Alice không chuyển sang giai đoạn dữ liệu cho đến khi nhận được gói dữ liệu đầu tiên từ Bob. Điều này khiến SSU 1 trở thành thiết lập hai round-trip.

Đối với SSU 2, Khoảng thời gian truyền lại Session Confirmed được khuyến nghị: 1,25, 2,5, và 5 giây (1,25, 3,75, và 8,75 giây sau lần gửi đầu tiên).

Có một số phương án thay thế. Tất cả đều là 1 RTT:

  1. Alice giả định Session Confirmed đã được nhận, gửi các thông điệp dữ liệu ngay lập tức, không bao giờ truyền lại Session Confirmed. Các gói dữ liệu nhận được không theo thứ tự (trước Session Confirmed) sẽ không thể giải mã được, nhưng sẽ được truyền lại. Nếu Session Confirmed bị mất, tất cả các thông điệp dữ liệu đã gửi sẽ bị loại bỏ.

  2. Như trong 1), gửi các thông điệp dữ liệu ngay lập tức, nhưng cũng truyền lại Session Confirmed cho đến khi nhận được một thông điệp dữ liệu.

  3. Chúng ta có thể sử dụng IK thay vì XK, vì nó chỉ có hai thông điệp trong handshake, nhưng nó sử dụng thêm một DH (4 thay vì 3).

Việc triển khai được khuyến nghị là tùy chọn 2). Alice phải giữ lại thông tin cần thiết để truyền lại thông báo Session Confirmed. Alice cũng nên truyền lại tất cả các thông báo Data sau khi thông báo Session Confirmed được truyền lại.

Khi retransmit Session Confirmed, duy trì cùng source và connection IDs, ephemeral key, và packet number 1. Hoặc, chỉ cần giữ lại encrypted packet. Packet number không được tăng, vì điều đó sẽ thay đổi chained hash value mà đó là input cho hàm split().

Bob có thể giữ lại (xếp hàng) các thông điệp dữ liệu nhận được trước thông điệp Session Confirmed. Cả khóa bảo vệ header và khóa giải mã đều không có sẵn trước khi nhận được thông điệp Session Confirmed, vì vậy Bob không biết rằng đó là các thông điệp dữ liệu, nhưng có thể suy đoán được điều đó. Sau khi nhận được thông điệp Session Confirmed, Bob có thể giải mã và xử lý các thông điệp Data đã xếp hàng. Nếu điều này quá phức tạp, Bob có thể đơn giản bỏ qua các thông điệp Data không thể giải mã được, vì Alice sẽ truyền lại chúng.

Lưu ý: Nếu các gói session confirmed bị mất, Bob sẽ truyền lại session created. Header của session created sẽ không thể giải mã được với intro key của Alice, vì nó được thiết lập với intro key của Bob (trừ khi thực hiện giải mã dự phòng với intro key của Bob). Bob có thể ngay lập tức truyền lại các gói session confirmed nếu chưa được ack trước đó, và một gói không thể giải mã được nhận.

Token Request

Nếu Alice không nhận được Retry:

Duy trì cùng source và connection ID. Một implementation có thể tạo ra một packet number ngẫu nhiên mới và mã hóa một packet mới; Hoặc có thể tái sử dụng cùng packet number hoặc chỉ giữ lại và truyền lại cùng encrypted packet. Packet number không được tăng lên, vì điều đó sẽ thay đổi giá trị chained hash được sử dụng để mã hóa Session Created message.

Khoảng thời gian truyền lại được khuyến nghị: 3 và 6 giây (3 và 9 giây sau lần gửi đầu tiên). Timeout được khuyến nghị: tổng cộng 15 giây

Retry

Nếu Bob không nhận được Session Request:

Một thông báo Retry không được truyền lại khi hết thời gian chờ, để giảm thiểu tác động của các địa chỉ nguồn giả mạo.

Tuy nhiên, một thông điệp Retry có thể được truyền lại để phản hồi cho một thông điệp Session Request lặp lại được nhận với token gốc (không hợp lệ), hoặc để phản hồi cho một thông điệp Token Request lặp lại. Trong cả hai trường hợp, điều này cho thấy thông điệp Retry đã bị mất.

Nếu nhận được một thông điệp Session Request thứ hai với token khác nhưng vẫn không hợp lệ, hãy hủy bỏ session đang chờ xử lý và không phản hồi.

Nếu gửi lại thông điệp Retry: Duy trì cùng source và connection ID và token. Một triển khai có thể tạo một packet number ngẫu nhiên mới và mã hóa một packet mới; Hoặc có thể tái sử dụng cùng packet number hoặc chỉ giữ lại và truyền lại cùng encrypted packet.

Total Timeout

Thời gian chờ tổng cộng được khuyến nghị cho handshake là 20 giây.

Duplicates and Error Handling

Các bản sao của ba thông điệp Noise handshake Session Request, Session Created, và Session Confirmed phải được phát hiện trước khi MixHash() của header. Mặc dù quá trình xử lý Noise AEAD có thể sẽ thất bại sau đó, nhưng handshake hash đã bị hỏng.

Nếu bất kỳ một trong ba thông điệp bị hỏng và không thành công AEAD, quá trình handshake không thể được khôi phục ngay cả khi truyền lại, bởi vì MixHash() đã được gọi trên thông điệp bị hỏng.

Tokens

Token trong header Session Request được sử dụng để giảm thiểu DoS, ngăn chặn giả mạo địa chỉ nguồn, và chống lại các cuộc tấn công replay.

Nếu Bob không chấp nhận token trong thông điệp Session Request, Bob KHÔNG giải mã thông điệp, vì nó yêu cầu một phép toán DH tốn kém. Bob chỉ đơn giản gửi một thông điệp Retry với một token mới.

Nếu một thông điệp Session Request tiếp theo được nhận với token đó, Bob tiến hành giải mã thông điệp đó và tiếp tục với quá trình handshake.

Token phải là một giá trị 8 byte được tạo ngẫu nhiên, nếu bộ tạo token lưu trữ các giá trị và IP cùng port liên quan (trong bộ nhớ hoặc lâu dài). Bộ tạo không được tạo ra một giá trị không rõ ràng, ví dụ, sử dụng SipHash (với khóa bí mật K0, K1) của IP, port và giờ hoặc ngày hiện tại, để tạo ra các token không cần được lưu trong bộ nhớ, bởi vì phương pháp này khiến việc từ chối các token được sử dụng lại và các cuộc tấn công replay trở nên khó khăn.

Token chỉ có thể được sử dụng một lần. Token được Bob gửi đến Alice trong thông báo Retry phải được sử dụng ngay lập tức và hết hạn sau vài giây. Token được gửi trong khối New Token trong phiên đã thiết lập có thể được sử dụng trong kết nối tiếp theo và sẽ hết hạn vào thời điểm được chỉ định trong khối đó. Thời gian hết hạn được chỉ định bởi người gửi; các giá trị được khuyến nghị là tối thiểu một giờ, tối đa vài giờ.

Nếu IP hoặc port của một router thay đổi, nó phải xóa tất cả các token đã lưu (cả inbound và outbound) cho IP hoặc port cũ, vì chúng không còn hợp lệ. Các token có thể tùy chọn được duy trì qua các lần khởi động lại router, tùy thuộc vào cách triển khai. Việc chấp nhận một token chưa hết hạn không được đảm bảo; nếu Bob đã quên hoặc xóa các token đã lưu của mình, anh ta sẽ gửi một Retry cho Alice. Một router có thể chọn giới hạn việc lưu trữ token, và loại bỏ các token được lưu trữ cũ nhất ngay cả khi chúng chưa hết hạn.

Các khối Token mới có thể được gửi từ Alice đến Bob hoặc từ Bob đến Alice. Chúng thường được gửi một lần, trong hoặc ngay sau khi thiết lập phiên. Token có thể được gửi lại trước hoặc sau khi hết hạn với thời gian hết hạn mới, hoặc có thể gửi một token mới. Các router nên giả định rằng chỉ token cuối cùng nhận được là hợp lệ; không có yêu cầu lưu trữ nhiều token đầu vào hoặc đầu ra cho cùng một IP/port.

Một token được ràng buộc với sự kết hợp của IP/port nguồn và IP/port đích. Một token nhận được trên IPv4 không thể được sử dụng cho IPv6 hoặc ngược lại.

Nếu một trong hai peer di chuyển sang IP hoặc port mới trong phiên (xem phần Connection Migration), bất kỳ token nào đã trao đổi trước đó sẽ bị vô hiệu hóa, và các token mới phải được trao đổi.

Các triển khai có thể, nhưng không bắt buộc phải, lưu các token trên đĩa và tải lại chúng khi khởi động lại. Nếu được lưu trữ lâu dài, triển khai phải đảm bảo rằng IP và port không thay đổi kể từ khi tắt máy trước khi tải lại chúng.

I2NP Message Fragmentation

Sự khác biệt so với SSU 1

Lưu ý: Giống như trong SSU 1, fragment ban đầu không chứa thông tin về tổng số fragment hoặc tổng độ dài. Các fragment tiếp theo không chứa thông tin về offset của chúng. Điều này cung cấp cho người gửi tính linh hoạt để phân mảnh “ngay lập tức” dựa trên không gian khả dụng trong gói tin. (Java I2P không làm như vậy; nó “phân mảnh trước” trước khi fragment đầu tiên được gửi) Tuy nhiên, điều này làm tăng gánh nặng cho người nhận phải lưu trữ các fragment nhận được không theo thứ tự và trì hoãn việc tái hợp thành cho đến khi tất cả fragment được nhận.

Như trong SSU 1, bất kỳ việc truyền lại các fragment nào cũng phải bảo toàn độ dài (và offset ngầm định) của lần truyền trước đó của fragment.

SSU 2 tách riêng ba trường hợp (thông điệp đầy đủ, fragment ban đầu, và fragment tiếp theo) thành ba loại khối khác nhau, để cải thiện hiệu suất xử lý.

I2NP Message Duplication

Giao thức này KHÔNG hoàn toàn ngăn chặn việc gửi trùng lặp các thông điệp I2NP. Các bản sao ở tầng IP hoặc các cuộc tấn công replay sẽ được phát hiện ở tầng SSU2, vì mỗi packet number chỉ có thể được sử dụng một lần.

Tuy nhiên, khi các thông điệp I2NP hoặc các đoạn được truyền lại trong các gói tin mới, điều này không thể phát hiện được ở tầng SSU2. Router nên thực thi việc hết hạn I2NP (cả quá cũ và quá xa trong tương lai) và sử dụng bộ lọc Bloom hoặc cơ chế khác dựa trên ID thông điệp I2NP.

Các cơ chế bổ sung có thể được sử dụng bởi router, hoặc trong triển khai SSU2, để phát hiện các bản sao. Ví dụ, SSU2 có thể duy trì một cache của các message ID đã nhận gần đây. Điều này phụ thuộc vào triển khai.

Congestion Control

Đề xuất này xác định giao thức cho việc đánh số gói tin và các khối ACK. Điều này cung cấp đủ thông tin thời gian thực để bộ truyền có thể triển khai một thuật toán kiểm soát tắc nghẽn hiệu quả và phản hồi nhanh, trong khi cho phép tính linh hoạt và sự đổi mới trong việc triển khai đó. Phần này thảo luận về các mục tiêu triển khai và đưa ra các gợi ý. Hướng dẫn chung có thể được tìm thấy trong RFC 9002. Xem thêm RFC 6298 để được hướng dẫn về bộ đếm thời gian truyền lại.

Các gói dữ liệu chỉ chứa ACK không nên được tính vào bytes hoặc packets đang truyền và không được kiểm soát tắc nghẽn. Không giống như trong TCP, SSU2 có thể phát hiện việc mất các gói tin này và thông tin đó có thể được sử dụng để điều chỉnh trạng thái tắc nghẽn. Tuy nhiên, tài liệu này không chỉ định cơ chế để thực hiện việc đó.

Các packet chứa một số block không phải dữ liệu khác cũng có thể được loại trừ khỏi kiểm soát tắc nghẽn nếu muốn, tùy thuộc vào cách triển khai. Ví dụ:

  • Peer Test
  • Yêu cầu/giới thiệu/phản hồi Relay
  • Thử thách/phản hồi đường dẫn

Khuyến nghị rằng kiểm soát tắc nghẽn nên dựa trên số lượng byte, không phải số lượng packet, tuân theo hướng dẫn trong các TCP RFCs và QUIC RFC 9002. Một giới hạn số lượng packet bổ sung cũng có thể hữu ích để ngăn chặn tràn buffer trong kernel hoặc trong các middlebox, tùy thuộc vào implementation, mặc dù điều này có thể làm tăng độ phức tạp đáng kể. Nếu output packet theo session và/hoặc tổng thể bị giới hạn băng thông và/hoặc được paced, điều này có thể giảm thiểu nhu cầu giới hạn số lượng packet.

Packet Numbers

Trong SSU 1, ACK và NACK chứa số thứ tự tin nhắn I2NP và bitmask của các fragment. Các transmitter theo dõi trạng thái ACK của các tin nhắn gửi đi (và các fragment của chúng) và truyền lại các fragment khi cần thiết.

Trong SSU 2, các ACK và NACK chứa số packet. Các transmitter phải duy trì một cấu trúc dữ liệu với ánh xạ từ số packet đến nội dung của chúng. Khi một packet được ACK hoặc NACK, transmitter phải xác định những I2NP message và fragment nào có trong packet đó, để quyết định cái gì cần truyền lại.

Session Confirmed ACK

Bob gửi một ACK của packet 0, xác nhận thông điệp Session Confirmed và cho phép Alice tiến vào giai đoạn dữ liệu, đồng thời loại bỏ thông điệp Session Confirmed lớn đang được lưu để có thể truyền lại. Điều này thay thế cho DeliveryStatusMessage được gửi bởi Bob trong SSU 1.

Bob nên gửi ACK càng sớm càng tốt sau khi nhận được thông điệp Session Confirmed. Độ trễ nhỏ (không quá 50 ms) là có thể chấp nhận được, vì ít nhất một thông điệp Data sẽ đến gần như ngay lập tức sau thông điệp Session Confirmed, để ACK có thể xác nhận cả Session Confirmed và thông điệp Data. Điều này sẽ ngăn Bob khỏi việc phải truyền lại thông điệp Session Confirmed.

Generating ACKs

Định nghĩa: Các gói ack-eliciting: Các gói chứa các khối ack-eliciting sẽ kích hoạt một ACK từ bên nhận trong thời gian trễ xác nhận tối đa và được gọi là các gói ack-eliciting.

Các router xác nhận tất cả các gói tin mà chúng nhận và xử lý. Tuy nhiên, chỉ có các gói tin yêu cầu xác nhận (ack-eliciting) mới khiến một khối ACK được gửi trong thời gian trễ xác nhận tối đa. Các gói tin không yêu cầu xác nhận chỉ được xác nhận khi một khối ACK được gửi vì những lý do khác.

Khi gửi một gói tin vì bất kỳ lý do gì, một endpoint nên cố gắng bao gồm một khối ACK nếu chưa gửi gần đây. Làm như vậy sẽ giúp phát hiện mất mát kịp thời tại peer.

Nhìn chung, phản hồi thường xuyên từ bên nhận cải thiện khả năng phản ứng với mất mát và tắc nghẽn, nhưng điều này phải được cân bằng với tải trọng quá mức do bên nhận tạo ra khi gửi khối ACK để phản hồi mọi gói tin yêu cầu xác nhận. Hướng dẫn được đưa ra bên dưới nhằm tạo ra sự cân bằng này.

Các gói dữ liệu trong phiên chứa bất kỳ khối nào NGOẠI TRỪ những khối sau đây đều yêu cầu xác nhận:

  • Khối ACK
  • Khối địa chỉ
  • Khối DateTime
  • Khối padding
  • Khối termination
  • Bất kỳ khối nào trong cùng gói tin với khối Termination
  • Khác?

Các gói tin chứa khối Termination với lý do khác “termination received” sẽ được xác nhận bằng một gói tin chứa khối Termination với “termination received”.

Các gói tin ngoài phiên, bao gồm thông điệp bắt tay và thông điệp kiểm tra peer 5-7, có cơ chế xác nhận riêng của chúng. Xem bên dưới.

Handshake ACKs

Đây là những trường hợp đặc biệt:

  • Token Request được xác nhận ngầm định bởi Retry
  • Session Request được xác nhận ngầm định bởi Session Created hoặc Retry
  • Retry được xác nhận ngầm định bởi Session Request
  • Session Created được xác nhận ngầm định bởi Session Confirmed
  • Session Confirmed nên được xác nhận ngay lập tức

Sending ACK Blocks

Các khối ACK được sử dụng để xác nhận các gói tin giai đoạn dữ liệu. Chúng chỉ được bao gồm cho các gói tin giai đoạn dữ liệu trong phiên.

Mỗi gói tin phải được xác nhận ít nhất một lần, và các gói tin yêu cầu xác nhận phải được xác nhận ít nhất một lần trong thời gian trễ tối đa.

Một endpoint phải xác nhận tất cả các gói handshake yêu cầu ack ngay lập tức trong khoảng thời gian trễ tối đa của nó, với ngoại lệ sau đây. Trước khi xác nhận handshake, một endpoint có thể không có khóa mã hóa header gói để giải mã các gói khi chúng được nhận. Do đó, nó có thể đệm chúng và xác nhận chúng khi các khóa cần thiết trở nên khả dụng.

Vì các packet chỉ chứa các khối ACK không được kiểm soát tắc nghẽn, một endpoint không được gửi nhiều hơn một packet như vậy để phản hồi việc nhận một packet ack-eliciting.

Một endpoint không được gửi gói tin không yêu cầu ACK để phản hồi một gói tin không yêu cầu ACK, ngay cả khi có khoảng trống gói tin đứng trước gói tin đã nhận. Điều này tránh vòng lặp phản hồi vô hạn của các acknowledgment, có thể ngăn kết nối trở nên idle. Các gói tin không yêu cầu ACK cuối cùng sẽ được acknowledge khi endpoint gửi một ACK block để phản hồi các sự kiện khác.

Một endpoint chỉ gửi các khối ACK sẽ không nhận được xác nhận từ peer của nó trừ khi những xác nhận đó được bao gồm trong các gói tin có chứa các khối ack-eliciting. Một endpoint nên gửi một khối ACK cùng với các khối khác khi có các gói tin ack-eliciting mới cần được xác nhận. Khi chỉ có các gói tin non-ack-eliciting cần được xác nhận, một endpoint CÓ THỂ chọn không gửi khối ACK cùng với các khối đисходящих cho đến khi nhận được một gói tin ack-eliciting.

Một endpoint chỉ gửi các gói non-ack-eliciting có thể chọn thỉnh thoảng thêm một khối ack-eliciting vào các gói đó để đảm bảo rằng nó nhận được một acknowledgment. Trong trường hợp đó, một endpoint KHÔNG ĐƯỢC gửi một khối ack-eliciting trong tất cả các gói mà nếu không sẽ là non-ack-eliciting, để tránh vòng lặp phản hồi vô hạn của các acknowledgment.

Để hỗ trợ phát hiện mất gói tin tại bên gửi, một endpoint nên tạo và gửi một khối ACK không chậm trễ khi nó nhận được một gói tin ack-eliciting trong bất kỳ trường hợp nào sau đây:

  • Khi gói tin nhận được có số thứ tự gói tin nhỏ hơn một gói tin ack-eliciting khác đã được nhận

  • Khi gói tin có số thứ tự gói lớn hơn gói tin ack-eliciting có số thứ tự cao nhất đã được nhận và có các gói tin bị thiếu giữa gói tin đó và gói tin này.

  • Khi cờ ack-immediate trong header gói tin được thiết lập

Các thuật toán được kỳ vọng sẽ có khả năng chống chịu với những receiver không tuân theo hướng dẫn được đưa ra ở trên. Tuy nhiên, một implementation chỉ nên lệch khỏi những yêu cầu này sau khi xem xét cẩn thận các tác động hiệu suất của thay đổi, đối với các kết nối được thực hiện bởi endpoint và đối với những người dùng khác của mạng.

ACK Frequency

Bên nhận xác định tần suất gửi xác nhận để phản hồi các gói tin yêu cầu ack. Việc xác định này liên quan đến sự đánh đổi.

Các endpoint dựa vào việc xác nhận kịp thời để phát hiện mất mát. Các bộ điều khiển tắc nghẽn dựa trên cửa sổ dựa vào xác nhận để quản lý cửa sổ tắc nghẽn của chúng. Trong cả hai trường hợp, việc trì hoãn xác nhận có thể ảnh hưởng xấu đến hiệu suất.

Mặt khác, việc giảm tần suất các gói tin chỉ mang thông tin xác nhận sẽ làm giảm chi phí truyền và xử lý gói tin tại cả hai điểm cuối. Điều này có thể cải thiện thông lượng kết nối trên các liên kết bất đối xứng nghiêm trọng và giảm lưu lượng traffic xác nhận sử dụng dung lượng đường truyền ngược; xem Mục 3 của RFC 3449.

Một receiver nên gửi một ACK block sau khi nhận được ít nhất hai gói tin ack-eliciting. Khuyến nghị này mang tính tổng quát và nhất quán với các khuyến nghị cho hành vi TCP endpoint RFC 5681. Hiểu biết về điều kiện mạng, kiến thức về bộ điều khiển tắc nghẽn của peer, hoặc nghiên cứu và thử nghiệm sâu hơn có thể đề xuất các chiến lược acknowledgment thay thế với đặc tính hiệu suất tốt hơn.

Bên nhận có thể xử lý nhiều gói tin có sẵn trước khi quyết định có gửi khối ACK để phản hồi hay không. Nói chung, bên nhận không nên trì hoãn ACK quá RTT / 6, hoặc tối đa 150 ms.

Cờ ack-immediate trong header của data packet là một yêu cầu để receiver gửi ack ngay sau khi nhận được, có thể trong vòng vài ms. Nói chung, receiver không nên trì hoãn immediate ACK quá RTT / 16, hoặc tối đa 5 ms.

Immediate ACK Flag

Bên nhận không biết kích thước send window của bên gửi, và do đó không biết phải trì hoãn bao lâu trước khi gửi một ACK. Cờ immediate ACK trong header của gói dữ liệu là một cách quan trọng để duy trì thông lượng tối đa bằng cách giảm thiểu RTT hiệu quả. Cờ immediate ACK là header byte 13, bit 0, tức là (header[13] & 0x01). Khi được thiết lập, một ACK ngay lập tức sẽ được yêu cầu. Xem phần short header ở trên để biết chi tiết.

Có một số chiến lược có thể mà người gửi có thể sử dụng để xác định khi nào cần đặt cờ immediate-ack:

  • Được đặt một lần sau mỗi N gói tin, với N là một số nhỏ
  • Được đặt trên gói tin cuối cùng trong một chuỗi gói tin
  • Được đặt khi cửa sổ gửi gần đầy, ví dụ trên 2/3 dung lượng
  • Được đặt trên tất cả các gói tin có chứa các fragment được truyền lại

Các flag ACK ngay lập tức chỉ nên cần thiết trên các gói dữ liệu chứa các thông điệp I2NP hoặc các phân đoạn thông điệp.

ACK Block Size

Khi một khối ACK được gửi, một hoặc nhiều phạm vi của các gói tin đã được xác nhận sẽ được bao gồm. Việc bao gồm các xác nhận cho các gói tin cũ hơn sẽ giảm khả năng truyền lại giả mạo do mất các khối ACK đã gửi trước đó, với cái giá là các khối ACK lớn hơn.

Các khối ACK phải luôn xác nhận các gói tin được nhận gần đây nhất, và càng nhiều gói tin bị lộn xộn thứ tự thì việc gửi khối ACK cập nhật một cách nhanh chóng càng quan trọng, để ngăn peer tuyên bố một gói tin bị mất và retransmit giả một cách không cần thiết các khối mà nó chứa. Một khối ACK phải vừa trong một gói tin duy nhất. Nếu không vừa, thì các phạm vi cũ hơn (những phạm vi có số gói tin nhỏ nhất) sẽ bị bỏ qua.

Một receiver giới hạn số lượng ACK ranges mà nó ghi nhớ và gửi trong các ACK blocks, vừa để hạn chế kích thước của ACK blocks vừa để tránh cạn kiệt tài nguyên. Sau khi nhận được acknowledgments cho một ACK block, receiver nên ngừng theo dõi những ACK ranges đã được acknowledged đó. Senders có thể mong đợi acknowledgments cho hầu hết các packets, nhưng giao thức này không đảm bảo việc nhận được acknowledgment cho mọi packet mà receiver xử lý.

Có thể việc giữ lại nhiều dải ACK có thể khiến cho một khối ACK trở nên quá lớn. Bên nhận có thể loại bỏ các Dải ACK chưa được xác nhận để giới hạn kích thước khối ACK, với chi phí là tăng số lần truyền lại từ bên gửi. Điều này là cần thiết nếu một khối ACK quá lớn để có thể vừa trong một gói tin. Các bên nhận cũng có thể giới hạn kích thước khối ACK hơn nữa để bảo tồn không gian cho các khối khác hoặc để giới hạn băng thông mà các xác nhận tiêu thụ.

Bên nhận phải giữ lại phạm vi ACK trừ khi nó có thể đảm bảo rằng nó sẽ không chấp nhận các gói tin có số thứ tự trong phạm vi đó sau này. Duy trì số gói tin tối thiểu tăng lên khi các phạm vi bị loại bỏ là một cách để đạt được điều này với trạng thái tối thiểu.

Bên nhận có thể loại bỏ tất cả các dải ACK, nhưng họ phải giữ lại số gói tin lớn nhất đã được xử lý thành công, vì nó được sử dụng để khôi phục số gói tin từ các gói tin tiếp theo.

Phần sau đây mô tả một phương pháp mẫu để xác định những packet nào cần xác nhận trong mỗi ACK block. Mặc dù mục tiêu của thuật toán này là tạo ra một xác nhận cho mỗi packet được xử lý, việc mất xác nhận vẫn có thể xảy ra.

Limiting Ranges by Tracking ACK Blocks

Khi một gói tin chứa khối ACK được gửi, trường Ack Through trong khối đó có thể được lưu. Khi một gói tin chứa khối ACK được xác nhận, bên nhận có thể ngừng xác nhận các gói tin nhỏ hơn hoặc bằng trường Ack Through trong khối ACK đã gửi.

Một receiver chỉ gửi các packet không yêu cầu ack, chẳng hạn như các ACK block, có thể không nhận được acknowledgment trong một thời gian dài. Điều này có thể khiến receiver phải duy trì trạng thái cho một số lượng lớn ACK block trong thời gian dài, và các ACK block mà nó gửi có thể không cần thiết phải lớn. Trong trường hợp như vậy, receiver có thể thỉnh thoảng gửi một PING hoặc block nhỏ khác yêu cầu ack, chẳng hạn như một lần mỗi round trip, để yêu cầu một ACK từ peer.

Trong các trường hợp không có mất mát ACK block, thuật toán này cho phép tối thiểu 1 RTT của việc sắp xếp lại thứ tự. Trong các trường hợp có mất mát ACK block và sắp xếp lại thứ tự, cách tiếp cận này không đảm bảo rằng mọi xác nhận đều được người gửi nhìn thấy trước khi nó không còn được bao gồm trong ACK block. Các gói tin có thể được nhận không theo thứ tự, và tất cả các ACK block tiếp theo chứa chúng có thể bị mất. Trong trường hợp này, thuật toán khôi phục mất mát có thể gây ra các lần truyền lại giả, nhưng người gửi sẽ tiếp tục tiến triển về phía trước.

Congestion

Các transport I2P không đảm bảo việc chuyển phát tin nhắn I2NP theo thứ tự. Do đó, việc mất một tin nhắn Data chứa một hoặc nhiều tin nhắn I2NP hoặc fragment KHÔNG ngăn cản các tin nhắn I2NP khác được chuyển phát; không có hiện tượng head-of-line blocking. Các implementation nên tiếp tục gửi tin nhắn mới trong giai đoạn khôi phục mất mát nếu send window cho phép.

Retransmission

Người gửi không nên giữ lại toàn bộ nội dung của một thông điệp để truyền lại một cách giống hệt (trừ các thông điệp handshake, xem phần trên). Người gửi phải lắp ráp các thông điệp chứa thông tin cập nhật (ACK, NACK, và dữ liệu chưa được xác nhận) mỗi lần gửi thông điệp. Người gửi nên tránh truyền lại thông tin từ các thông điệp một khi chúng đã được xác nhận. Điều này bao gồm các thông điệp được xác nhận sau khi bị tuyên bố là mất, có thể xảy ra khi có sự sắp xếp lại thứ tự trong mạng.

Window

Chưa xác định. Hướng dẫn tổng quát có thể được tìm thấy trong RFC 9002.

Connection Migration

IP hoặc cổng của một peer có thể thay đổi trong suốt thời gian tồn tại của một phiên kết nối. Việc thay đổi IP có thể do xoay vòng địa chỉ tạm thời IPv6, thay đổi IP định kỳ do nhà cung cấp dịch vụ Internet, client di động chuyển đổi giữa IP WiFi và cellular, hoặc các thay đổi mạng cục bộ khác. Việc thay đổi cổng có thể do NAT tái ràng buộc sau khi ràng buộc trước đó hết thời gian.

IP hoặc cổng của một peer có thể xuất hiện thay đổi do các cuộc tấn công trên đường truyền và ngoài đường truyền khác nhau, bao gồm việc sửa đổi hoặc chèn các gói tin.

Migration kết nối là quá trình mà một source endpoint mới (IP+port) được xác thực, trong khi ngăn chặn những thay đổi không được xác thực. Quá trình này là phiên bản đơn giản hóa của quá trình được định nghĩa trong QUIC RFC 9000. Quá trình này chỉ được định nghĩa cho giai đoạn dữ liệu của một phiên. Migration không được phép trong quá trình handshake. Tất cả các gói handshake phải được xác minh là từ cùng một IP và port như các gói đã gửi và nhận trước đó. Nói cách khác, IP và port của một peer phải không đổi trong suốt quá trình handshake.

Threat Model

(Chuyển thể từ QUIC RFC 9000)

Ghi chú

Một peer có thể giả mạo địa chỉ nguồn của mình để khiến một endpoint gửi lượng dữ liệu quá mức đến một host không sẵn sàng. Nếu endpoint gửi nhiều dữ liệu hơn đáng kể so với peer giả mạo, connection migration có thể được sử dụng để khuếch đại khối lượng dữ liệu mà kẻ tấn công có thể tạo ra hướng về nạn nhân.

Phân mảnh Session Confirmed

Một kẻ tấn công trên đường truyền có thể gây ra việc di chuyển kết nối giả mạo bằng cách sao chép và chuyển tiếp một gói tin với địa chỉ giả mạo sao cho nó đến trước gói tin gốc. Gói tin với địa chỉ giả mạo sẽ được xem như đến từ một kết nối đang di chuyển, và gói tin gốc sẽ được xem như bản sao và bị loại bỏ. Sau một lần di chuyển giả mạo, việc xác thực địa chỉ nguồn sẽ thất bại vì thực thể tại địa chỉ nguồn không có các khóa mật mã cần thiết để đọc hoặc phản hồi Path Challenge được gửi đến nó ngay cả khi nó muốn làm vậy.

Off-Path Packet Forwarding

Kẻ tấn công ngoài đường truyền có thể quan sát các gói tin có thể chuyển tiếp bản sao của các gói tin chính thức đến các điểm cuối. Nếu gói tin sao chép đến trước gói tin chính thức, điều này sẽ xuất hiện như một sự rebinding NAT. Bất kỳ gói tin chính thức nào sẽ bị loại bỏ như một bản sao. Nếu kẻ tấn công có thể tiếp tục chuyển tiếp các gói tin, nó có thể có khả năng gây ra việc di chuyển đến một đường truyền qua kẻ tấn công. Điều này đặt kẻ tấn công vào đường truyền, cho nó khả năng quan sát hoặc loại bỏ tất cả các gói tin tiếp theo.

Privacy Implications

QUIC RFC 9000 quy định thay đổi ID kết nối khi thay đổi đường dẫn mạng. Việc sử dụng ID kết nối ổn định trên nhiều đường dẫn mạng sẽ cho phép một người quan sát thụ động liên kết hoạt động giữa các đường dẫn đó. Một endpoint di chuyển giữa các mạng có thể không muốn hoạt động của họ được liên kết bởi bất kỳ thực thể nào khác ngoài đối tác của họ. Tuy nhiên, QUIC không mã hóa ID kết nối trong header. SSU2 thì có làm điều đó, vì vậy việc rò rỉ quyền riêng tư sẽ yêu cầu người quan sát thụ động cũng phải có quyền truy cập vào cơ sở dữ liệu mạng để lấy introduction key cần thiết để giải mã ID kết nối. Ngay cả với introduction key, đây không phải là một cuộc tấn công mạnh, và chúng tôi không thay đổi ID kết nối sau khi di chuyển trong SSU2, vì điều này sẽ là một biến chứng đáng kể.

Initiating Path Validation

Trong giai đoạn dữ liệu, các peer phải kiểm tra IP nguồn và cổng của mỗi gói dữ liệu nhận được. Nếu IP hoặc cổng khác với những gì đã nhận trước đó, VÀ gói tin không phải là số gói trùng lặp, VÀ gói tin giải mã thành công, phiên sẽ chuyển vào giai đoạn xác thực đường dẫn.

Thêm vào đó, một peer phải xác minh rằng IP và port mới là hợp lệ theo các quy tắc xác thực cục bộ (không bị chặn, không phải port bất hợp pháp, v.v.). Các peer KHÔNG bắt buộc phải hỗ trợ di chuyển giữa IPv4 và IPv6, và có thể coi IP mới trong họ địa chỉ khác là không hợp lệ, vì đây không phải là hành vi mong đợi và có thể thêm độ phức tạp triển khai đáng kể. Khi nhận được một packet từ IP/port không hợp lệ, một triển khai có thể đơn giản loại bỏ nó, hoặc có thể khởi tạo xác thực đường dẫn với IP/port cũ.

Khi bước vào giai đoạn xác thực đường dẫn, thực hiện các bước sau:

  • Khởi động bộ đếm thời gian timeout xác thực đường dẫn trong vài giây, hoặc gấp vài lần RTO hiện tại (TBD)
  • Giảm cửa sổ tắc nghẽn xuống mức tối thiểu
  • Giảm PMTU xuống mức tối thiểu (1280)
  • Gửi một gói dữ liệu chứa khối Path Challenge, khối Address (chứa IP/port mới), và thường là khối ACK, đến IP và port mới. Gói tin này sử dụng cùng connection ID và khóa mã hóa như phiên hiện tại. Dữ liệu khối Path Challenge phải chứa đủ entropy (ít nhất 8 byte) để không thể bị giả mạo.
  • Tùy chọn, cũng gửi Path Challenge đến IP/port cũ, với dữ liệu khối khác. Xem bên dưới.
  • Khởi động bộ đếm thời gian timeout Path Response dựa trên RTO hiện tại (thường là RTT + bội số của RTTdev)

Trong khi ở giai đoạn xác thực đường dẫn, phiên có thể tiếp tục xử lý các gói tin đến. Dù từ IP/port cũ hay mới. Phiên cũng có thể tiếp tục gửi và xác nhận các gói dữ liệu. Tuy nhiên, congestion window và PMTU phải được giữ ở giá trị tối thiểu trong giai đoạn xác thực đường dẫn, để ngăn chặn việc bị sử dụng cho các cuộc tấn công từ chối dịch vụ bằng cách gửi lưu lượng lớn đến một địa chỉ giả mạo.

Một implementation có thể, nhưng không bắt buộc, cố gắng xác thực nhiều đường dẫn cùng lúc. Điều này có lẽ không đáng để tăng thêm độ phức tạp. Nó có thể, nhưng không bắt buộc, ghi nhớ một IP/port trước đó đã được xác thực, và bỏ qua việc xác thực đường dẫn nếu một peer quay trở lại IP/port trước đó của nó.

Nếu nhận được Path Response chứa dữ liệu giống hệt như đã gửi trong Path Challenge, thì Path Validation đã thành công. Địa chỉ IP/cổng nguồn của thông điệp Path Response không bắt buộc phải giống với địa chỉ mà Path Challenge đã được gửi tới.

Nếu không nhận được Path Response trước khi bộ đếm thời gian Path Response hết hạn, hãy gửi một Path Challenge khác và nhân đôi bộ đếm thời gian Path Response.

Nếu không nhận được Path Response trước khi hết hạn bộ đếm thời gian Path Validation, thì Path Validation đã thất bại.

Message Contents

Các thông điệp Data nên chứa các khối sau đây. Thứ tự không được chỉ định ngoại trừ việc Padding phải ở cuối:

  • Khối Path Validation hoặc Path Response. Path Validation chứa dữ liệu mờ đục, khuyến nghị tối thiểu 8 byte. Path Response chứa dữ liệu từ Path Validation.
  • Khối Address chứa địa chỉ IP rõ ràng của người nhận
  • Khối DateTime
  • Khối ACK
  • Khối Padding

Không khuyến nghị bao gồm bất kỳ khối nào khác (ví dụ, I2NP) trong thông điệp.

Được phép bao gồm một khối Path Validation trong thông điệp chứa Path Response, để khởi tạo một quá trình xác thực theo hướng ngược lại.

Các khối Path Challenge và Path Response là ACK-eliciting. Path Challenge sẽ được ACK bằng một thông điệp Data chứa các khối Path Response và ACK. Path Response nên được ACK bằng một thông điệp Data chứa một khối ACK.

Routing during Path Validation

Đặc tả QUIC không rõ ràng về việc gửi các gói dữ liệu đến đâu trong quá trình xác thực đường dẫn - đến IP/port cũ hay mới? Cần có sự cân bằng giữa việc phản hồi nhanh chóng với các thay đổi IP/port và không gửi lưu lượng đến các địa chỉ giả mạo. Ngoài ra, các gói giả mạo không được phép tác động đáng kể đến một phiên hiện có. Các thay đổi chỉ về port có thể do NAT rebinding sau một khoảng thời gian không hoạt động; các thay đổi IP có thể xảy ra trong các giai đoạn lưu lượng cao theo một hoặc cả hai hướng.

Các chiến lược có thể được nghiên cứu và cải tiến. Các khả năng bao gồm:

  • Không gửi các gói dữ liệu đến IP/port mới cho đến khi được xác thực
  • Tiếp tục gửi các gói dữ liệu đến IP/port cũ cho đến khi IP/port mới được xác thực
  • Đồng thời xác thực lại IP/port cũ
  • Không gửi bất kỳ dữ liệu nào cho đến khi IP/port cũ hoặc mới được xác thực
  • Các chiến lược khác nhau cho việc thay đổi chỉ port so với việc thay đổi IP
  • Các chiến lược khác nhau cho việc thay đổi IPv6 trong cùng /32, có thể do việc luân chuyển địa chỉ tạm thời

Responding to Path Challenge

Khi nhận được Path Challenge, peer phải phản hồi bằng một data packet chứa Path Response, với dữ liệu từ Path Challenge. TODO Có thể???: Path Response phải được gửi đến IP/port mà từ đó Path Challenge được nhận. Điều này KHÔNG NHẤT THIẾT là IP/port đã được thiết lập trước đó cho peer. Điều này đảm bảo rằng việc xác thực đường dẫn bởi một peer chỉ thành công nếu đường dẫn hoạt động theo cả hai hướng. Xem phần Validation after Local Change bên dưới.

Trừ khi IP/port khác với IP/port đã biết trước đó của peer, hãy xử lý Path Challenge như một ping đơn giản và chỉ cần phản hồi vô điều kiện bằng Path Response. Bên nhận không lưu giữ hoặc thay đổi bất kỳ trạng thái nào dựa trên Path Challenge nhận được. Nếu IP/port khác biệt, peer phải xác minh rằng IP và port mới là hợp lệ theo các quy tắc xác thực cục bộ (không bị chặn, không phải port bất hợp pháp, v.v.). Các peer KHÔNG được yêu cầu hỗ trợ phản hồi cross-address-family giữa IPv4 và IPv6, và có thể xử lý IP mới trong họ địa chỉ khác như không hợp lệ, vì đây không phải là hành vi mong đợi.

Trừ khi bị giới hạn bởi kiểm soát tắc nghẽn, Path Response nên được gửi ngay lập tức. Các triển khai nên thực hiện các biện pháp để giới hạn tốc độ Path Response hoặc băng thông được sử dụng nếu cần thiết.

Một khối Path Challenge thường đi kèm với một khối Address trong cùng một thông điệp. Nếu khối address chứa một IP/port mới, một peer có thể xác thực IP/port đó và bắt đầu kiểm tra peer đối với IP/port mới đó, với session peer hoặc bất kỳ peer nào khác. Nếu peer cho rằng nó bị firewall, và chỉ có port thay đổi, sự thay đổi này có thể do NAT rebinding, và việc kiểm tra peer thêm có thể không cần thiết.

Successful Path Validation

Khi xác thực đường dẫn thành công, kết nối sẽ được di chuyển hoàn toàn sang IP/port mới. Khi thành công:

  • Thoát khỏi giai đoạn xác thực đường dẫn
  • Tất cả các gói tin được gửi đến IP và cổng mới.
  • Các hạn chế về cửa sổ tắc nghẽn và PMTU được gỡ bỏ, và chúng được phép tăng lên. Không đơn giản khôi phục chúng về các giá trị cũ, vì đường dẫn mới có thể có các đặc điểm khác.
  • Nếu IP thay đổi, đặt RTT tính toán và RTO về các giá trị ban đầu. Bởi vì các thay đổi chỉ cổng thường là kết quả của việc tái ràng buộc NAT hoặc hoạt động middlebox khác, peer có thể thay vào đó giữ lại trạng thái kiểm soát tắc nghẽn và ước tính round-trip trong những trường hợp đó thay vì quay về các giá trị ban đầu.
  • Xóa (vô hiệu hóa) bất kỳ token nào đã gửi hoặc nhận cho IP/cổng cũ (tùy chọn)
  • Gửi một khối token mới cho IP/cổng mới (tùy chọn)

Cancelling Path Validation

Trong giai đoạn xác thực đường dẫn, bất kỳ gói tin hợp lệ, không trùng lặp nào được nhận từ IP/port cũ và được giải mã thành công sẽ khiến Path Validation bị hủy. Điều quan trọng là việc hủy xác thực đường dẫn, do một gói tin giả mạo gây ra, không được gây ra việc chấm dứt hoặc gián đoạn đáng kể một phiên hợp lệ.

Về việc hủy bỏ xác thực đường dẫn:

  • Thoát khỏi giai đoạn xác thực đường dẫn
  • Tất cả các gói tin được gửi đến IP và port cũ.
  • Các hạn chế về congestion window và PMTU được gỡ bỏ, và chúng được phép tăng lên, hoặc tùy chọn, khôi phục các giá trị trước đó
  • Truyền lại bất kỳ gói tin dữ liệu nào đã được gửi trước đó đến IP/port mới sang IP/port cũ.

Failed Path Validation

Điều quan trọng là việc xác thực đường dẫn thất bại, do gói tin giả mạo gây ra, không được làm cho một phiên hợp lệ bị chấm dứt hoặc bị gián đoạn đáng kể.

Khi xác thực đường dẫn thất bại:

  • Thoát khỏi giai đoạn xác thực đường dẫn
  • Tất cả các gói tin được gửi đến IP và port cũ.
  • Các hạn chế về congestion window và PMTU được gỡ bỏ, và chúng được phép tăng lên.
  • Tùy chọn, bắt đầu xác thực đường dẫn trên IP và port cũ. Nếu thất bại, chấm dứt phiên.
  • Nếu không, tuân theo các quy tắc timeout và chấm dứt phiên tiêu chuẩn.
  • Truyền lại bất kỳ gói tin dữ liệu nào đã được gửi trước đó đến IP/port mới sang IP/port cũ.

Validation After Local Change

Quy trình trên được định nghĩa cho các peer nhận được gói tin từ IP/cổng đã thay đổi. Tuy nhiên, nó cũng có thể được khởi tạo theo hướng ngược lại, bởi một peer phát hiện ra rằng IP hoặc cổng của mình đã thay đổi. Một peer có thể phát hiện được rằng IP cục bộ của mình đã thay đổi; tuy nhiên, khả năng phát hiện cổng của mình thay đổi do NAT rebinding thì thấp hơn nhiều. Do đó, điều này là tùy chọn.

Khi nhận được path challenge từ một peer mà địa chỉ IP hoặc port đã thay đổi, peer kia nên khởi tạo một path challenge theo hướng ngược lại.

Bảo mật Relay

Các khối Path Validation và Path Response có thể được sử dụng bất kỳ lúc nào như các gói tin Ping/Pong. Việc nhận khối Path Validation không thay đổi bất kỳ trạng thái nào tại máy nhận, trừ khi nhận được từ một IP/port khác.

Multiple Sessions

Các peer không nên thiết lập nhiều phiên làm việc với cùng một peer, dù là SSU 1 hay 2, hoặc với cùng một địa chỉ IP hoặc các địa chỉ IP khác nhau. Tuy nhiên, điều này có thể xảy ra do lỗi, hoặc do thông điệp kết thúc phiên trước đó bị mất, hoặc trong tình huống race condition khi thông điệp kết thúc chưa đến.

Nếu Bob đã có một phiên kết nối với Alice, khi Bob nhận được Session Confirmed từ Alice, hoàn thành quá trình bắt tay và thiết lập một phiên mới, Bob nên:

  • Di chuyển bất kỳ tin nhắn I2NP gửi đi chưa được gửi hoặc chưa được xác nhận nào từ phiên cũ sang phiên mới
  • Gửi lệnh kết thúc với mã lý do 22 trên phiên cũ
  • Xóa phiên cũ và thay thế bằng phiên mới

Session Termination

Bảo mật Kiểm tra Peer

Các session trong giai đoạn handshake thường được kết thúc đơn giản bằng cách timeout, hoặc không phản hồi thêm. Tùy chọn, chúng có thể được kết thúc bằng cách bao gồm một Termination block trong phản hồi, nhưng hầu hết các lỗi không thể phản hồi được do thiếu các khóa mật mã. Ngay cả khi có khóa có sẵn cho một phản hồi bao gồm termination block, thường không đáng để tiêu tốn CPU để thực hiện DH cho phản hồi. Một ngoại lệ CÓ THỂ là một Termination block trong tin nhắn retry, việc này ít tốn kém để tạo ra.

Mục Tiêu Thiết Kế Relay và Peer Test

Các phiên trong giai đoạn dữ liệu được chấm dứt bằng cách gửi một thông điệp dữ liệu bao gồm một khối Termination. Thông điệp này cũng nên bao gồm một khối ACK. Nó có thể, nếu phiên đã hoạt động đủ lâu để một token đã gửi trước đó đã hết hạn hoặc sắp hết hạn, bao gồm một khối New Token. Thông điệp này không yêu cầu xác nhận. Khi nhận được một khối Termination với bất kỳ lý do nào ngoại trừ “Termination Received”, peer phản hồi bằng một thông điệp dữ liệu chứa một khối Termination với lý do “Termination Received”.

Sau khi gửi hoặc nhận một Termination block, phiên sẽ chuyển vào giai đoạn đóng kết nối trong một khoảng thời gian tối đa nào đó (chưa xác định). Trạng thái đóng kết nối là cần thiết để bảo vệ chống lại việc mất packet chứa Termination block, và các packet đang truyền theo hướng ngược lại. Trong giai đoạn đóng kết nối, không có yêu cầu phải xử lý bất kỳ packet nhận được bổ sung nào. Một phiên ở trạng thái đóng kết nối sẽ gửi một packet chứa Termination block để phản hồi bất kỳ packet đến nào mà nó cho là thuộc về phiên đó. Một phiên nên giới hạn tỷ lệ mà nó tạo ra các packet ở trạng thái đóng kết nối. Ví dụ, một phiên có thể chờ một số lượng packet nhận được hoặc khoảng thời gian ngày càng tăng trước khi phản hồi các packet nhận được.

Để giảm thiểu trạng thái mà một router duy trì cho một phiên đang đóng, các phiên có thể, nhưng không bắt buộc, gửi chính xác cùng một gói tin với cùng số hiệu gói tin như vậy để phản hồi bất kỳ gói tin nhận được nào. Lưu ý: Việc cho phép truyền lại gói tin chấm dứt là một ngoại lệ đối với yêu cầu rằng một số hiệu gói tin mới phải được sử dụng cho mỗi gói tin. Việc gửi các số hiệu gói tin mới chủ yếu có lợi cho việc khôi phục mất mát và kiểm soát tắc nghẽn, những điều này không được mong đợi sẽ có liên quan đối với một kết nối đã đóng. Việc truyền lại gói tin cuối cùng đòi hỏi ít trạng thái hơn.

Sau khi nhận được khối Termination với lý do “Termination Received”, phiên có thể thoát khỏi giai đoạn đóng.

Cleanup

Khi có bất kỳ sự kết thúc bình thường hay bất thường nào, các router nên xóa sạch mọi dữ liệu tạm thời trong bộ nhớ, bao gồm các khóa tạm thời handshake, khóa mã hóa đối xứng và thông tin liên quan.

MTU

Yêu cầu có thể khác nhau, dựa trên việc địa chỉ được công bố có được chia sẻ với SSU 1 hay không. Mức tối thiểu IPv4 hiện tại của SSU 1 là 620, điều này chắc chắn là quá nhỏ.

MTU tối thiểu của SSU2 là 1280 cho cả IPv4 và IPv6, giống như được chỉ định trong RFC 9000. Xem bên dưới. Bằng cách tăng MTU tối thiểu, các tunnel message 1 KB và tunnel build message ngắn sẽ vừa trong một datagram, giảm đáng kể lượng phân mảnh thông thường. Điều này cũng cho phép tăng kích thước tối đa của I2NP message. Các streaming message 1820-byte sẽ vừa trong hai datagram.

Một router không được phép bật SSU2 hoặc công bố địa chỉ SSU2 trừ khi MTU cho địa chỉ đó ít nhất là 1280.

Các router phải công bố một MTU không mặc định trong mỗi địa chỉ router SSU hoặc SSU2.

Tóm tắt

Địa chỉ chia sẻ với SSU 1, phải tuân theo các quy tắc của SSU 1. IPv4: Mặc định và tối đa là 1484. Tối thiểu là 1292. (IPv4 MTU + 4) phải là bội số của 16. IPv6: Phải được công bố, tối thiểu là 1280 và tối đa là 1488. IPv6 MTU phải là bội số của 16.

Đảm bảo Giao hàng

IPv4: Mặc định và tối đa là 1500. Tối thiểu là 1280. IPv6: Mặc định và tối đa là 1500. Tối thiểu là 1280. Không có quy tắc bội số của 16, nhưng có lẽ nên là bội số của 2.

Noise Protocol Framework

Đối với SSU 1, Java I2P hiện tại thực hiện khám phá PMTU bằng cách bắt đầu với các gói tin nhỏ và tăng dần kích thước, hoặc tăng dựa trên kích thước gói tin nhận được. Phương pháp này thô sơ và làm giảm đáng kể hiệu quả. Việc tiếp tục tính năng này trong SSU 2 vẫn chưa được xác định.

Các nghiên cứu gần đây PMTU cho thấy rằng mức tối thiểu cho IPv4 là 1200 byte hoặc hơn sẽ hoạt động cho hơn 99% kết nối. QUIC RFC 9000 yêu cầu kích thước gói IP tối thiểu là 1280 byte.

trích dẫn RFC 9000:

Kích thước datagram tối đa được định nghĩa là kích thước lớn nhất của UDP payload có thể được gửi qua một đường dẫn mạng bằng cách sử dụng một datagram UDP duy nhất. QUIC KHÔNG ĐƯỢC sử dụng nếu đường dẫn mạng không thể hỗ trợ kích thước datagram tối đa ít nhất 1200 bytes.

QUIC giả định kích thước gói IP tối thiểu ít nhất là 1280 byte. Đây là kích thước tối thiểu của IPv6 [IPv6] và cũng được hỗ trợ bởi hầu hết các mạng IPv4 hiện đại. Giả định kích thước header IP tối thiểu là 40 byte cho IPv6 và 20 byte cho IPv4 cùng với kích thước header UDP là 8 byte, điều này dẫn đến kích thước datagram tối đa là 1232 byte cho IPv6 và 1252 byte cho IPv4. Do đó, các đường dẫn mạng IPv4 hiện đại và tất cả IPv6 được kỳ vọng có thể hỗ trợ QUIC.

Lưu ý: Yêu cầu hỗ trợ UDP payload 1200 bytes này giới hạn không gian có sẵn cho IPv6 extension headers xuống còn 32 bytes hoặc IPv4 options xuống còn 52 bytes nếu đường truyền chỉ hỗ trợ IPv6 minimum MTU là 1280 bytes. Điều này ảnh hưởng đến Initial packets và path validation.

kết thúc trích dẫn

Các Bổ Sung cho Framework

QUIC yêu cầu các datagram Initial theo cả hai hướng phải có ít nhất 1200 byte, để ngăn chặn các cuộc tấn công khuếch đại và đảm bảo PMTU hỗ trợ theo cả hai hướng.

Chúng ta có thể yêu cầu điều này cho Session Request và Session Created, với chi phí băng thông đáng kể. Có lẽ chúng ta chỉ có thể làm điều này nếu chúng ta không có token, hoặc sau khi nhận được thông báo Retry. TBD

QUIC yêu cầu rằng Bob không được gửi quá ba lần lượng dữ liệu đã nhận cho đến khi địa chỉ client được xác thực. SSU2 đáp ứng yêu cầu này một cách tự nhiên, bởi vì thông điệp Retry có kích thước tương đương với thông điệp Token Request, và nhỏ hơn thông điệp Session Request. Ngoài ra, thông điệp Retry chỉ được gửi một lần.

Ước tính chi phí xử lý

QUIC yêu cầu các thông điệp chứa các khối PATH_CHALLENGE hoặc PATH_RESPONSE phải có ít nhất 1200 byte, để ngăn chặn các cuộc tấn công khuếch đại và đảm bảo PMTU hỗ trợ nó trong cả hai hướng.

Chúng ta cũng có thể yêu cầu điều này, nhưng sẽ tốn khá nhiều băng thông. Tuy nhiên, những trường hợp này sẽ hiếm khi xảy ra. TBD

Max I2NP Message Size

IPv4: Không giả định phân mảnh IP. Header IP + datagram là 28 byte. Điều này giả định không có tùy chọn IPv4. Kích thước thông điệp tối đa là MTU - 28. Header giai đoạn dữ liệu là 16 byte và MAC là 16 byte, tổng cộng 32 byte. Kích thước payload là MTU - 60. Payload giai đoạn dữ liệu tối đa là 1440 cho MTU tối đa 1500. Payload giai đoạn dữ liệu tối đa là 1220 cho MTU tối thiểu 1280.

IPv6: Không cho phép phân mảnh IP. Header IP + datagram là 48 byte. Điều này giả định không có extension header IPv6. Kích thước thông điệp tối đa là MTU - 48. Header giai đoạn dữ liệu là 16 byte và MAC là 16 byte, tổng cộng 32 byte. Kích thước payload là MTU - 80. Payload giai đoạn dữ liệu tối đa là 1420 cho MTU tối đa 1500. Payload giai đoạn dữ liệu tối đa là 1200 cho MTU tối thiểu 1280.

Trong SSU 1, các hướng dẫn là giới hạn tối đa nghiêm ngặt khoảng 32 KB cho một thông điệp I2NP dựa trên tối đa 64 phân đoạn và MTU tối thiểu 620. Do chi phí phụ trội cho các LeaseSets được gói và các khóa phiên, giới hạn thực tế ở cấp ứng dụng thấp hơn khoảng 6KB, tức là khoảng 26KB. Giao thức SSU 1 cho phép 128 phân đoạn nhưng các triển khai hiện tại giới hạn ở 64 phân đoạn.

Bằng cách tăng MTU tối thiểu lên 1280, với payload của giai đoạn dữ liệu khoảng 1200, một thông điệp SSU 2 khoảng 76 KB có thể thực hiện được trong 64 fragment và 152 KB trong 128 fragment. Điều này dễ dàng cho phép tối đa 64 KB.

Do sự phân mảnh trong các tunnel và sự phân mảnh trong SSU 2, khả năng mất message tăng theo cấp số nhân với kích thước message. Chúng tôi tiếp tục khuyến nghị giới hạn thực tế khoảng 10 KB ở tầng ứng dụng cho các I2NP datagram.

Peer Test Process

Xem phần Bảo mật Peer Test ở trên để có phân tích về SSU1 Peer Test và các mục tiêu của SSU2 Peer Test.

Alice                     Bob                  Charlie
1. PeerTest ------------------->
                              Alice RI ------------------->
2.                          PeerTest ------------------->
3.                             <------------------ PeerTest
          <---------------- Charlie RI
4.      <------------------ PeerTest

5.      <----------------------------------------- PeerTest
6. PeerTest ----------------------------------------->
7.      <----------------------------------------- PeerTest

Khi bị Bob từ chối:

Alice                     Bob                  Charlie
1. PeerTest ------------------->
4.      <------------------ PeerTest (reject)

Khi bị Charlie từ chối:

Alice                     Bob                  Charlie
1. PeerTest ------------------->
                              Alice RI ------------------->
2.                          PeerTest ------------------->
3.                             <------------------ PeerTest (reject)
                        (optional: Bob could try another Charlie here)
4.      <------------------ PeerTest (reject)

LƯU Ý: RI có thể được gửi dưới dạng thông điệp I2NP Database Store trong các khối I2NP, hoặc dưới dạng các khối RI (nếu đủ nhỏ). Chúng có thể được chứa trong cùng các gói tin với các khối peer test, nếu đủ nhỏ.

Các thông điệp 1-4 đang trong phiên sử dụng các khối Peer Test trong thông điệp Data. Các thông điệp 5-7 đang ngoài phiên sử dụng các khối Peer Test trong thông điệp Peer Test.

GHI CHÚ: Như trong SSU 1, thông điệp 4 và 5 có thể đến theo bất kỳ thứ tự nào. Thông điệp 5 và/hoặc 7 có thể không được nhận hoàn toàn nếu Alice bị tường lửa chặn. Khi thông điệp 5 đến trước thông điệp 4, Alice không thể gửi ngay thông điệp 6, vì cô ấy chưa có intro key của Charlie để mã hóa header. Khi thông điệp 4 đến trước thông điệp 5, Alice không nên gửi ngay thông điệp 6, vì cô ấy nên đợi để xem liệu thông điệp 5 có đến mà không cần mở tường lửa với thông điệp 6.

MessagePathIntro Key
1A->B sessionin-session
2B->C sessionin-session
3C->B sessionin-session
4B->A sessionin-session
5C->AAlice
6A->CCharlie
7C->AAlice

Versions

Kiểm tra peer (nút mạng) giữa các phiên bản khác nhau không được hỗ trợ. Kết hợp phiên bản duy nhất được cho phép là khi tất cả các peer đều sử dụng phiên bản 2.

Alice/BobBob/CharlieAlice/CharlieSupported
111SSU 1
112no, use 1/1/1
121no, Bob must s
122no, Bob must s
211no, Bob must s
212no, Bob must s
221no, use 2/2/2
222yes

Thiết lập Phiên

Tin nhắn 1-4 là trong phiên và được bao phủ bởi các quy trình ACK và truyền lại pha dữ liệu. Các khối Peer Test yêu cầu xác nhận (ack-eliciting).

Các thông điệp 5-7 có thể được truyền lại mà không thay đổi.

Header Gói Tin

Như trong SSU 1, việc kiểm thử các địa chỉ IPv6 được hỗ trợ, và giao tiếp Alice-Bob và Alice-Charlie có thể thực hiện qua IPv6, nếu Bob và Charlie chỉ ra sự hỗ trợ với khả năng ‘B’ trong địa chỉ IPv6 đã công bố của họ. Xem Proposal 126 để biết chi tiết.

Như trong SSU 1 trước phiên bản 0.9.50, Alice gửi yêu cầu đến Bob bằng cách sử dụng một phiên kết nối hiện có qua giao thức vận chuyển (IPv4 hoặc IPv6) mà cô ấy muốn kiểm tra. Khi Bob nhận được yêu cầu từ Alice qua IPv4, Bob phải chọn một Charlie có quảng cáo địa chỉ IPv4. Khi Bob nhận được yêu cầu từ Alice qua IPv6, Bob phải chọn một Charlie có quảng cáo địa chỉ IPv6. Việc giao tiếp thực tế giữa Bob-Charlie có thể thông qua IPv4 hoặc IPv6 (tức là độc lập với loại địa chỉ của Alice). Đây KHÔNG phải là hành vi của SSU 1 từ phiên bản 0.9.50, nơi cho phép các yêu cầu hỗn hợp IPv4/v6.

Processing by Bob

Không giống như trong SSU 1, Alice chỉ định IP và cổng kiểm tra được yêu cầu trong thông điệp 1. Bob nên xác thực IP và cổng này, và từ chối với mã 5 nếu không hợp lệ. Xác thực IP được khuyến nghị là, đối với IPv4, nó phải khớp với IP của Alice, và đối với IPv6, ít nhất 8 byte đầu tiên của IP phải khớp. Xác thực cổng nên từ chối các cổng đặc quyền và cổng cho các giao thức phổ biến.

Relay Process

Xem phần Bảo mật Relay ở trên để phân tích về SSU1 Relay và các mục tiêu cho SSU2 Relay.

Alice                         Bob                  Charlie
     lookup Bob RI

     SessionRequest -------------------->
          <------------  SessionCreated
     SessionConfirmed  ----------------->

1. RelayRequest ---------------------->
                                           Alice RI  ------------>
2.                                       RelayIntro ----------->
3.                                  <-------------- RelayResponse
4.      <-------------- RelayResponse

5.      <-------------------------------------------- HolePunch
6. SessionRequest -------------------------------------------->
7.      <-------------------------------------------- SessionCreated
8. SessionConfirmed ------------------------------------------>

Khi bị Bob từ chối:

Alice                         Bob                  Charlie
     lookup Bob RI

     SessionRequest -------------------->
          <------------  SessionCreated
     SessionConfirmed  ----------------->

1. RelayRequest ---------------------->
4.      <-------------- RelayResponse

Khi bị Charlie từ chối:

Alice                         Bob                  Charlie
     lookup Bob RI

     SessionRequest -------------------->
          <------------  SessionCreated
     SessionConfirmed  ----------------->

1. RelayRequest ---------------------->
                                           Alice RI  ------------>
2.                                       RelayIntro ----------->
3.                                  <-------------- RelayResponse
4.      <-------------- RelayResponse

LƯU Ý: RI có thể được gửi dưới dạng thông điệp I2NP Database Store trong các khối I2NP, hoặc dưới dạng khối RI (nếu đủ nhỏ). Chúng có thể được chứa trong cùng các gói tin với các khối relay, nếu đủ nhỏ.

Trong SSU 1, thông tin router của Charlie chứa IP, port, intro key, relay tag và thời gian hết hạn của từng introducer.

Trong SSU 2, thông tin router của Charlie chứa router hash, relay tag và thời hạn hết hiệu lực của mỗi introducer.

Alice nên giảm số lượng round trip cần thiết bằng cách đầu tiên chọn một introducer (Bob) mà cô ấy đã có kết nối. Thứ hai, nếu không có, hãy chọn một introducer mà cô ấy đã có router info.

Việc chuyển tiếp cross-version cũng nên được hỗ trợ nếu có thể. Điều này sẽ tạo điều kiện cho việc chuyển đổi dần dần từ SSU 1 sang SSU 2. Các kết hợp phiên bản được phép là (TODO):

Alice/BobBob/CharlieAlice/CharlieSupported
111SSU 1
112no, use 1/1/1
121yes?
122no, use 1/2/1
211yes?
212yes?
221no, use 2/2/2
222yes

Retransmissions

Relay Request, Relay Intro và Relay Response đều nằm trong phiên và được bao phủ bởi các quy trình ACK và truyền lại của giai đoạn dữ liệu. Các khối Relay Request, Relay Intro và Relay Response đều kích hoạt ack.

Hole punch có thể được truyền lại, như trong SSU 1.

IPv4/v6

Tất cả các tính năng của SSU 1 relay đều được hỗ trợ, bao gồm những tính năng được mô tả trong Proposal 158 và được hỗ trợ từ phiên bản 0.9.50. Các introduction IPv4 và IPv6 đều được hỗ trợ. Một Relay Request có thể được gửi qua phiên IPv4 cho một introduction IPv6, và một Relay Request có thể được gửi qua phiên IPv6 cho một introduction IPv4.

Processing by Alice

Sau đây là những điểm khác biệt so với SSU 1 và các khuyến nghị cho việc triển khai SSU 2.

Ghi chú

Trong SSU 1, việc giới thiệu tương đối ít tốn kém, và Alice thường gửi Relay Requests đến tất cả các introducer. Trong SSU 2, việc giới thiệu tốn kém hơn, vì trước tiên phải thiết lập kết nối với một introducer. Để giảm thiểu độ trễ và chi phí của việc giới thiệu, các bước xử lý được khuyến nghị như sau:

  • Bỏ qua bất kỳ introducer nào đã hết hạn dựa trên giá trị iexp trong địa chỉ
  • Nếu kết nối SSU2 đã được thiết lập tới một hoặc nhiều introducer, chọn một introducer và chỉ gửi Relay Request tới introducer đó.
  • Ngược lại, nếu Router Info được biết cục bộ cho một hoặc nhiều introducer, chọn một introducer và chỉ kết nối tới introducer đó.
  • Ngược lại, tra cứu Router Info cho tất cả introducer, kết nối tới introducer có Router Info được nhận đầu tiên.

Ghi chú

Trong cả SSU 1 và SSU 2, Relay Response và Hole Punch có thể được nhận theo thứ tự bất kỳ, hoặc có thể không được nhận chút nào.

Trong SSU 1, Alice thường nhận được Relay Response (1 RTT) trước Hole Punch (1 1/2 RTT). Điều này có thể không được ghi chép đầy đủ trong các đặc tả đó, nhưng Alice phải nhận được Relay Response từ Bob trước khi tiếp tục, để nhận được IP của Charlie. Nếu Hole Punch được nhận trước, Alice sẽ không nhận ra nó, vì nó không chứa dữ liệu và IP nguồn không được nhận dạng. Sau khi nhận được Relay Response, Alice nên đợi HOẶC nhận được Hole Punch từ Charlie, HOẶC một khoảng trễ ngắn (khuyến nghị 500 ms) trước khi bắt đầu handshake với Charlie.

Trong SSU 2, Alice thường sẽ nhận được Hole Punch (1 1/2 RTT) trước Relay Response (2 RTT). SSU 2 Hole Punch dễ xử lý hơn so với SSU 1, vì nó là một thông điệp đầy đủ với các connection ID được định nghĩa (được dẫn xuất từ relay nonce) và nội dung bao gồm IP của Charlie. Relay Response (thông điệp Data) và thông điệp Hole Punch chứa khối Relay Response đã ký giống hệt nhau. Do đó, Alice có thể bắt đầu quá trình handshake với Charlie sau KHI nhận được Hole Punch từ Charlie, HOẶC nhận được Relay Response từ Bob.

Việc xác minh chữ ký của Hole Punch bao gồm router hash của người giới thiệu (Bob). Nếu Relay Requests đã được gửi đến nhiều hơn một người giới thiệu, có một số tùy chọn để xác thực chữ ký:

  • Thử mỗi hash mà một yêu cầu đã được gửi tới
  • Sử dụng các nonce khác nhau cho mỗi introducer, và sử dụng điều đó để xác định introducer nào mà Hole Punch này đang phản hồi
  • Không xác thực lại chữ ký nếu nội dung giống hệt với nội dung trong Relay Response, nếu đã nhận được
  • Không xác thực chữ ký gì cả

Nếu Charlie ở phía sau một symmetric NAT, cổng được báo cáo của anh ta trong Relay Response và Hole Punch có thể không chính xác. Do đó, Alice nên kiểm tra cổng nguồn UDP của thông điệp Hole Punch, và sử dụng cổng đó nếu nó khác với cổng được báo cáo.

Tag Requests by Bob

Trong SSU 1, chỉ Alice mới có thể yêu cầu một tag, trong Session Request. Bob không bao giờ có thể yêu cầu tag, và Alice không thể relay cho Bob.

Trong SSU2, Alice thường yêu cầu một tag trong Session Request, nhưng cả Alice hoặc Bob cũng có thể yêu cầu một tag trong giai đoạn dữ liệu. Bob thường không bị firewall sau khi nhận được một yêu cầu đến, nhưng có thể xảy ra sau một relay, hoặc trạng thái của Bob có thể thay đổi, hoặc anh ta có thể yêu cầu một introducer cho loại địa chỉ khác (IPv4/v6). Vì vậy, trong SSU2, có thể cả Alice và Bob đồng thời làm relay cho bên kia.

Published Router Info

Address Properties

Các thuộc tính địa chỉ sau đây có thể được công bố, không thay đổi so với SSU 1, bao gồm các thay đổi trong Đề xuất 158 được hỗ trợ từ API 0.9.50:

  • caps: khả năng [B,C,4,6]

  • host: IP (IPv4 hoặc IPv6). Địa chỉ IPv6 rút gọn (với “::”) được cho phép. Có thể có hoặc không có nếu bị tường lửa chặn. Tên host không được phép.

  • iexp[0-2]: Thời hạn hết hiệu lực của introducer này. Các chữ số ASCII, tính bằng giây kể từ epoch. Chỉ có mặt nếu bị tường lửa chặn và cần có introducer. Tùy chọn (ngay cả khi có các thuộc tính khác của introducer này).

  • ihost[0-2]: IP của Introducer (IPv4 hoặc IPv6). Địa chỉ IPv6 rút gọn (với “::”) được cho phép. Chỉ có mặt nếu bị chặn bởi tường lửa và cần có introducer. Không cho phép tên máy chủ. Chỉ địa chỉ SSU.

  • ikey[0-2]: Khóa giới thiệu Base 64 của Introducer. Chỉ có mặt nếu bị tường lửa chặn và yêu cầu introducer. Chỉ dành cho địa chỉ SSU.

  • iport[0-2]: Cổng của introducer từ 1024 - 65535. Chỉ có mặt nếu bị chặn firewall và yêu cầu introducer. Chỉ dành cho địa chỉ SSU.

  • itag[0-2]: Tag của introducer 1 - (2**32 - 1) Các chữ số ASCII. Chỉ có mặt nếu bị firewall và cần introducer.

  • key: Khóa giới thiệu Base 64.

  • mtu: Tùy chọn. Xem phần MTU ở trên.

  • port: 1024 - 65535 Có thể có hoặc không có nếu bị tường lửa chặn.

Published Addresses

RouterAddress được công bố (một phần của RouterInfo) sẽ có định danh giao thức là “SSU” hoặc “SSU2”.

RouterAddress phải chứa ba tùy chọn để chỉ ra hỗ trợ SSU2:

  • s=(Base64 key) Khóa công khai tĩnh Noise hiện tại (s) cho RouterAddress này. Được mã hóa Base 64 sử dụng bảng chữ cái Base 64 chuẩn của I2P. 32 byte ở dạng nhị phân, 44 byte khi được mã hóa Base 64, khóa công khai X25519 little-endian.

  • i=(Base64 key) Khóa giới thiệu hiện tại để mã hóa các header cho RouterAddress này. Được mã hóa Base 64 sử dụng bảng chữ cái I2P Base 64 chuẩn. 32 byte ở dạng nhị phân, 44 byte khi được mã hóa Base 64, khóa ChaCha20 big-endian.

  • v=2 Phiên bản hiện tại (2). Khi được công bố dưới dạng “SSU”, hỗ trợ bổ sung cho phiên bản 1 được ngầm hiểu. Hỗ trợ cho các phiên bản tương lai sẽ sử dụng giá trị phân tách bằng dấu phẩy, ví dụ v=2,3 Implementation nên xác minh tính tương thích, bao gồm cả nhiều phiên bản nếu có dấu phẩy. Các phiên bản phân tách bằng dấu phẩy phải theo thứ tự số.

Alice phải xác minh rằng cả ba tùy chọn đều có mặt và hợp lệ trước khi kết nối bằng giao thức SSU2.

Khi được công bố là “SSU” với các tùy chọn “s”, “i”, và “v”, và với các tùy chọn “host” và “port”, router phải chấp nhận các kết nối đến trên host và port đó cho cả giao thức SSU và SSU2, và tự động phát hiện phiên bản giao thức.

Khi được công bố dưới dạng “SSU2” với các tùy chọn “s”, “i”, và “v”, và với các tùy chọn “host” và “port”, router sẽ chấp nhận các kết nối đến trên host và port đó chỉ dành cho giao thức SSU2.

Nếu một router hỗ trợ cả kết nối SSU1 và SSU2 nhưng không triển khai tính năng tự động phát hiện phiên bản cho các kết nối đến, nó phải quảng bá cả địa chỉ “SSU” và “SSU2”, và chỉ bao gồm các tùy chọn SSU2 trong địa chỉ “SSU2”. Router nên đặt giá trị cost thấp hơn (ưu tiên cao hơn) trong địa chỉ “SSU2” so với địa chỉ “SSU”, để SSU2 được ưu tiên.

Nếu nhiều SSU2 RouterAddresses (dưới dạng “SSU” hoặc “SSU2”) được công bố trong cùng một RouterInfo (cho các địa chỉ IP hoặc cổng bổ sung), tất cả các địa chỉ chỉ định cùng một cổng phải chứa các tùy chọn và giá trị SSU2 giống hệt nhau. Đặc biệt, tất cả phải chứa cùng một khóa tĩnh “s” và khóa giới thiệu “i”.

Introducers

Khi được xuất bản dưới dạng SSU hoặc SSU2 với introducers, các tùy chọn sau sẽ có mặt:

  • ih[0-2]=(Base64 hash) Một router hash cho introducer. Được mã hóa Base 64 sử dụng bảng chữ cái I2P Base 64 chuẩn. 32 byte ở dạng nhị phân, 44 byte khi được mã hóa Base 64

  • iexp[0-2]: Thời hạn hết hiệu lực của introducer này. Không thay đổi so với SSU 1.

  • itag[0-2]: Tag của Introducer 1 - (2**32 - 1) Không thay đổi so với SSU 1.

Các tùy chọn sau chỉ dành cho SSU và không được sử dụng cho SSU2. Trong SSU2, Alice lấy thông tin này từ RI của Charlie thay vào đó.

  • ihost[0-2]
  • ikey[0-2]
  • itag[0-2]

Một router không được phát hành host hoặc port trong địa chỉ khi phát hành introducers. Một router phải phát hành 4 và/hoặc 6 caps trong địa chỉ khi phát hành introducers để chỉ ra hỗ trợ cho IPv4 và/hoặc IPv6. Điều này giống như thực hành hiện tại đối với các địa chỉ SSU 1 gần đây.

Lưu ý: Nếu được xuất bản dưới dạng SSU, và có sự kết hợp giữa các introducer SSU 1 và SSU2, các introducer SSU 1 nên được đặt ở các chỉ số thấp hơn và các introducer SSU2 nên được đặt ở các chỉ số cao hơn, để tương thích với các router cũ hơn.

Unpublished SSU2 Address

Nếu Alice không công bố địa chỉ SSU2 của mình (dưới dạng “SSU” hoặc “SSU2”) cho các kết nối đến, cô ấy phải công bố một router address “SSU2” chỉ chứa static key và phiên bản SSU2 của mình, để Bob có thể xác thực key sau khi nhận được RouterInfo của Alice trong Session Confirmed phần 2.

  • s=(Base64 key) Như được định nghĩa ở trên cho các địa chỉ đã được xuất bản.

  • i=(Base64 key) Như đã định nghĩa ở trên cho các địa chỉ đã được công bố.

  • v=2 Như được định nghĩa ở trên cho các địa chỉ đã xuất bản.

Địa chỉ router này sẽ không chứa các tùy chọn “host” hoặc “port”, vì chúng không cần thiết cho các kết nối SSU2 outbound. Chi phí được công bố cho địa chỉ này không quan trọng nghiêm ngặt, vì nó chỉ dành cho inbound; tuy nhiên, có thể hữu ích cho các router khác nếu chi phí được đặt cao hơn (ưu tiên thấp hơn) so với các địa chỉ khác. Giá trị được đề xuất là 14.

Alice cũng có thể đơn giản thêm các tùy chọn “i”, “s” và “v” vào một địa chỉ “SSU” đã được xuất bản hiện có.

Tính toàn vẹn gói tin

Việc sử dụng cùng các khóa tĩnh cho NTCP2 và SSU2 là được phép, nhưng không được khuyến nghị.

Do việc lưu trữ cache của RouterInfos, các router không được xoay vòng static public key hoặc IV khi router đang hoạt động, cho dù có trong địa chỉ được công bố hay không. Các router phải lưu trữ bền vững key và IV này để tái sử dụng sau khi khởi động lại ngay lập tức, để các kết nối đến sẽ tiếp tục hoạt động, và thời gian khởi động lại không bị lộ. Các router phải lưu trữ bền vững, hoặc xác định bằng cách khác, thời gian tắt-máy lần cuối, để có thể tính toán thời gian downtime trước đó khi khởi động.

Tùy thuộc vào mối quan ngại về việc tiết lộ thời gian khởi động lại, các router có thể luân phiên khóa hoặc IV này khi khởi động nếu router trước đó đã ngừng hoạt động trong một thời gian dài (ít nhất vài ngày).

Nếu router có bất kỳ SSU2 RouterAddresses nào được công bố (dưới dạng SSU hoặc SSU2), thời gian downtime tối thiểu trước khi rotation nên dài hơn nhiều, ví dụ như một tháng, trừ khi địa chỉ IP cục bộ đã thay đổi hoặc router “rekeys”.

Nếu router có bất kỳ SSU RouterAddresses nào được xuất bản, nhưng không có SSU2 (dưới dạng SSU hoặc SSU2) thì thời gian downtime tối thiểu trước khi xoay vòng nên dài hơn, ví dụ một ngày, trừ khi địa chỉ IP cục bộ đã thay đổi hoặc router “rekeys”. Điều này áp dụng ngay cả khi địa chỉ SSU được xuất bản có introducers.

Nếu router không có bất kỳ RouterAddresses đã xuất bản nào (SSU, SSU2, hoặc SSU), thời gian ngừng hoạt động tối thiểu trước khi xoay vòng có thể ngắn đến hai giờ, ngay cả khi địa chỉ IP thay đổi, trừ khi router thực hiện “rekeys”.

Nếu router “rekeys” sang một Router Hash khác, nó cũng nên tạo ra một noise key và intro key mới.

Các triển khai phải nhận thức rằng việc thay đổi khóa công khai tĩnh hoặc IV sẽ ngăn cản các kết nối SSU2 đến từ các router đã cache RouterInfo cũ hơn. Việc xuất bản RouterInfo, lựa chọn tunnel peer (bao gồm cả OBGW và IB closest hop), lựa chọn zero-hop tunnel, lựa chọn transport, và các chiến lược triển khai khác phải tính đến điều này.

Việc xoay khóa intro tuân theo các quy tắc giống hệt như việc xoay khóa.

Lưu ý: Thời gian ngừng hoạt động tối thiểu trước khi rekeying có thể được điều chỉnh để đảm bảo sức khỏe mạng, và để ngăn chặn reseeding bởi một router ngừng hoạt động trong một khoảng thời gian vừa phải.

Identity Hiding

Khả năng phủ nhận không phải là mục tiêu. Xem tổng quan ở trên.

Mỗi pattern được gán các thuộc tính mô tả tính bảo mật được cung cấp cho khóa công khai tĩnh của bên khởi tạo và cho khóa công khai tĩnh của bên phản hồi. Các giả định cơ bản là các khóa riêng tư ephemeral là an toàn, và các bên sẽ hủy bỏ quá trình bắt tay nếu họ nhận được khóa công khai tĩnh từ bên kia mà họ không tin tưởng.

Phần này chỉ xem xét việc rò rỉ danh tính thông qua các trường khóa công khai tĩnh trong handshake. Tất nhiên, danh tính của các bên tham gia Noise có thể bị lộ thông qua các phương tiện khác, bao gồm các trường payload, phân tích lưu lượng, hoặc metadata như địa chỉ IP.

Alice: (8) Mã hóa với tính bảo mật chuyển tiếp đến một bên đã được xác thực.

Bob: (3) Không được truyền, nhưng kẻ tấn công thụ động có thể kiểm tra các ứng viên cho khóa riêng của người phản hồi và xác định xem ứng viên có đúng hay không.

Bob công bố khóa công khai tĩnh của mình trong netDb. Alice có thể không làm vậy, nhưng phải bao gồm nó trong RI được gửi đến Bob.

Packet Guidelines

Mã hóa xác thực

Các bước cơ bản của thông điệp handshake (Session Request/Created/Confirmed, Retry), theo thứ tự:

  • Tạo header 16 hoặc 32 byte
  • Tạo payload
  • mixHash() header (trừ Retry)
  • Mã hóa payload bằng Noise (trừ Retry, sử dụng ChaChaPoly với header làm AD)
  • Mã hóa header, và đối với Session Request/Created, mã hóa ephemeral key

Các bước cơ bản của thông điệp giai đoạn dữ liệu, theo thứ tự:

  • Tạo header 16-byte
  • Tạo payload
  • Mã hóa payload sử dụng ChaChaPoly với header làm AD
  • Mã hóa header

Inbound Packet Handling

Payload

Xử lý ban đầu của tất cả các thông báo đến:

  • Giải mã 8 byte đầu tiên của header (Destination Connection ID) với intro key
  • Tra cứu kết nối theo Destination Connection ID
  • Nếu tìm thấy kết nối và đang ở giai đoạn data, chuyển đến phần giai đoạn data
  • Nếu không tìm thấy kết nối, chuyển đến phần handshake
  • Lưu ý: Các thông điệp Peer Test và Hole Punch cũng có thể được tra cứu theo Destination Connection ID được tạo từ test hoặc relay nonce.

Xử lý các thông điệp handshake (Session Request/Created/Confirmed, Retry, Token Request) và các thông điệp ngoài phiên (Peer Test, Hole Punch):

  • Giải mã byte 8-15 của header (loại packet, phiên bản, và net ID) với intro key. Nếu đó là Session Request, Token Request, Peer Test, hoặc Hole Punch hợp lệ, tiếp tục
  • Nếu không phải là message hợp lệ, tra cứu kết nối outbound đang chờ theo IP/port nguồn của packet, coi packet như là Session Created hoặc Retry. Giải mã lại 8 byte đầu của header với key đúng, và byte 8-15 của header (loại packet, phiên bản, và net ID). Nếu đó là Session Created hoặc Retry hợp lệ, tiếp tục
  • Nếu không phải là message hợp lệ, thất bại, hoặc xếp hàng như một packet data phase có thể ngoài thứ tự
  • Đối với Session Request/Created, Retry, Token Request, Peer Test, và Hole Punch, giải mã byte 16-31 của header
  • Đối với Session Request/Created, giải mã ephemeral key
  • Xác thực tất cả các trường header, dừng nếu không hợp lệ
  • mixHash() header
  • Đối với Session Request/Created/Confirmed, giải mã payload sử dụng Noise
  • Đối với Retry và data phase, giải mã payload sử dụng ChaChaPoly
  • Xử lý header và payload

Xử lý thông điệp giai đoạn dữ liệu:

  • Giải mã byte 8-15 của header (loại packet, phiên bản và net ID) với khóa đúng
  • Giải mã payload sử dụng ChaChaPoly với header làm AD
  • Xử lý header và payload

Details

Trong SSU 1, việc phân loại gói tin đầu vào là khó khăn, bởi vì không có header để chỉ ra số phiên. Các router phải đầu tiên khớp IP nguồn và cổng với trạng thái peer hiện có, và nếu không tìm thấy, thực hiện nhiều lần giải mã với các khóa khác nhau để tìm trạng thái peer thích hợp hoặc bắt đầu một phiên mới. Trong trường hợp IP nguồn hoặc cổng cho phiên hiện có thay đổi, có thể do hành vi NAT, router có thể sử dụng các phương pháp heuristic tốn kém để cố gắng khớp gói tin với phiên hiện có và khôi phục nội dung.

SSU 2 được thiết kế để giảm thiểu nỗ lực phân loại gói tin đến trong khi vẫn duy trì khả năng chống DPI và các mối đe dọa khác trên đường truyền. Số Connection ID được bao gồm trong header cho tất cả các loại thông điệp, và được mã hóa (làm mờ) bằng ChaCha20 với một khóa và nonce đã biết. Ngoài ra, loại thông điệp cũng được bao gồm trong header (được mã hóa với bảo vệ header bằng một khóa đã biết và sau đó được làm mờ với ChaCha20) và có thể được sử dụng cho việc phân loại bổ sung. Trong mọi trường hợp, không cần thiết phải thực hiện thử nghiệm DH hoặc các phép toán mã hóa bất đối xứng khác để phân loại một gói tin.

Đối với hầu hết tất cả các thông điệp từ tất cả các peer, khóa ChaCha20 cho mã hóa Connection ID là introduction key của router đích như được công bố trong netDb.

Ngoại lệ duy nhất là những thông điệp đầu tiên được gửi từ Bob đến Alice (Session Created hoặc Retry) khi introduction key của Alice chưa được Bob biết đến. Trong những trường hợp này, introduction key của Bob được sử dụng làm khóa.

Giao thức được thiết kế để tối thiểu hóa việc xử lý phân loại gói tin có thể yêu cầu các phép toán mật mã bổ sung trong nhiều bước dự phòng hoặc các phương pháp phỏng đoán phức tạp. Ngoài ra, phần lớn các gói tin nhận được sẽ không yêu cầu tra cứu dự phòng (có thể tốn kém) theo IP/port nguồn và giải mã header lần thứ hai. Chỉ Session Created và Retry (và có thể những loại khác TBD) mới yêu cầu xử lý dự phòng. Nếu một endpoint thay đổi IP hoặc port sau khi tạo session, connection ID vẫn được sử dụng để tra cứu session. Không bao giờ cần thiết phải sử dụng phương pháp phỏng đoán để tìm session, ví dụ như tìm kiếm một session khác có cùng IP nhưng port khác.

Do đó, các bước xử lý được khuyến nghị trong logic vòng lặp receiver là:

  1. Giải mã 8 byte đầu tiên bằng ChaCha20 sử dụng introduction key cục bộ, để khôi phục Destination Connection ID. Nếu Connection ID khớp với một phiên inbound hiện tại hoặc đang chờ xử lý:

a) Sử dụng khóa phù hợp, giải mã các byte header 8-15

  to recover the version, net ID, and message type.

b) Nếu loại thông điệp là Session Confirmed, thì đây là header dài.

  Verify the net ID and protocol version are valid.
  Decrypt the bytes 15-31 of the header with ChaCha20
  using the local intro key. Then MixHash() the
  decrypted 32 byte header and decrypt the message with Noise.

c) Nếu loại thông báo hợp lệ nhưng không phải Session Confirmed,

  it is a short header.
  Verify the net ID and protocol version are valid.
  decrypt the rest of the message with ChaCha20/Poly1305
  using the session key, using the decrypted 16-byte header
  as the AD.

d) (tùy chọn) Nếu ID kết nối là một phiên inbound đang chờ xử lý

  awaiting a Session Confirmed message,
  but the net ID, protocol, or message type is not valid,
  it could be a Data message received out-of-order before the
  Session Confirmed, so the data phase header protection keys are not yet known,
  and the header bytes 8-15 were incorrectly decrypted.
  Queue the message, and attempt to decrypt it once the
  Session Confirmed message is received.

e) Nếu b) hoặc c) thất bại, hãy loại bỏ thông điệp.

  1. Nếu ID kết nối không khớp với phiên hiện tại: Kiểm tra header plaintext tại các byte 8-15 có hợp lệ (mà không thực hiện bất kỳ thao tác bảo vệ header nào). Xác minh net ID và phiên bản giao thức có hợp lệ, và loại thông điệp là Session Request, hoặc loại thông điệp khác được phép ngoài phiên (TBD).

a) Nếu tất cả đều hợp lệ và loại thông điệp là Session Request,

  decrypt bytes 16-31 of the header and the 32-byte X value
  with ChaCha20 using the local intro key.
  • Nếu token tại header bytes 24-31 được chấp nhận, thì MixHash() header 32 byte đã giải mã và giải mã message bằng Noise. Gửi Session Created để phản hồi.
    • Nếu token không được chấp nhận, gửi message Retry đến IP/port nguồn với một token. Không cố gắng giải mã message bằng Noise để tránh các cuộc tấn công DDoS.

b) Nếu loại thông điệp là một thông điệp hợp lệ khác

  out-of-session, presumably with a short header,
  decrypt the rest of the message with ChaCha20/Poly1305
  using the intro key, and using the decrypted 16-byte header
  as the AD. Process the message.

c) Nếu a) hoặc b) thất bại, chuyển đến bước 3)

  1. Tra cứu một phiên outbound đang chờ xử lý theo IP/port nguồn của gói tin.

a) Nếu tìm thấy, giải mã lại 8 byte đầu tiên bằng ChaCha20 sử dụng khóa giới thiệu của Bob

  to recover the Destination Connection ID.

b) Nếu ID kết nối khớp với phiên đang chờ:

  Using the correct key, decrypt bytes 8-15 of the header
  to recover the version, net ID, and message type.
  Verify the net ID and protocol version are valid, and
  the message type is Session Created or Retry, or other message type
  allowed out-of-session (TBD).
  • Nếu tất cả đều hợp lệ và loại thông điệp là Session Created, giải mã 16 byte tiếp theo của header và giá trị Y 32-byte bằng ChaCha20 sử dụng intro key của Bob. Sau đó MixHash() header 32 byte đã giải mã và giải mã thông điệp bằng Noise. Gửi Session Confirmed để phản hồi.

    • Nếu tất cả đều hợp lệ và loại thông điệp là Retry, giải mã byte 16-31 của header bằng ChaCha20 sử dụng intro key của Bob. Giải mã và xác thực thông điệp sử dụng ChaCha20/Poly1305 với TBD làm key và TBD làm nonce và header 32-byte đã giải mã làm AD. Gửi lại Session Request với token đã nhận để phản hồi.
    • Nếu loại thông điệp là một thông điệp khác hợp lệ ngoài session, có thể với header ngắn, giải mã phần còn lại của thông điệp bằng ChaCha20/Poly1305 sử dụng intro key, và sử dụng header 16-byte đã giải mã làm AD. Xử lý thông điệp.

    c) If a pending outbound session is not found, or the connection ID does not match the pending session, drop the message, unless the port is shared with SSU 1.

  1. Nếu đang chạy SSU 1 trên cùng port, hãy thử xử lý tin nhắn như một gói tin SSU 1.

Error Handling

Nói chung, một phiên (trong giai đoạn handshake hoặc dữ liệu) không bao giờ nên bị hủy sau khi nhận được một gói tin với loại thông điệp không mong đợi. Điều này ngăn chặn các cuộc tấn công chèn gói tin. Những gói tin này cũng thường được nhận sau khi truyền lại gói tin handshake, khi các khóa giải mã header không còn hợp lệ.

Trong hầu hết các trường hợp, đơn giản chỉ cần loại bỏ gói tin. Một implementation có thể, nhưng không bắt buộc phải, truyền lại gói tin đã gửi trước đó (handshake message hoặc ACK 0) để phản hồi.

Sau khi gửi Session Created với vai trò Bob, các gói tin bất ngờ thường là các gói tin Data không thể được giải mã vì các gói tin Session Confirmed đã bị mất hoặc không theo thứ tự. Xếp hàng các gói tin này và thử giải mã chúng sau khi nhận được các gói tin Session Confirmed.

Sau khi nhận Session Confirmed với tư cách là Bob, các gói tin bất ngờ thường là các gói tin Session Confirmed được truyền lại, bởi vì ACK 0 của Session Confirmed đã bị mất. Các gói tin bất ngờ có thể bị loại bỏ. Một triển khai có thể, nhưng không bắt buộc phải, gửi một gói tin Data chứa khối ACK để phản hồi.

Notes

Đối với Session Created và Session Confirmed, các implementation phải xác thực cẩn thận tất cả các trường header đã giải mã (Connection IDs, packet number, packet type, version, id, frag, và flags) TRƯỚC KHI gọi mixHash() trên header và cố gắng giải mã payload bằng Noise AEAD. Nếu việc giải mã Noise AEAD thất bại, không được thực hiện xử lý thêm nào nữa, bởi vì mixHash() sẽ làm hỏng trạng thái handshake, trừ khi implementation lưu trữ và “khôi phục” trạng thái hash.

Version Detection

Có thể không hiệu quả khi phát hiện các gói tin đến là phiên bản 1 hay 2 trên cùng một cổng inbound. Các bước trên có thể hợp lý để thực hiện trước khi xử lý SSU 1, nhằm tránh việc thử các phép toán DH bằng cả hai phiên bản giao thức.

Sẽ được xác định nếu cần thiết.

  • Thời gian chờ truyền lại handshake đi: 1.25 giây, với exponential backoff (truyền lại tại 1.25, 3.75, và 8.75 giây)
  • Tổng thời gian chờ handshake đi: 15 giây
  • Thời gian chờ truyền lại handshake đến: 1 giây, với exponential backoff (truyền lại tại 1, 3, và 7 giây)
  • Tổng thời gian chờ handshake đến: 12 giây
  • Thời gian chờ sau khi gửi retry: 9 giây
  • Độ trễ ACK: max(10, min(rtt/6, 150)) ms
  • Độ trễ ACK ngay lập tức: min(rtt/16, 5) ms
  • Số lượng ACK range tối đa: 256?
  • Độ sâu ACK tối đa: 512?
  • Phân bố padding: 0-15 byte, hoặc lớn hơn

Variants, Fallbacks, and General Issues

Sẽ được bổ sung

Packet Overhead Analysis

Giả định IPv4, không bao gồm padding bổ sung, không bao gồm kích thước header IP và UDP. Padding là mod-16 padding chỉ dành cho SSU 1.

SSU 1

MessageHeader+MACKeysDataPaddingTotalNotes
Session Request4025653304Incl.
Session Created37256791336Incl.
Session Confirmed3746213512Incl.
Data (RI)3710141051Incl.
Data (1 full msg)371451Incl.
Total2254
SSU 2
MessageHeader+MACsKeysDataPaddingTotalNotes
Session Request4832787DateTi
Session Created48321696DateTi
Session Confirmed4832100510851000 b
Data (1 full msg)321446
Total1314
TODO TRỪ KHI kích thước gói tin tối thiểu trong Session Request và Created được thực thi cho PMTU.