-
Notifications
You must be signed in to change notification settings - Fork 260
LP reg telescoping #6240
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
durch
wants to merge
14
commits into
drazen/lp-reg
Choose a base branch
from
drazen/lp-reg-telescoping
base: drazen/lp-reg
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
LP reg telescoping #6240
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add in-memory state storage for handshake and session state to enable stateless transport layer. This is the foundation for packet-per-connection forwarding and future UDP support. Changes: - Add handshake_states: Arc<DashMap<[u8; 32], LpStateMachine>> Keyed by client Ed25519 public key for in-progress handshakes - Add session_states: Arc<DashMap<u32, LpSession>> Keyed by session_id for established sessions - Initialize both maps in production code (node/mod.rs) - Initialize both maps in test code (handler.rs) No logic changes yet - pure infrastructure addition. All existing tests pass. Fixes: nym-qtji
Major architectural change: decouple handshake state from TCP connection to enable packet-per-connection forwarding and future UDP support. ## Changes ### Gateway Handler (handler.rs) - Refactor `handle()` from persistent-connection loop to single-packet processing - Add `handle_client_hello()`: Process ClientHello (session_id=0), create LpStateMachine, store in handshake_states map - Add `handle_handshake_packet()`: Process handshake packets incrementally, transition to session_states when complete - Add `handle_transport_packet()`: Handle registration/forward requests via established sessions ### State Management - Use handshake_states (DashMap<u32, LpStateMachine>) for in-progress handshakes - Use session_states (DashMap<u32, LpSession>) for established sessions - Session ID computed deterministically from X25519 keys immediately after ClientHello - State persists across connection closes ### Packet Flow ``` packet arrives → parse session_id from header if session_id == 0: handle_client_hello (create state) elif in handshake_states: handle_handshake_packet (advance state) elif in session_states: handle_transport_packet (decrypt, process) else: error (unknown session) send response → close connection ``` ## Testing - All 13 existing unit tests pass - Tests verify low-level packet I/O, timestamp validation, etc. - Integration testing via nym-gateway-probe (next step) ## Backwards Compatibility - Old handshake.rs methods kept but unused (may remove later) - Metrics unchanged - Protocol wire format unchanged ## Next Steps - Test with docker/localnet topology - Verify telescoping works (nym-gateway-probe) - Apply same architecture to entry gateway (nym-31hl) Fixes: nym-21th Blocks: nym-31hl
Gateway responder's StartHandshake doesn't return a packet - it just transitions
to KKTExchange state and waits for client's KKT request. Fixed handle_client_hello()
to not expect a response packet.
## Changes
### Add BOOTSTRAP_SESSION_ID constant
- `common/nym-lp/src/packet.rs`: Add `pub const BOOTSTRAP_SESSION_ID: u32 = 0`
- Document that session_id=0 is only used for ClientHello bootstrap
- Export from lib.rs for public use
### Fix handle_client_hello() logic
- `gateway/src/node/lp_listener/handler.rs:201-225`: - Remove expectation of SendPacket action from StartHandshake
- Responder transitions to KKTExchange without sending
- Store state machine and close connection
- Client sends KKT request on next connection with computed session_id
### Use constant throughout codebase
- `gateway/src/node/lp_listener/handler.rs:115`: Use BOOTSTRAP_SESSION_ID in routing
- `nym-registration-client/src/lp_client/client.rs:259`: Use constant instead of literal 0
## Protocol Flow (Fixed)
```
Connection 1: Client sends ClientHello (session_id=0)
→ Gateway stores state, closes (no response)
Connection 2: Client sends KKT request (session_id=X)
→ Gateway finds state, processes, responds
Connection 3+: Handshake continues until complete...
```
## Testing
- All 13 unit tests pass
- Real test: docker/localnet + nym-gateway-probe (next step)
Fixes: nym-v9un
Unblocks: nym-21th
- Extend handle_transport_packet() to conditionally deserialize both LpRegistrationRequest and ForwardPacketData messages - Add handle_registration_request() helper for registration flow - Add handle_forwarding_request() helper for telescoping flow - Delete dead handle_forwarding_loop() method (persistent connection model) - Clean up unused imports and dead code warnings - All 13 tests passing Entry gateway now fully supports single-packet-per-connection architecture for both direct client registration and packet forwarding to exit gateways. Each ForwardPacket arrives on a new connection, gets processed, response sent, and connection closes - consistent with exit gateway behavior from nym-21th.
- Create TimestampedState<T> wrapper with created_at and last_activity tracking - Add TTL config fields to LpConfig: * handshake_ttl_secs (default: 90s) * session_ttl_secs (default: 24h) * state_cleanup_interval_secs (default: 5min) - Update LpHandlerState maps to use TimestampedState wrappers - Update all handler.rs access points to wrap/unwrap states - Implement background cleanup task in LpListener: * Spawns on startup, stops on shutdown * Removes handshakes older than handshake_ttl * Removes sessions with no activity > session_ttl * Tracks metrics: lp_states_cleanup_handshake_removed, lp_states_cleanup_session_removed - Touch last_activity on every packet in handle_transport_packet() - All 13 tests passing Prevents memory leaks from abandoned handshakes and expired sessions in long-running gateways. Configurable TTLs for different use cases.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
2 Skipped Deployments
|
- Add OuterAeadKey derived from PSK via Blake3 KDF for packet encryption - Add LpMessage::Ack (0x0008) for ClientHello acknowledgment - Gateway sends Ack after processing ClientHello (packet-per-connection) - Update codec with AEAD encrypt/decrypt using ChaCha20-Poly1305 - Header remains cleartext (AAD), payload encrypted after PSK derivation - Add parse_lp_header_only() for routing before session lookup - Update session to expose outer_aead_key() getter - Various LP protocol improvements and test coverage Closes: nym-f4v1, nym-n9dr
…8wuj, nym-k0tb] Refactor LpRegistrationClient from persistent TCP connection model to packet-per-connection model, matching gateway's stateless connection pattern. Each LP packet exchange opens a new TCP connection, sends one packet, receives one response, then closes. State persists in LpStateMachine locally. Key changes: - Add connect_send_receive() helper for packet-per-connection exchanges - Rewrite perform_handshake() with clean loop-based approach - Remove LpTransport (packet-per-connection doesn't need persistent transport) - Combine send_registration_request + receive_registration_response into register() - Remove connect() method - handshake now handles connection internally NestedLpSession refactoring: - Add send_and_receive_via_forward() helper (consolidates 9 outer_key extractions) - Rewrite perform_handshake() from 6-level nesting to clean loop - Use BOOTSTRAP_RECEIVER_IDX constant instead of hardcoded 0 - Fix stale doc comment referencing removed connect() method Result: 438 fewer lines, cleaner control flow, DRY outer_key handling.
- Validate Ack response in NestedLpSession and LP client final handshake - Replace manual Drop with derive(Zeroize, ZeroizeOnDrop) for OuterAeadKey - Add replay counter check before AEAD decryption to prevent DoS [nym-qm2q, nym-z82d, nym-9ik3, nym-62fs]
Restructure LP packet format so cleartext fields (receiver_idx, counter) are always first, enabling trivial header parsing for routing before session lookup. Protocol version and reserved fields are now encrypted in the inner payload for encrypted packets. Wire format change: - Before: proto(1B) + reserved(3B) + receiver_idx(4B) + counter(8B) - After: receiver_idx(4B) + counter(8B) | proto(1B) + reserved(3B) + ... Key changes: - Add OuterHeader struct (12 bytes) for routing/replay protection - Update serialize_lp_packet/parse_lp_packet for unified format - parse_lp_header_only now returns OuterHeader - Gateway handler uses OuterHeader for session lookup - Update DESIGN.md with new wire format diagrams Security improvement: Only receiver_idx and counter visible after PSK establishment (was also exposing protocol version and reserved).
- Add subsession message types: SubsessionKK1, KK2, Ready, Request, Abort - Implement SubsessionHandshake for Noise KKpsk0 tunneled through parent - Add subsession PSK derivation from parent's PQ shared secret - Handle simultaneous initiation with X25519 key comparison tie-breaker - Add stale SubsessionAbort handler for message interleaving scenarios - Add test for simultaneous subsession initiation race condition Subsessions provide forward secrecy via periodic rekeying while inheriting PQ protection from the parent session's ML-KEM shared secret.
- Store LpStateMachine in session_states (not LpSession) for subsession handling - Add LpStateMachine::from_subsession() factory for promoted sessions - Rewrite handle_transport_packet() to use state machine for all messages - Add handle_subsession_complete() for session promotion flow - Add collision check for new_receiver_index before insert (nym-90rw) - Add demoted_session_ttl_secs config (default 60s) for ReadOnlyTransport sessions to be cleaned up quickly after subsession promotion (nym-atza) - Track demoted session cleanup separately with lp_states_cleanup_demoted_removed
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This change is