shadowsocks

package
v0.3.3 Latest Latest
Warning

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

Go to latest
Published: Mar 27, 2022 License: Apache-2.0 Imports: 21 Imported by: 0

Documentation

Index

Constants

View Source
const (
	HeaderTypeClientStream = 0
	HeaderTypeServerStream = 1

	HeaderTypeClientPacket = 0
	HeaderTypeServerPacket = 1

	MinPaddingLength = 0
	MaxPaddingLength = 900

	// type + 64-bit timestamp + socks address + padding length + padding
	TCPReqHeaderMaxLength = 1 + 8 + socks.MaxAddrLen + 2 + MaxPaddingLength

	// type + 64-bit timestamp + max salt length
	TCPRespHeaderMaxLength = 1 + 8 + 32

	// server session id + packet id + type + timestamp + client session id + padding length
	UDPServerMessageHeaderFixedLength = 8 + 8 + 1 + 8 + 8 + 2

	// client session id + packet id + type + timestamp + padding length
	UDPClientMessageHeaderFixedLength = 8 + 8 + 1 + 8 + 2
)
View Source
const TestCipher = "chacha20-ietf-poly1305"

TestCipher is a preferred cipher to use in testing.

Variables

View Source
var (
	ErrIncompleteHeaderInFirstChunk = errors.New("header in first chunk is missing or incomplete")
	ErrPaddingExceedChunkBorder     = errors.New("padding in first chunk is shorter than advertised")
	ErrBadTimestamp                 = errors.New("time diff is over 30 seconds")
	ErrTypeMismatch                 = errors.New("header type mismatch")
	ErrPaddingLengthOutOfRange      = errors.New("padding length is less than 0 or greater than 900")
	ErrClientSaltMismatch           = errors.New("client salt in response header does not match request")
	ErrClientSessionIDMismatch      = errors.New("client session ID in server message header does not match current session")
	ErrTooManyServerSessions        = errors.New("server session changed more than once during the last minute")
)
View Source
var ErrShortPacket = errors.New("short packet")

Functions

func DecryptOnce

func DecryptOnce(cipher *Cipher, salt []byte, plainText, cipherText []byte) ([]byte, error)

DecryptOnce will decrypt the cipherText using the cipher and salt, appending the output to plainText.

func DecryptSeparateHeader

func DecryptSeparateHeader(cipher *Cipher, dst, src []byte) error

func MakeTestPayload

func MakeTestPayload(size int) []byte

MakeTestPayload returns a slice of `size` arbitrary bytes.

func MakeTestSecrets

func MakeTestSecrets(n int) []string

MakeTestSecrets returns a slice of `n` test passwords. Not secure!

func Pack

func Pack(dst, plaintext []byte, cipher *Cipher) ([]byte, error)

Pack encrypts a Shadowsocks-UDP packet and returns a slice containing the encrypted packet. dst must be big enough to hold the encrypted packet. If plaintext and dst overlap but are not aligned for in-place encryption, this function will panic.

func PackAesWithSeparateHeader

func PackAesWithSeparateHeader(dst, plaintext []byte, cipher *Cipher, sessionAEAD cipher.AEAD) ([]byte, error)

Pack function for 2022-blake3-aes-256-gcm. Do not encrypt header before calling this function. This function encrypts the separate header after sealing AEAD.

plaintext should start with the separate header.

func ParseTCPReqHeader

func ParseTCPReqHeader(r Reader, cipherConfig CipherConfig) (string, []byte, error)

ParseTCPReqHeader reads the first payload chunk, validates the header, and returns the target address, initial payload, or an error.

For Shadowsocks 2022, the first payload chunk MUST contain either a non-zero-length padding or initial payload, or both (not recommended client behavior but allowed). If the padding length is 0 and there's no initial payload, an error is returned.

func ParseTCPRespHeader

func ParseTCPRespHeader(r Reader, clientSalt []byte, cipherConfig CipherConfig) ([]byte, error)

func ParseUDPHeader

func ParseUDPHeader(plaintext []byte, htype byte, csid []byte, cipherConfig CipherConfig) (socksAddrStart int, socksAddr socks.Addr, payload []byte, err error)

For spec 2022, this function only parses the decrypted AEAD header. csid is the expected client session id, used when verifying a server packet.

func SupportedCipherNames

func SupportedCipherNames() []string

SupportedCipherNames lists the names of the AEAD ciphers that are supported.

func Unpack

func Unpack(dst, pkt []byte, cipher *Cipher) (plaintextStart int, plaintext []byte, err error)

Unpack decrypts a Shadowsocks UDP packet and returns the plaintext offset in the original packet buffer, a slice containing the decrypted plaintext (header + payload) or an error.

If dst is present, it is used to store the plaintext, and must have enough capacity. If dst is nil, decryption proceeds in-place.

func UnpackAesWithSeparateHeader

func UnpackAesWithSeparateHeader(dst, pkt, separateHeader []byte, unpackAEAD cipher.AEAD) ([]byte, error)

Unpack function for 2022-blake3-aes-256-gcm. If separateHeader is nil, DecryptSeparateheader MUST be called to decrypte the separate header in-place before passing the ciphertext. The returned buffer includes the separate header.

func WriteClientUDPHeader

func WriteClientUDPHeader(plaintext []byte, cipherConfig CipherConfig, sid []byte, pid uint64, targetAddr net.Addr, maxPacketSize int) (n int, err error)

WriteClientUDPHeader fills a Shadowsocks UDP header into the buffer.

