Compare commits

..

10 Commits

Author SHA1 Message Date
Darien Raymond
948c86e5c5 remove unnecessary function call 2016-12-13 07:03:48 +01:00
Darien Raymond
3005526e32 Fix response option 2016-12-12 22:46:15 +01:00
Darien Raymond
42417cab17 fix compile warning 2016-12-12 21:58:13 +01:00
Darien Raymond
582438ce5e gofmt 2016-12-12 21:54:28 +01:00
Darien Raymond
ed9217bf20 test partial read 2016-12-12 21:49:04 +01:00
Darien Raymond
201d6e6471 support aggressive mode in auth reader 2016-12-12 21:44:16 +01:00
Darien Raymond
417284ed99 fix auth reader 2016-12-12 17:42:03 +01:00
Darien Raymond
a67d525fc2 try fix connection reuse settings 2016-12-12 13:08:31 +01:00
Darien Raymond
f159d504f2 comments 2016-12-12 02:14:48 +01:00
Darien Raymond
a11d2ce9d6 support server name override 2016-12-11 23:58:37 +01:00
16 changed files with 241 additions and 35 deletions

View File

@@ -58,8 +58,6 @@ type BufferToBytesReader struct {
eof bool
}
// Private: Visible for testing.
func (v *BufferToBytesReader) Fill() {
b, err := v.stream.Read()

View File

@@ -6,10 +6,12 @@ import (
"io"
)
// OriginalReader invokes bufio.NewReader() from Golang standard library.
func OriginalReader(reader io.Reader) *bufio.Reader {
return bufio.NewReader(reader)
}
// OriginalReaderSize invokes bufio.NewReaderSize() from Golang standard library.
func OriginalReaderSize(reader io.Reader, size int) *bufio.Reader {
return bufio.NewReaderSize(reader, size)
}

View File

@@ -4,9 +4,11 @@ import (
"io"
"sync"
"v2ray.com/core/common"
"v2ray.com/core/common/buf"
)
// BufferedReader is a reader with internal cache.
type BufferedReader struct {
sync.Mutex
reader io.Reader
@@ -14,6 +16,7 @@ type BufferedReader struct {
cached bool
}
// NewReader creates a new BufferedReader based on an io.Reader.
func NewReader(rawReader io.Reader) *BufferedReader {
return &BufferedReader{
reader: rawReader,
@@ -22,23 +25,31 @@ func NewReader(rawReader io.Reader) *BufferedReader {
}
}
// Release implements Releasable.Release().
func (v *BufferedReader) Release() {
v.Lock()
defer v.Unlock()
v.buffer.Release()
v.buffer = nil
if releasable, ok := v.reader.(common.Releasable); ok {
releasable.Release()
}
v.reader = nil
}
// Cached returns true if the internal cache is effective.
func (v *BufferedReader) Cached() bool {
return v.cached
}
// SetCached is to enable or disable internal cache. If cache is disabled,
// Read() and Write() calls will be delegated to the underlying io.Reader directly.
func (v *BufferedReader) SetCached(cached bool) {
v.cached = cached
}
// Read implements io.Reader.Read().
func (v *BufferedReader) Read(b []byte) (int, error) {
v.Lock()
defer v.Unlock()

View File

@@ -4,6 +4,7 @@ import (
"io"
"sync"
"v2ray.com/core/common"
"v2ray.com/core/common/buf"
"v2ray.com/core/common/errors"
)
@@ -117,5 +118,9 @@ func (v *BufferedWriter) Release() {
v.buffer.Release()
v.buffer = nil
if releasable, ok := v.writer.(common.Releasable); ok {
releasable.Release()
}
v.writer = nil
}

View File

@@ -139,7 +139,9 @@ func (v *AuthenticationReader) EnsureChunk() error {
return copy(b, leftover), nil
})
}
err = v.buffer.AppendSupplier(buf.ReadFrom(v.reader))
if err := v.buffer.AppendSupplier(buf.ReadFrom(v.reader)); err == nil {
continue
}
}
return err
}
@@ -156,8 +158,14 @@ func (v *AuthenticationReader) Read(b []byte) (int, error) {
return 0, err
}
nBytes := v.CopyChunk(b)
return nBytes, nil
totalBytes := v.CopyChunk(b)
for v.aggressive {
if err := v.NextChunk(); err != nil {
break
}
totalBytes += v.CopyChunk(b[totalBytes:])
}
return totalBytes, nil
}
type AuthenticationWriter struct {

173
common/crypto/auth_test.go Normal file
View File

@@ -0,0 +1,173 @@
package crypto_test
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"io"
"testing"
"v2ray.com/core/common/buf"
. "v2ray.com/core/common/crypto"
"v2ray.com/core/testing/assert"
)
func TestAuthenticationReaderWriter(t *testing.T) {
assert := assert.On(t)
key := make([]byte, 16)
rand.Read(key)
block, err := aes.NewCipher(key)
assert.Error(err).IsNil()
aead, err := cipher.NewGCM(block)
assert.Error(err).IsNil()
payload := make([]byte, 8*1024)
rand.Read(payload)
cache := buf.NewLocal(16 * 1024)
iv := make([]byte, 12)
rand.Read(iv)
writer := NewAuthenticationWriter(&AEADAuthenticator{
AEAD: aead,
NonceGenerator: &StaticBytesGenerator{
Content: iv,
},
AdditionalDataGenerator: &NoOpBytesGenerator{},
}, cache)
nBytes, err := writer.Write(payload)
assert.Error(err).IsNil()
assert.Int(nBytes).Equals(len(payload))
assert.Int(cache.Len()).GreaterThan(0)
_, err = writer.Write([]byte{})
assert.Error(err).IsNil()
reader := NewAuthenticationReader(&AEADAuthenticator{
AEAD: aead,
NonceGenerator: &StaticBytesGenerator{
Content: iv,
},
AdditionalDataGenerator: &NoOpBytesGenerator{},
}, cache, false)
actualPayload := make([]byte, 16*1024)
nBytes, err = reader.Read(actualPayload)
assert.Error(err).IsNil()
assert.Int(nBytes).Equals(len(payload))
assert.Bytes(actualPayload[:nBytes]).Equals(payload)
_, err = reader.Read(actualPayload)
assert.Error(err).Equals(io.EOF)
}
func TestAuthenticationReaderWriterPartial(t *testing.T) {
assert := assert.On(t)
key := make([]byte, 16)
rand.Read(key)
block, err := aes.NewCipher(key)
assert.Error(err).IsNil()
aead, err := cipher.NewGCM(block)
assert.Error(err).IsNil()
payload := make([]byte, 8*1024)
rand.Read(payload)
cache := buf.NewLocal(16 * 1024)
iv := make([]byte, 12)
rand.Read(iv)
writer := NewAuthenticationWriter(&AEADAuthenticator{
AEAD: aead,
NonceGenerator: &StaticBytesGenerator{
Content: iv,
},
AdditionalDataGenerator: &NoOpBytesGenerator{},
}, cache)
nBytes, err := writer.Write(payload)
assert.Error(err).IsNil()
assert.Int(nBytes).Equals(len(payload))
assert.Int(cache.Len()).GreaterThan(0)
_, err = writer.Write([]byte{})
assert.Error(err).IsNil()
reader := NewAuthenticationReader(&AEADAuthenticator{
AEAD: aead,
NonceGenerator: &StaticBytesGenerator{
Content: iv,
},
AdditionalDataGenerator: &NoOpBytesGenerator{},
}, cache, false)
actualPayload := make([]byte, 7*1024)
nBytes, err = reader.Read(actualPayload)
assert.Error(err).IsNil()
assert.Int(nBytes).Equals(len(actualPayload))
assert.Bytes(actualPayload[:nBytes]).Equals(payload[:nBytes])
nBytes, err = reader.Read(actualPayload)
assert.Error(err).IsNil()
assert.Int(nBytes).Equals(len(payload) - len(actualPayload))
assert.Bytes(actualPayload[:nBytes]).Equals(payload[7*1024:])
_, err = reader.Read(actualPayload)
assert.Error(err).Equals(io.EOF)
}
func TestAuthenticationReaderWriterAggressive(t *testing.T) {
assert := assert.On(t)
key := make([]byte, 16)
rand.Read(key)
block, err := aes.NewCipher(key)
assert.Error(err).IsNil()
aead, err := cipher.NewGCM(block)
assert.Error(err).IsNil()
payload := make([]byte, 7*1024)
rand.Read(payload)
cache := buf.NewLocal(16 * 1024)
iv := make([]byte, 12)
rand.Read(iv)
writer := NewAuthenticationWriter(&AEADAuthenticator{
AEAD: aead,
NonceGenerator: &StaticBytesGenerator{
Content: iv,
},
AdditionalDataGenerator: &NoOpBytesGenerator{},
}, cache)
nBytes, err := writer.Write(payload)
assert.Error(err).IsNil()
assert.Int(nBytes).Equals(len(payload))
assert.Int(cache.Len()).GreaterThan(0)
_, err = writer.Write(payload)
assert.Error(err).IsNil()
assert.Int(nBytes).Equals(len(payload))
_, err = writer.Write([]byte{})
assert.Error(err).IsNil()
reader := NewAuthenticationReader(&AEADAuthenticator{
AEAD: aead,
NonceGenerator: &StaticBytesGenerator{
Content: iv,
},
AdditionalDataGenerator: &NoOpBytesGenerator{},
}, cache, true)
actualPayload := make([]byte, 16*1024)
nBytes, err = reader.Read(actualPayload)
assert.Error(err).IsNil()
assert.Int(nBytes).Equals(len(payload) * 2)
_, err = reader.Read(actualPayload)
assert.Error(err).Equals(io.EOF)
}

