diff --git a/proxy/shadowsocks/config.go b/proxy/shadowsocks/config.go index 43e4b3c6a..1408407f7 100644 --- a/proxy/shadowsocks/config.go +++ b/proxy/shadowsocks/config.go @@ -102,12 +102,17 @@ type Cipher interface { IVSize() int NewEncryptionWriter(key []byte, iv []byte, writer io.Writer) (buf.Writer, error) NewDecryptionReader(key []byte, iv []byte, reader io.Reader) (buf.Reader, error) + IsAEAD() bool } type AesCfb struct { KeyBytes int } +func (*AesCfb) IsAEAD() bool { + return false +} + func (v *AesCfb) KeySize() int { return v.KeyBytes } @@ -132,6 +137,10 @@ type AEADCipher struct { AEADAuthCreator func(key []byte) cipher.AEAD } +func (*AEADCipher) IsAEAD() bool { + return true +} + func (c *AEADCipher) KeySize() int { return c.KeyBytes } @@ -170,6 +179,10 @@ type ChaCha20 struct { IVBytes int } +func (*ChaCha20) IsAEAD() bool { + return false +} + func (v *ChaCha20) KeySize() int { return 32 } diff --git a/proxy/shadowsocks/protocol.go b/proxy/shadowsocks/protocol.go index 5901d3d05..c58ecbcc2 100644 --- a/proxy/shadowsocks/protocol.go +++ b/proxy/shadowsocks/protocol.go @@ -61,7 +61,7 @@ func ReadTCPSession(user *protocol.User, reader io.Reader) (*protocol.RequestHea request.Option.Set(RequestOptionOneTimeAuth) } - if request.Option.Has(RequestOptionOneTimeAuth) && account.OneTimeAuth == Account_Disabled { + if request.Option.Has(RequestOptionOneTimeAuth) && (account.OneTimeAuth == Account_Disabled || account.Cipher.IsAEAD()) { return nil, nil, newError("rejecting connection with OTA enabled, while server disables OTA") } @@ -136,8 +136,12 @@ func WriteTCPRequest(request *protocol.RequestHeader, writer io.Writer) (buf.Wri } account := rawAccount.(*ShadowsocksAccount) + if account.Cipher.IsAEAD() { + request.Option.Clear(RequestOptionOneTimeAuth) + } + iv := make([]byte, account.Cipher.IVSize()) - rand.Read(iv) + common.Must2(rand.Read(iv)) _, err = writer.Write(iv) if err != nil { return nil, newError("failed to write IV")