[GH-ISSUE #25] Shadowsocks: replay protection is disabled (IV/nonce dedup never runs) #4

Open
opened 2026-10-13 21:10:45 +00:00 by bsakaguchi · 0 comments
Owner

Originally created by @FrogRocky on GitHub (Aug 17, 2026).
Original GitHub issue: https://github.com/amnezia-vpn/amnezia-xray-core/issues/25

Summary

Shadowsocks replay protection is effectively disabled: the IV/nonce uniqueness check is commented out, so a recorded AEAD packet is accepted for replay any number of times.

Affected code: proxy/shadowsocks/validator.go:112-154 — Validator.Get() never returns ErrIVNotUnique; the only check is commented out at line 148:

// err = user.Account.(*MemoryAccount).CheckIV(bs[:ivLen])

ErrIVNotUnique (defined in config.go:29) is unreachable, and the error-handling branches in protocol.go:81 and :234 are dead code.

Additionally, for UDP (proxy/shadowsocks/server.go:147-156), after the first packet sets inbound.User, every subsequent packet is decoded through a freshly constructed Validator containing only that user — bypassing even a hypothetical dedup state for all packets after the first from a source.

Impact

An on-path attacker records a legitimate client's AEAD packet (UDP, or the first TCP chunk) and replays it at will: the server decrypts and re-dispatches every copy — repeated outbound connections and UDP amplification through the proxy. AEAD integrity does not help here; nothing rejects duplicates.

This matches upstream Xray-core behavior (the check is disabled upstream too), but it contradicts the Shadowsocks AEAD practice of salt/IV deduplication.

Suggested fix

  • Re-enable the salt/IV filter in Validator.Get() (CheckIV for non-AEAD, nonce dedup for AEAD), with a bounded per-user replay window (as in shadowsocks SIP004 implementations).
  • Share one nonce-filter instance across the connection so the UDP fast path (server.go:147-156) checks subsequent packets against it instead of a fresh Validator.
Originally created by @FrogRocky on GitHub (Aug 17, 2026). Original GitHub issue: https://github.com/amnezia-vpn/amnezia-xray-core/issues/25 ## Summary Shadowsocks replay protection is effectively disabled: the IV/nonce uniqueness check is commented out, so a recorded AEAD packet is accepted for replay any number of times. **Affected code:** `proxy/shadowsocks/validator.go:112-154` — `Validator.Get()` never returns `ErrIVNotUnique`; the only check is commented out at line 148: ```go // err = user.Account.(*MemoryAccount).CheckIV(bs[:ivLen]) ``` `ErrIVNotUnique` (defined in `config.go:29`) is unreachable, and the error-handling branches in `protocol.go:81` and `:234` are dead code. Additionally, for UDP (`proxy/shadowsocks/server.go:147-156`), after the first packet sets `inbound.User`, every subsequent packet is decoded through a freshly constructed `Validator` containing only that user — bypassing even a hypothetical dedup state for all packets after the first from a source. ## Impact An on-path attacker records a legitimate client's AEAD packet (UDP, or the first TCP chunk) and replays it at will: the server decrypts and re-dispatches every copy — repeated outbound connections and UDP amplification through the proxy. AEAD integrity does not help here; nothing rejects duplicates. This matches upstream Xray-core behavior (the check is disabled upstream too), but it contradicts the Shadowsocks AEAD practice of salt/IV deduplication. ## Suggested fix - Re-enable the salt/IV filter in `Validator.Get()` (`CheckIV` for non-AEAD, nonce dedup for AEAD), with a bounded per-user replay window (as in shadowsocks SIP004 implementations). - Share one nonce-filter instance across the connection so the UDP fast path (`server.go:147-156`) checks subsequent packets against it instead of a fresh `Validator`.
Sign in to join this conversation.
No labels
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
amnezia-vpn/amnezia-xray-core#4
No description provided.