diff --git a/common/serial/string_json.go b/common/serial/string_json.go new file mode 100644 index 00000000..5f0f20fe --- /dev/null +++ b/common/serial/string_json.go @@ -0,0 +1,16 @@ +// +build json + +package serial + +import ( + "encoding/json" +) + +func (this *StringLiteral) UnmarshalJSON(data []byte) error { + var str string + if err := json.Unmarshal(data, &str); err != nil { + return err + } + *this = StringLiteral(str) + return nil +} diff --git a/proxy/shadowsocks/config.go b/proxy/shadowsocks/config.go new file mode 100644 index 00000000..2a876c38 --- /dev/null +++ b/proxy/shadowsocks/config.go @@ -0,0 +1,49 @@ +package shadowsocks + +import ( + "io" + + "github.com/v2ray/v2ray-core/common/crypto" +) + +type Cipher interface { + KeySize() int + IVSize() int + NewEncodingStream(key []byte, iv []byte, writer io.Writer) (io.Writer, error) + NewDecodingStream(key []byte, iv []byte, reader io.Reader) (io.Reader, error) +} + +type AesCfb struct { + KeyBytes int +} + +func (this *AesCfb) KeySize() int { + return this.KeyBytes +} + +func (this *AesCfb) IVSize() int { + return 16 +} + +func (this *AesCfb) NewEncodingStream(key []byte, iv []byte, writer io.Writer) (io.Writer, error) { + stream, err := crypto.NewAesEncryptionStream(key, iv) + if err != nil { + return nil, err + } + aesWriter := crypto.NewCryptionWriter(stream, writer) + return aesWriter, nil +} + +func (this *AesCfb) NewDecodingStream(key []byte, iv []byte, reader io.Reader) (io.Reader, error) { + stream, err := crypto.NewAesDecryptionStream(key, iv) + if err != nil { + return nil, err + } + aesReader := crypto.NewCryptionReader(stream, reader) + return aesReader, nil +} + +type Config struct { + Cipher Cipher + Password string +} diff --git a/proxy/shadowsocks/config_json.go b/proxy/shadowsocks/config_json.go new file mode 100644 index 00000000..238f8c6c --- /dev/null +++ b/proxy/shadowsocks/config_json.go @@ -0,0 +1,46 @@ +// +build json + +package shadowsocks + +import ( + "encoding/json" + + "github.com/v2ray/v2ray-core/common/log" + "github.com/v2ray/v2ray-core/common/serial" + "github.com/v2ray/v2ray-core/proxy/internal" +) + +func (this *Config) UnmarshalJSON(data []byte) error { + type JsonConfig struct { + Cipher *serial.StringLiteral `json:"method"` + Password *serial.StringLiteral `json:"password"` + } + jsonConfig := new(JsonConfig) + if err := json.Unmarshal(data, jsonConfig); err != nil { + return err + } + if this.Password == nil { + log.Error("Shadowsocks: Password is not specified.") + return internal.ErrorBadConfiguration + } + this.Password = jsonConfig.Password.String() + if this.Cipher == nil { + log.Error("Shadowsocks: Cipher method is not specified.") + return internal.ErrorBadConfiguration + } + jsonConfig.Cipher = jsonConfig.Cipher.ToLower() + switch jsonConfig.Cipher.String() { + case "aes-256-cfb": + this.Cipher = &AesCfb { + KeyBytes: 32 + } + case "aes-128-cfb": + this.Cipher = &AesCfb { + KeyBytes: 32 + } + default: + log.Error("Shadowsocks: Unknown cipher method: ", jsonConfig.Cipher) + return internal.ErrorBadConfiguration + } + return nil +} diff --git a/proxy/shadowsocks/shadowsocks.go b/proxy/shadowsocks/shadowsocks.go new file mode 100644 index 00000000..666346e0 --- /dev/null +++ b/proxy/shadowsocks/shadowsocks.go @@ -0,0 +1,20 @@ +// R.I.P Shadowsocks + +package shadowsocks + +import ( + v2net "github.com/v2ray/v2ray-core/common/net" +) + +type Shadowsocks struct { + config *Config + port v2net.Port +} + +func (this *Shadowsocks) Port() v2net.Port { + return this.port +} + +func (this *Shadowsocks) Listen(port v2net.Port) error { + return nil +}