View File

@@ -67,7 +67,7 @@ func (v *ResponseOption) Set(option ResponseOption) {
}
func (v ResponseOption) Has(option ResponseOption) bool {
return (v | option) == option
return (v & option) == option
}
func (v *ResponseOption) Clear(option ResponseOption) {

View File

@@ -30,7 +30,7 @@ func TestRequestSerialization(t *testing.T) {
Version: 1,
User: user,
Command: protocol.RequestCommandTCP,
Option: protocol.RequestOption(0),
Option: protocol.RequestOptionConnectionReuse,
Address: v2net.DomainAddress("www.v2ray.com"),
Port: v2net.Port(443),
Security: protocol.Security(protocol.SecurityType_AES128_GCM),

View File

@@ -138,9 +138,7 @@ func (v *VMessOutboundHandler) handleResponse(session *encoding.ClientSession, c
}
go v.handleCommand(dest, header.Command)
if !header.Option.Has(protocol.ResponseOptionConnectionReuse) {
conn.SetReusable(false)
}
conn.SetReusable(header.Option.Has(protocol.ResponseOptionConnectionReuse))
reader.SetCached(false)
bodyReader := session.DecodeResponseBody(request, reader)

View File

@@ -146,8 +146,9 @@ type TLSCertConfig struct {
KeyFile string `json:"keyFile"`
}
type TLSConfig struct {
Insecure bool `json:"allowInsecure"`
Certs []*TLSCertConfig `json:"certificates"`
Insecure bool `json:"allowInsecure"`
Certs []*TLSCertConfig `json:"certificates"`
ServerName string `json:"serverName"`
}
func (v *TLSConfig) Build() (*loader.TypedSettings, error) {
@@ -168,6 +169,9 @@ func (v *TLSConfig) Build() (*loader.TypedSettings, error) {
}
}
config.AllowInsecure = v.Insecure
if len(v.ServerName) > 0 {
config.ServerName = v.ServerName
}
return loader.NewTypedSettings(config), nil
}

View File

@@ -19,8 +19,8 @@ func (v *SRTP) Size() int {
func (v *SRTP) Write(b []byte) (int, error) {
v.number++
b = serial.Uint16ToBytes(v.number, b[:0])
b = serial.Uint16ToBytes(v.number, b)
serial.Uint16ToBytes(v.number, b[:0])
serial.Uint16ToBytes(v.number, b[:2])
return 4, nil
}

View File

@@ -19,8 +19,9 @@ func (v *UTP) Size() int {
}
func (v *UTP) Write(b []byte) (int, error) {
b = serial.Uint16ToBytes(v.connectionId, b[:0])
b = append(b, v.header, v.extension)
serial.Uint16ToBytes(v.connectionId, b[:0])
b[2] = v.header
b[3] = v.extension
return 4, nil
}

View File

@@ -93,14 +93,11 @@ func (v *Connection) SetWriteDeadline(t time.Time) error {
}
func (v *Connection) SetReusable(reusable bool) {
if !v.config.ConnectionReuse.IsEnabled() {
return
}
v.reusable = reusable
}
func (v *Connection) Reusable() bool {
return v.reusable
return v.config.ConnectionReuse.IsEnabled() && v.reusable
}
func (v *Connection) SysFd() (int, error) {

View File

@@ -34,6 +34,9 @@ func (v *Config) GetTLSConfig() *tls.Config {
config.InsecureSkipVerify = v.AllowInsecure
config.Certificates = v.BuildCertificates()
config.BuildNameToCertificate()
if len(v.ServerName) > 0 {
config.ServerName = v.ServerName
}
return config
}

View File

@@ -46,6 +46,8 @@ type Config struct {
AllowInsecure bool `protobuf:"varint,1,opt,name=allow_insecure,json=allowInsecure" json:"allow_insecure,omitempty"`
// List of certificates to be served on server.
Certificate []*Certificate `protobuf:"bytes,2,rep,name=certificate" json:"certificate,omitempty"`
// Override server name.
ServerName string `protobuf:"bytes,3,opt,name=server_name,json=serverName" json:"server_name,omitempty"`
}
func (m *Config) Reset() { *m = Config{} }
@@ -68,19 +70,20 @@ func init() {
func init() { proto.RegisterFile("v2ray.com/core/transport/internet/tls/config.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 218 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x84, 0x50, 0xb1, 0x4a, 0x03, 0x41,
0x10, 0xe5, 0x72, 0x10, 0x64, 0x57, 0x45, 0xb6, 0x4a, 0x79, 0x06, 0x02, 0xa9, 0x66, 0xe1, 0xac,
0x2c, 0x4d, 0x2a, 0xb1, 0x09, 0x57, 0xda, 0xc8, 0xba, 0x4c, 0x64, 0x61, 0xb3, 0x13, 0x66, 0x47,
0x25, 0xa5, 0x7f, 0x2e, 0xd9, 0x78, 0x72, 0x57, 0x5d, 0x37, 0xf3, 0xe6, 0xcd, 0x7b, 0x8f, 0xa7,
0xda, 0xaf, 0x96, 0xdd, 0x09, 0x3c, 0x1d, 0xac, 0x27, 0x46, 0x2b, 0xec, 0x52, 0x3e, 0x12, 0x8b,
0x0d, 0x49, 0x90, 0x13, 0x8a, 0x95, 0x98, 0xad, 0xa7, 0xb4, 0x0f, 0x1f, 0x70, 0x64, 0x12, 0x32,
0xf7, 0xfd, 0x0f, 0x23, 0xfc, 0xf3, 0xa1, 0xe7, 0x83, 0xc4, 0xbc, 0x7c, 0x52, 0x7a, 0x8b, 0x2c,
0x61, 0x1f, 0xbc, 0x13, 0x34, 0xcd, 0x68, 0x5d, 0x54, 0x4d, 0xb5, 0xbe, 0xee, 0x46, 0x8c, 0x3b,
0x55, 0xbf, 0xe0, 0x69, 0x31, 0x2b, 0x97, 0xf3, 0xb8, 0xfc, 0xa9, 0xd4, 0x7c, 0x5b, 0x6c, 0xcd,
0x4a, 0xdd, 0xba, 0x18, 0xe9, 0xfb, 0x2d, 0xa4, 0x8c, 0xfe, 0x93, 0x2f, 0x0a, 0x57, 0xdd, 0x4d,
0x41, 0x9f, 0xff, 0x40, 0xb3, 0x53, 0xda, 0x0f, 0x5c, 0x66, 0x4d, 0xbd, 0xd6, 0x2d, 0xc0, 0x64,
0x5a, 0x18, 0x04, 0xe9, 0x86, 0x12, 0x9b, 0x47, 0xb5, 0xf2, 0x74, 0x98, 0x56, 0xd8, 0xe8, 0x4b,
0xd2, 0xdd, 0xb9, 0x9f, 0xd7, 0x5a, 0x62, 0x7e, 0x9f, 0x97, 0xae, 0x1e, 0x7e, 0x03, 0x00, 0x00,
0xff, 0xff, 0x5d, 0x97, 0x5b, 0x86, 0x61, 0x01, 0x00, 0x00,
// 240 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x84, 0x50, 0xc1, 0x4a, 0x03, 0x31,
0x10, 0x65, 0xbb, 0x50, 0x74, 0xa2, 0x22, 0x39, 0xed, 0xcd, 0xb5, 0x50, 0xd8, 0x53, 0x02, 0xeb,
0xc9, 0xa3, 0xed, 0x49, 0x04, 0x29, 0x7b, 0xf4, 0x52, 0x62, 0x98, 0x4a, 0x20, 0x9b, 0x94, 0xc9,
0x58, 0xe9, 0xef, 0xf8, 0xa5, 0xd2, 0xac, 0x2d, 0xdb, 0x53, 0x6f, 0xc9, 0x9b, 0x37, 0xef, 0xbd,
0x79, 0xd0, 0xee, 0x5a, 0x32, 0x7b, 0x65, 0x63, 0xaf, 0x6d, 0x24, 0xd4, 0x4c, 0x26, 0xa4, 0x6d,
0x24, 0xd6, 0x2e, 0x30, 0x52, 0x40, 0xd6, 0xec, 0x93, 0xb6, 0x31, 0x6c, 0xdc, 0x97, 0xda, 0x52,
0xe4, 0x28, 0x1f, 0x8f, 0x3b, 0x84, 0xea, 0xc4, 0x57, 0x47, 0xbe, 0x62, 0x9f, 0x66, 0x2f, 0x20,
0x96, 0x48, 0xec, 0x36, 0xce, 0x1a, 0x46, 0x59, 0x9f, 0x7d, 0xab, 0xa2, 0x2e, 0x9a, 0x9b, 0xee,
0x8c, 0x71, 0x0f, 0xe5, 0x1b, 0xee, 0xab, 0x49, 0x9e, 0x1c, 0x9e, 0xb3, 0xdf, 0x02, 0xa6, 0xcb,
0x6c, 0x2b, 0xe7, 0x70, 0x67, 0xbc, 0x8f, 0x3f, 0x6b, 0x17, 0x12, 0xda, 0x6f, 0x1a, 0x14, 0xae,
0xba, 0xdb, 0x8c, 0xbe, 0xfe, 0x83, 0x72, 0x05, 0xc2, 0x8e, 0x5c, 0x26, 0x75, 0xd9, 0x88, 0x56,
0xa9, 0x8b, 0x69, 0xd5, 0x28, 0x48, 0x37, 0x96, 0x90, 0x0f, 0x20, 0x12, 0xd2, 0x0e, 0x69, 0x1d,
0x4c, 0x8f, 0x55, 0x59, 0x17, 0xcd, 0x75, 0x07, 0x03, 0xf4, 0x6e, 0x7a, 0x5c, 0x3c, 0xc3, 0xdc,
0xc6, 0xfe, 0xb2, 0xc5, 0x42, 0x0c, 0xa7, 0xac, 0x0e, 0x05, 0x7e, 0x94, 0xec, 0xd3, 0xe7, 0x34,
0x97, 0xf9, 0xf4, 0x17, 0x00, 0x00, 0xff, 0xff, 0x42, 0x2a, 0x28, 0x66, 0x82, 0x01, 0x00, 0x00,
}

View File

@@ -19,4 +19,7 @@ message Config {
// List of certificates to be served on server.
repeated Certificate certificate = 2;
// Override server name.
string server_name = 3;
}