shadowsocks

package
v0.0.0-...-6ebb1da Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 12, 2026 License: GPL-3.0 Imports: 20 Imported by: 0

Documentation

Overview

Package shadowsocks implements a Shadowsocks AEAD proxy server for anzu-proxy, supporting the AEAD_CHACHA20_POLY1305 and AEAD_AES_256_GCM cipher suites as specified in:

https://shadowsocks.org/doc/aead.html

Wire format (TCP):

[salt (32 B)] [encrypted chunks...]

Each encrypted chunk:
  [2-byte payload length, AEAD-sealed] [payload, AEAD-sealed]

The session subkey is derived with HKDF-SHA1:

subkey = HKDF-SHA1(key=password, salt=salt, info="ss-subkey", len=keySize)

Authentication is password-only (no UserStore). A wrong password or any ciphertext error causes a silent close with no reply — this is the Shadowsocks anti-probing requirement.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Cipher

type Cipher struct {
	// contains filtered or unexported fields
}

Cipher holds the parameters for one AEAD cipher suite.

func NewCipher

func NewCipher(name string) (*Cipher, error)

NewCipher returns a Cipher for the given suite name. Accepted names (case-insensitive):

"AEAD_CHACHA20_POLY1305" / "chacha20-ietf-poly1305"
"AEAD_AES_256_GCM"       / "aes-256-gcm"

func (*Cipher) DeriveSubkey

func (c *Cipher) DeriveSubkey(password, salt []byte) ([]byte, error)

DeriveSubkey derives the per-session subkey from the shared password and the per-connection random salt using HKDF-SHA1 as specified by the Shadowsocks AEAD standard.

func (*Cipher) NewAEAD

func (c *Cipher) NewAEAD(subkey []byte) (cipher.AEAD, error)

NewAEAD constructs the AEAD instance for a derived subkey.

func (*Cipher) SaltSize

func (c *Cipher) SaltSize() int

SaltSize returns the number of bytes the client sends as the per-session salt.

type Handler

type Handler struct {
	// contains filtered or unexported fields
}

Handler manages a single Shadowsocks client connection.

Protocol flow:

  1. Read salt (cipher.SaltSize() bytes) from client — plaintext
  2. Derive session subkey: HKDF-SHA1(password, salt, "ss-subkey")
  3. Wrap connection in AEAD reader; decrypt SOCKS5-style address header
  4. Dial the target via netutil.DialTarget (respects upstream proxy + SSRF)
  5. Relay bidirectionally: client→target (via AEAD reader), target→client (via a new aeadWriter with its own fresh salt)

Any error before the relay starts is surfaced as a return value but produces NO reply to the client — Shadowsocks anti-probing requirement.

func NewHandler

func NewHandler(conn net.Conn, cfg *config.Config, c *Cipher) *Handler

NewHandler creates a Handler for one accepted connection.

func (*Handler) Handle

func (h *Handler) Handle() error

Handle drives the full connection lifecycle.

type Server

type Server struct {
	// contains filtered or unexported fields
}

Server is the Shadowsocks AEAD proxy server. It runs a TCP listener (for the stream relay) and a UDP socket (for the datagram relay) on the same address and port.

func NewServer

func NewServer(cfg *config.Config) (*Server, error)

NewServer creates a Server after validating the cipher name and password.

func (*Server) Addr

func (s *Server) Addr() string

Addr returns the configured listen address.

func (*Server) ServeListener

func (s *Server) ServeListener(ln net.Listener) error

ServeListener is used by tests that pre-bind their own TCP listener. It binds the UDP socket on the same address automatically.

func (*Server) Shutdown

func (s *Server) Shutdown(ctx context.Context) error

Shutdown closes the listeners and waits for in-flight handlers to drain.

func (*Server) Start

func (s *Server) Start() error

Start binds the TCP listener and UDP socket then begins serving. Blocks until Shutdown is called.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL