Bảo mật UDP
Trên trang này
- Runtime mong đợi điều gì#
- Luồng tổng quan#
- Cấu trúc phía máy chủ#
- 1. Kế thừa UdpListenerBase#
- 2. Giữ TCP và UDP gắn với cùng một session#
- Bố cục gói tin phía client mang tính khái niệm#
- Mã giả cho việc gửi phía client#
- Quy tắc transport#
- Điều gì xảy ra khi thất bại#
- Quy trình triển khai khuyến nghị#
- Các trang liên quan#
Hướng dẫn này giải thích cấu trúc session UDP thực tế mà UdpListenerBase đang sử dụng, theo cách dễ hiểu với client.
Hãy dùng nó khi bạn đã biết mình cần UDP và muốn hiểu các quy tắc về tin cậy và chống phát lại trước khi triển khai client.
Runtime mong đợi điều gì
Khi UdpListenerBase nhận một datagram, nó mong đợi một lớp bọc xác thực 12 byte bao quanh gói tin Nalix đã tuần tự hóa (kích thước datagram tối thiểu là 18 byte = SessionTokenSize (8) + PacketHeader.Size (6) + UdpMacTagSize (4)):
- session token (
Snowflake, 8 byte tại[0..8]) - payload (tối thiểu là
PacketHeader6 byte của Nalix tại[8..^4]:[OpCode(2), Flags(1), Priority(1), SequenceId(2)]) - thẻ xác thực
XxHash32(4 byte tại[^4..^0])
Trong mã nguồn (UdpListener.Receive.cs), listener kiểm tra:
- datagram dài ít nhất
18byte (8token +6PacketHeader.Size+4thẻXxHash32) - token 8 byte phân giải được thành một kết nối đang hoạt động, chưa bị dispose trong
ConnectionHub, vớiSecretkhác không - thẻ
XxHash324 byte ở cuối khớp vớiXxHash32.Compute(connection.Secret.AsSpan(), seed: XxHash32.Compute(datagram[..^4])) - endpoint từ xa khớp với endpoint đã ghim của kết nối (
IsPinnedEndpointMatch) - cửa sổ chống phát lại UDP (
connection.UdpReplayWindow.TryCheck(header.SequenceId)) chấp nhận số thứ tự của gói IsAuthenticated(...)bạn ghi đè hoặc predicate của hosting trả vềtrue
Luồng tổng quan
sequenceDiagram
participant Client
participant TCP as TcpListenerBase
participant Hub as ConnectionHub
participant UDP as UdpListenerBase
Client->>TCP: 1. Connect & HandshakeAsync()
TCP->>Hub: 2. Store connection (SessionToken + 32B Secret)
TCP-->>Client: 3. SessionEstablished (8B SessionToken)
Client->>UDP: 4. Datagram [8B Token][Payload][4B XxHash32 MAC]
UDP->>Hub: 5. Resolve session by 8B Token & verify 4B XxHash32 MAC
UDP->>UDP: 6. Replay check + IsAuthenticated(...)Cấu trúc phía máy chủ
1. Kế thừa UdpListenerBase
public sealed class SampleUdpListener : UdpListenerBase
{
public SampleUdpListener(IProtocol protocol, IConnectionHub hub) : base(protocol, hub) { }
public override bool IsAuthenticated(IConnection connection, EndPoint remoteEndPoint, ReadOnlySpan<byte> payload)
{
// Add your own checks here:
// - allowed endpoint
// - session state
// - region / shard ownership
return !connection.Secret.IsZero;
}
}
2. Giữ TCP và UDP gắn với cùng một session
Đường UDP giả định đã có sẵn một kết nối được biết đến trong ConnectionHub.
Vì vậy, một mẫu phổ biến là:
- xác thực hoặc handshake trên TCP trước
- tạo/điền connection secret
- lưu session vào
ConnectionHub - cho phép các gói UDP tham chiếu tới ID session đó
Bố cục gói tin phía client mang tính khái niệm
Listener kiểm tra ba phần sau:
[8-byte session-token][payload (>= 6B PacketHeader)][4-byte XxHash32 MAC]
Token là ID session Snowflake được gán cho kết nối sau handshake TCP, còn thẻ 4 byte ở cuối được tính trên [session-token][payload] với seed là connection.Secret 32 byte.
Mã giả cho việc gửi phía client
// Using Nalix.SDK UdpSession handles this automatically:
await using var udp = new UdpSession(udpOptions, tcpSession.State);
await udp.ConnectAsync(host, port);
await udp.SendAsync(packet);
// Or manually constructing the wire datagram:
uint bodyHash = XxHash32.Compute(tokenAndPayload, seed: 0);
uint macTag = XxHash32.Compute(sharedSecret.AsSpan(), seed: bodyHash);
Quy tắc transport
Runtime dùng tiền tố SessionToken 8 byte và thẻ xác thực XxHash32 4 byte ở cuối, được khóa bằng session secret X25519 32 byte được thiết lập qua TCP.
Với client, điều đó có nghĩa là:
- gửi session token 8 byte trước và gắn thẻ
XxHash324 byte vào cuối (hoặc dùngUdpSession, lớp này tự làm cả hai việc) - giữ tổng kích thước datagram đủ nhỏ để vừa với
MaxUdpDatagramSize(mặc định1440byte) - coi UDP là đường datagram nhanh gắn với một session TCP đã thiết lập, chứ không phải một giao thức xác thực độc lập
Điều gì xảy ra khi thất bại
Listener ghi lại chẩn đoán cho:
- gói quá ngắn
- session không xác định
- gói chưa được xác thực
- lỗi nhận
Các gói không hợp lệ bị loại bỏ trước khi đến logic protocol của bạn.
Quy trình triển khai khuyến nghị
Với một triển khai đơn giản:
- thiết lập session qua TCP
- gán/lưu session secret
- trả ID session về cho client
- cho phép client gửi datagram UDP có tiền tố là session token
- xác minh trong
IsAuthenticated(...)rằng session đã sẵn sàng cho UDP