shadowsocks

package
v0.0.1 Latest Latest
Warning

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

Go to latest
Published: Jul 28, 2023 License: Apache-2.0 Imports: 21 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	CHACHA20IETFPOLY1305 = "AEAD_CHACHA20_POLY1305"
	AES256GCM            = "AEAD_AES_256_GCM"
	AES192GCM            = "AEAD_AES_192_GCM"
	AES128GCM            = "AEAD_AES_128_GCM"
)

List of supported AEAD ciphers, as specified at https://shadowsocks.org/guide/aead.html

View Source
var ErrShortPacket = errors.New("short packet")

ErrShortPacket indicates the destination packet given to Unpack is too short.

Functions

func NewPacketListener

func NewPacketListener(endpoint transport.PacketEndpoint, key *EncryptionKey) (transport.PacketListener, error)

func Pack

func Pack(dst, plaintext []byte, key *EncryptionKey) ([]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 Unpack

func Unpack(dst, pkt []byte, key *EncryptionKey) ([]byte, error)

Unpack decrypts a Shadowsocks-UDP packet in the format [salt][cipherText][AEAD tag] and returns a slice containing the decrypted 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.

Types

type EncryptionKey

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

EncryptionKey encapsulates a Shadowsocks AEAD spec and a secret

func NewEncryptionKey

func NewEncryptionKey(cipherName string, secretText string) (*EncryptionKey, error)

NewEncryptionKey creates a Cipher given a cipher name and a secret. The cipher name must be the IETF name (as per https://www.iana.org/assignments/aead-parameters/aead-parameters.xhtml) or the Shadowsocks alias from https://shadowsocks.org/guide/aead.html.

func (*EncryptionKey) NewAEAD

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

NewAEAD creates the AEAD for this cipher

func (*EncryptionKey) SaltSize

func (c *EncryptionKey) SaltSize() int

SaltSize is the size of the salt for this Cipher

func (*EncryptionKey) TagSize

func (c *EncryptionKey) TagSize() int

TagSize is the size of the AEAD tag for this Cipher

type ErrUnsupportedCipher

type ErrUnsupportedCipher struct {
	// The name of the requested [Cipher]
	Name string
}

ErrUnsupportedCipher is returned by [CypherByName] when the named cipher is not supported.

func (ErrUnsupportedCipher) Error

func (err ErrUnsupportedCipher) Error() string

type Reader

type Reader interface {
	io.Reader
	io.WriterTo
}

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

func NewReader

func NewReader(reader io.Reader, key *EncryptionKey) Reader

NewReader creates a Reader that decrypts the given io.Reader using the shadowsocks protocol with the given encryption key.

type SaltGenerator

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

SaltGenerator generates unique salts to use in Shadowsocks connections.

var RandomSaltGenerator SaltGenerator = randomSaltGenerator{}

RandomSaltGenerator is a basic SaltGenerator.

func NewPrefixSaltGenerator

func NewPrefixSaltGenerator(prefix []byte) SaltGenerator

NewPrefixSaltGenerator returns a SaltGenerator whose output consists of the provided prefix, followed by random bytes. This is useful to change how shadowsocks traffic is classified by middleboxes.

Note: Prefixes steal entropy from the initialization vector. This weakens security by increasing the likelihood that the same IV is used in two different connections (which becomes likely once 2^(N/2) connections are made, due to the birthday attack). If an IV is reused, the attacker can not only decrypt the ciphertext of those two connections; they can also easily recover the shadowsocks key and decrypt all other connections to this server. Use with care!

type StreamDialer

type StreamDialer struct {

	// SaltGenerator is used by Shadowsocks to generate the connection salts.
	// `SaltGenerator` may be `nil`, which defaults to [shadowsocks.RandomSaltGenerator].
	SaltGenerator SaltGenerator

	// ClientDataWait specifies the amount of time to wait for client data before sending
	// the Shadowsocks connection request to the proxy server. It's 10 milliseconds by default.
	//
	// StreamDialer has an optimization to send the initial client payload along with
	// the Shadowsocks connection request.  This saves one packet during connection, and also
	// reduces the distinctiveness of the connection pattern.
	//
	// Normally, the initial payload will be sent as soon as the socket is connected,
	// except for delays due to inter-process communication.  However, some protocols
	// expect the server to send data first, in which case there is no client payload.
	// We therefore use a short delay by default (10ms), longer than any reasonable IPC but shorter than
	// typical network latency.  (In an Android emulator, the 90th percentile delay
	// was ~1 ms.)  If no client payload is received by this time, we connect without it.
	ClientDataWait time.Duration
	// contains filtered or unexported fields
}

func NewStreamDialer

func NewStreamDialer(endpoint transport.StreamEndpoint, key *EncryptionKey) (*StreamDialer, error)

NewStreamDialer creates a client that routes connections to a Shadowsocks proxy listening at the given StreamEndpoint, with `key` as the Shadowsocks encyption key.

func (*StreamDialer) Dial

func (c *StreamDialer) Dial(ctx context.Context, remoteAddr string) (transport.StreamConn, error)

Dial implements StreamDialer.Dial via a Shadowsocks server.

The Shadowsocks StreamDialer returns a connection after the connection to the proxy is established, but before the connection to the target is established. That means we cannot signal "connection refused" or "connection timeout" errors from the target to the application.

This behavior breaks IPv6 Happy Eyeballs because the application IPv6 socket will connect successfully, even if the proxy fails to connect to the IPv6 destination. The broken Happy Eyeballs behavior makes IPv6 unusable if the proxy cannot use IPv6.

We can't easily fix that issue because Shadowsocks, unlike SOCKS, does not have a way to indicate whether the target connection is successful. Even if that was possible, we want to wait until we have initial data from the application in order to send the Shadowsocks salt, SOCKS address and initial data all in one packet. This makes the size of the initial packet hard to predict, avoiding packet size fingerprinting. We can only get the application initial data if we return a connection first.

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 NewWriter

func NewWriter(writer io.Writer, key *EncryptionKey) *Writer

NewWriter creates a Writer that encrypts the given io.Writer using the shadowsocks protocol with the given encryption key.

func (*Writer) Flush

func (sw *Writer) Flush() error

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

func (*Writer) LazyWrite

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

LazyWrite queues p to be written, but doesn't send it until Flush() is called, a non-lazy write is made, or the buffer is filled.

func (*Writer) ReadFrom

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

ReadFrom implements the io.ReaderFrom interface.

func (*Writer) SetSaltGenerator

func (sw *Writer) SetSaltGenerator(saltGenerator SaltGenerator)

SetSaltGenerator sets the salt generator to be used. Must be called before the first write.

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