For Shadowsocks 2022, make sure to increment packet ID upon returning.

No buffer length checks are performed. Make sure the buffer can hold the socks address.

func WritePadding

func WritePadding(b []byte, paddingLen int) int

func WriteRandomPadding

func WriteRandomPadding(b []byte, targetPort int, max int) int

func WriteTCPReqHeader

func WriteTCPReqHeader(dst, socksaddr []byte, addPadding bool, cipherConfig CipherConfig) (n int)

func WriteTCPRespHeader

func WriteTCPRespHeader(dst, clientSalt []byte, cipherConfig CipherConfig) (n int)

func WriteUDPHeader

func WriteUDPHeader(plaintext []byte, htype byte, sid []byte, pid uint64, csid []byte, targetUDPAddr *net.UDPAddr, targetSocksAddr []byte, paddingLen int) (n int)

WriteUDPHeader fills a Shadowsocks 2022 UDP header into the buffer. Make sure to increment packet ID upon returning. To write a client header, pass csid as sid, and nil as csid. To write a server header, pass ssid as sid, and csid as csid. Pass either targetUDPAddr or targetSocksAddr.

For legacy Shadowsocks, call WriteUDPAddrToSocksAddr directly.

No buffer length checks are performed. Make sure the buffer can hold the socks address.

Types

type ChunkReader

type ChunkReader interface {
	// ReadChunk reads the next chunk and returns its payload.  The caller must
	// complete its use of the returned buffer before the next call.
	// The buffer is nil iff there is an error.  io.EOF indicates a close.
	ReadChunk() ([]byte, error)

	Salt() []byte
}

ChunkReader is similar to io.Reader, except that it controls its own buffer granularity.

type Cipher

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

Cipher encapsulates a Shadowsocks AEAD spec and a secret

func NewCipher

func NewCipher(cipherName string, secretText string) (*Cipher, error)

NewCipher creates a Cipher given a cipher name and a secret

func (*Cipher) Config

func (c *Cipher) Config() CipherConfig

func (*Cipher) NewAEAD

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

NewAEAD creates the AEAD for this cipher

func (*Cipher) SaltSize

func (c *Cipher) SaltSize() int

SaltSize is the size of the salt for this Cipher

func (*Cipher) TagSize

func (c *Cipher) TagSize() int

TagSize is the size of the AEAD tag for this Cipher

type CipherConfig

type CipherConfig struct {
	IsSpec2022           bool
	UDPHasSeparateHeader bool
}

type DecryptionErr

type DecryptionErr struct {
	Err error
}

func (*DecryptionErr) Error

func (e *DecryptionErr) Error() string

func (*DecryptionErr) Unwrap

func (e *DecryptionErr) Unwrap() error

type Reader

type Reader interface {
	io.Reader
	io.WriterTo

	// Salt returns the salt used by this instance to derive the subkey.
	Salt() []byte

	// EnsureLeftover makes sure that the leftover slice is not nil.
	// If it's nil, a read is attempted and the result is returned.
	EnsureLeftover() error

	// LeftoverZeroCopy returns the leftover slice without copying.
	// The content of the returned slice won't change until next read.
	LeftoverZeroCopy() []byte
}

Reader is an io.Reader that also implements io.WriterTo to allow for piping the data without extra allocations and copies.

func NewShadowsocksReader

func NewShadowsocksReader(reader io.Reader, ssCipher *Cipher) Reader

NewShadowsocksReader creates a Reader that decrypts the given Reader using the shadowsocks protocol with the given shadowsocks cipher.

type SaltGenerator

type SaltGenerator interface {
	// Returns a new salt
	GetSalt(salt []byte) error
}

SaltGenerator generates unique salts to use in Shadowsocks connections.

var (
	// RandomSaltGenerator is a basic SaltGenerator.
	RandomSaltGenerator SaltGenerator = randomSaltGenerator{}

	// High performance random salt/nonce generator
	Blake3KeyedHashSaltGenerator = NewBlake3KeyedHashReader(24)
)

func NewBlake3KeyedHashReader

func NewBlake3KeyedHashReader(size int) SaltGenerator

type Writer

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

Writer is an io.Writer that also implements io.ReaderFrom to allow for piping the data without extra allocations and copies. The LazyWrite and Flush methods allow a header to be added but delayed until the first write, for concatenation. All methods except Flush must be called from a single thread.

func NewShadowsocksWriter

func NewShadowsocksWriter(writer io.Writer, ssCipher *Cipher, saltGenerator SaltGenerator, lazyWriteBuf []byte, addPaddingOnFlush bool) (*Writer, error)

NewShadowsocksWriter creates a Writer that encrypts the given Writer using the shadowsocks protocol with the given shadowsocks cipher.

addPaddingOnFlush: true, lazyWriteBuf != nil: Shadowsocks 2022 client writer addPaddingOnFlush: false, lazyWriteBuf != nil: Shadowsocks 2022 server writer, Legacy Shadowsocks client writer addPaddingOnFlush: false, lazyWriteBuf == nil: Legacy Shadowsocks server writer

func (*Writer) Flush

func (sw *Writer) Flush() error

Flush sends the pending header, if any. This method is thread-safe.

func (*Writer) ReadFrom

func (sw *Writer) ReadFrom(r io.Reader) (n int64, err error)

ReadFrom implements the io.ReaderFrom interface.

func (*Writer) Salt

func (sw *Writer) Salt() []byte

func (*Writer) Write

func (sw *Writer) Write(p []byte) (int, error)

Jump to

Keyboard shortcuts

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