func TestNormalChunkWriting(t *testing.T) { assert := assert.On(t) buffer := buf.NewLocal(512) writer := NewChunkWriter(buffer, NewAuthenticator(ChunkKeyGenerator( []byte{21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36}))) b := buf.NewLocal(256) b.Append([]byte{11, 12, 13, 14, 15, 16, 17, 18}) err := writer.Write(b) assert.Error(err).IsNil() assert.Bytes(buffer.Bytes()).Equals([]byte{0, 8, 39, 228, 69, 96, 133, 39, 254, 26, 201, 70, 11, 12, 13, 14, 15, 16, 17, 18}) }
func (v *DefaultDispatcher) DispatchToOutbound(session *proxy.SessionInfo) ray.InboundRay { direct := ray.NewRay() dispatcher := v.ohm.GetDefaultHandler() destination := session.Destination if v.router != nil { if tag, err := v.router.TakeDetour(session); err == nil { if handler := v.ohm.GetHandler(tag); handler != nil { log.Info("DefaultDispatcher: Taking detour [", tag, "] for [", destination, "].") dispatcher = handler } else { log.Warning("DefaultDispatcher: Nonexisting tag: ", tag) } } else { log.Info("DefaultDispatcher: Default route for ", destination) } } if session.Inbound != nil && session.Inbound.AllowPassiveConnection { go dispatcher.Dispatch(destination, buf.NewLocal(32), direct) } else { go v.FilterPacketAndDispatch(destination, direct, dispatcher) } return direct }
func TestResponseWrite(t *testing.T) { assert := assert.On(t) response := Socks5Response{ socksVersion, ErrorSuccess, AddrTypeIPv4, [4]byte{0x72, 0x72, 0x72, 0x72}, "", [16]byte{}, v2net.Port(53), } buffer := buf.NewLocal(2048) defer buffer.Release() response.Write(buffer) expectedBytes := []byte{ socksVersion, ErrorSuccess, byte(0x00), AddrTypeIPv4, 0x72, 0x72, 0x72, 0x72, byte(0x00), byte(0x035), } assert.Bytes(buffer.Bytes()).Equals(expectedBytes) }
func Test1ByteDataSegment(t *testing.T) { assert := assert.On(t) b := buf.NewLocal(512) b.AppendBytes('a') seg := &DataSegment{ Conv: 1, Timestamp: 3, Number: 4, SendingNext: 5, Data: b, } nBytes := seg.ByteSize() bytes := make([]byte, nBytes) seg.Bytes()(bytes) assert.Int(len(bytes)).Equals(nBytes) iseg, _ := ReadSegment(bytes) seg2 := iseg.(*DataSegment) assert.Uint16(seg2.Conv).Equals(seg.Conv) assert.Uint32(seg2.Timestamp).Equals(seg.Timestamp) assert.Uint32(seg2.SendingNext).Equals(seg.SendingNext) assert.Uint32(seg2.Number).Equals(seg.Number) assert.Bytes(seg2.Data.Bytes()).Equals(seg.Data.Bytes()) }
func ReadUserPassRequest(reader io.Reader) (request Socks5UserPassRequest, err error) { buffer := buf.NewLocal(512) defer buffer.Release() err = buffer.AppendSupplier(buf.ReadFullFrom(reader, 2)) if err != nil { return } request.version = buffer.Byte(0) nUsername := int(buffer.Byte(1)) buffer.Clear() err = buffer.AppendSupplier(buf.ReadFullFrom(reader, nUsername)) if err != nil { return } request.username = buffer.String() err = buffer.AppendSupplier(buf.ReadFullFrom(reader, 1)) if err != nil { return } nPassword := int(buffer.Byte(0)) err = buffer.AppendSupplier(buf.ReadFullFrom(reader, nPassword)) if err != nil { return } request.password = buffer.String() return }
func (v *ChunkReader) Read() (*buf.Buffer, error) { buffer := buf.New() if err := buffer.AppendSupplier(buf.ReadFullFrom(v.reader, 2)); err != nil { buffer.Release() return nil, err } // There is a potential buffer overflow here. Large buffer is 64K bytes, // while uin16 + 10 will be more than that length := serial.BytesToUint16(buffer.BytesTo(2)) + AuthSize if length > buf.Size { // Theoretically the size of a chunk is 64K, but most Shadowsocks implementations used <4K buffer. buffer.Release() buffer = buf.NewLocal(int(length) + 128) } buffer.Clear() if err := buffer.AppendSupplier(buf.ReadFullFrom(v.reader, int(length))); err != nil { buffer.Release() return nil, err } authBytes := buffer.BytesTo(AuthSize) payload := buffer.BytesFrom(AuthSize) actualAuthBytes := make([]byte, AuthSize) v.auth.Authenticate(payload)(actualAuthBytes) if !bytes.Equal(authBytes, actualAuthBytes) { buffer.Release() return nil, errors.New("Shadowsocks|AuthenticationReader: Invalid auth.") } buffer.SliceFrom(AuthSize) return buffer, nil }
func TestUDPEncoding(t *testing.T) { assert := assert.On(t) request := &protocol.RequestHeader{ Version: Version, Command: protocol.RequestCommandUDP, Address: v2net.LocalHostIP, Port: 1234, User: &protocol.User{ Email: "*****@*****.**", Account: serial.ToTypedMessage(&Account{ Password: "******", CipherType: CipherType_AES_128_CFB, Ota: Account_Disabled, }), }, } data := buf.NewLocal(256) data.AppendSupplier(serial.WriteString("test string")) encodedData, err := EncodeUDPPacket(request, data) assert.Error(err).IsNil() decodedRequest, decodedData, err := DecodeUDPPacket(request.User, encodedData) assert.Error(err).IsNil() assert.Bytes(decodedData.Bytes()).Equals(data.Bytes()) assert.Address(decodedRequest.Address).Equals(request.Address) assert.Port(decodedRequest.Port).Equals(request.Port) }
func MarshalCommand(command interface{}, writer io.Writer) error { if command == nil { return ErrUnknownCommand } var cmdID byte var factory CommandFactory switch command.(type) { case *protocol.CommandSwitchAccount: factory = new(CommandSwitchAccountFactory) cmdID = 1 default: return ErrUnknownCommand } buffer := buf.NewLocal(512) defer buffer.Release() err := factory.Marshal(command, buffer) if err != nil { return err } auth := Authenticate(buffer.Bytes()) len := buffer.Len() + 4 if len > 255 { return ErrCommandTooLarge } writer.Write([]byte{cmdID, byte(len), byte(auth >> 24), byte(auth >> 16), byte(auth >> 8), byte(auth)}) writer.Write(buffer.Bytes()) return nil }
// NewReader creates a new BufferedReader based on an io.Reader. func NewReader(rawReader io.Reader) *BufferedReader { return &BufferedReader{ reader: rawReader, buffer: buf.NewLocal(1024), buffered: true, } }
func (v *VMessOutboundHandler) handleRequest(session *encoding.ClientSession, conn internet.Connection, request *protocol.RequestHeader, payload *buf.Buffer, input buf.Reader, finish *sync.Mutex) { defer finish.Unlock() writer := bufio.NewWriter(conn) defer writer.Release() session.EncodeRequestHeader(request, writer) bodyWriter := session.EncodeRequestBody(request, writer) defer bodyWriter.Release() if !payload.IsEmpty() { if err := bodyWriter.Write(payload); err != nil { log.Info("VMess|Outbound: Failed to write payload. Disabling connection reuse.", err) conn.SetReusable(false) } payload.Release() } writer.SetCached(false) if err := buf.PipeUntilEOF(input, bodyWriter); err != nil { conn.SetReusable(false) } if request.Option.Has(protocol.RequestOptionChunkStream) { err := bodyWriter.Write(buf.NewLocal(8)) if err != nil { conn.SetReusable(false) } } return }
func readUsernamePassword(reader io.Reader) (string, string, error) { buffer := buf.NewLocal(512) defer buffer.Release() if err := buffer.AppendSupplier(buf.ReadFullFrom(reader, 2)); err != nil { return "", "", err } nUsername := int(buffer.Byte(1)) buffer.Clear() if err := buffer.AppendSupplier(buf.ReadFullFrom(reader, nUsername)); err != nil { return "", "", err } username := buffer.String() buffer.Clear() if err := buffer.AppendSupplier(buf.ReadFullFrom(reader, 1)); err != nil { return "", "", err } nPassword := int(buffer.Byte(0)) buffer.Clear() if err := buffer.AppendSupplier(buf.ReadFullFrom(reader, nPassword)); err != nil { return "", "", err } password := buffer.String() return username, password, nil }
func transferResponse(session *encoding.ServerSession, request *protocol.RequestHeader, response *protocol.ResponseHeader, input ray.InputStream, output io.Writer) error { session.EncodeResponseHeader(response, output) bodyWriter := session.EncodeResponseBody(request, output) // Optimize for small response packet data, err := input.Read() if err != nil { return err } if err := bodyWriter.Write(data); err != nil { return err } data.Release() if bufferedWriter, ok := output.(*bufio.BufferedWriter); ok { if err := bufferedWriter.SetBuffered(false); err != nil { return err } } if err := buf.PipeUntilEOF(input, bodyWriter); err != nil { return err } if request.Option.Has(protocol.RequestOptionChunkStream) { if err := bodyWriter.Write(buf.NewLocal(8)); err != nil { return err } } return nil }
// NewWriter creates a new BufferedWriter. func NewWriter(rawWriter io.Writer) *BufferedWriter { return &BufferedWriter{ writer: rawWriter, buffer: buf.NewLocal(1024), buffered: true, } }
func NewAuthenticationReader(auth Authenticator, reader io.Reader, aggressive bool) *AuthenticationReader { return &AuthenticationReader{ auth: auth, buffer: buf.NewLocal(readerBufferSize), reader: reader, aggressive: aggressive, } }
func writeSocks4Response(writer io.Writer, errCode byte, address v2net.Address, port v2net.Port) error { buffer := buf.NewLocal(32) buffer.AppendBytes(0x00, errCode) buffer.AppendSupplier(serial.WriteUint16(port.Value())) buffer.Append(address.IP()) _, err := writer.Write(buffer.Bytes()) return err }
func writeSocks5Response(writer io.Writer, errCode byte, address v2net.Address, port v2net.Port) error { buffer := buf.NewLocal(64) buffer.AppendBytes(socks5Version, errCode, 0x00 /* reserved */) appendAddress(buffer, address, port) _, err := writer.Write(buffer.Bytes()) return err }
func TestUTPWrite(t *testing.T) { assert := assert.On(t) video := VideoChat{} payload := buf.NewLocal(2048) payload.AppendSupplier(video.Write) assert.Int(payload.Len()).Equals(video.Size()) }
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 TestSocks4AuthenticationResponseToBytes(t *testing.T) { assert := assert.On(t) response := NewSocks4AuthenticationResponse(byte(0x10), 443, []byte{1, 2, 3, 4}) buffer := buf.NewLocal(2048) defer buffer.Release() response.Write(buffer) assert.Bytes(buffer.Bytes()).Equals([]byte{0x00, 0x10, 0x01, 0xBB, 0x01, 0x02, 0x03, 0x04}) }
func TestUTPWrite(t *testing.T) { assert := assert.On(t) content := []byte{'a', 'b', 'c', 'd', 'e', 'f', 'g'} utp := UTP{} payload := buf.NewLocal(2048) payload.AppendSupplier(utp.Write) payload.Append(content) assert.Int(payload.Len()).Equals(len(content) + utp.Size()) }
func TestSetIPv6(t *testing.T) { assert := assert.On(t) response := NewSocks5Response() response.SetIPv6([]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}) buffer := buf.NewLocal(2048) defer buffer.Release() response.Write(buffer) assert.Bytes(buffer.Bytes()).Equals([]byte{ socksVersion, 0, 0, AddrTypeIPv6, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0}) }
func TestSetDomain(t *testing.T) { assert := assert.On(t) response := NewSocks5Response() response.SetDomain("v2ray.com") buffer := buf.NewLocal(2048) defer buffer.Release() response.Write(buffer) assert.Bytes(buffer.Bytes()).Equals([]byte{ socksVersion, 0, 0, AddrTypeDomain, 9, 118, 50, 114, 97, 121, 46, 99, 111, 109, 0, 0}) }
func ReadRequest(reader io.Reader) (request *Socks5Request, err error) { buffer := buf.NewLocal(512) defer buffer.Release() err = buffer.AppendSupplier(buf.ReadFullFrom(reader, 4)) if err != nil { return } request = &Socks5Request{ Version: buffer.Byte(0), Command: buffer.Byte(1), // buffer[2] is a reserved field AddrType: buffer.Byte(3), } switch request.AddrType { case AddrTypeIPv4: _, err = io.ReadFull(reader, request.IPv4[:]) if err != nil { return } case AddrTypeDomain: buffer.Clear() err = buffer.AppendSupplier(buf.ReadFullFrom(reader, 1)) if err != nil { return } domainLength := int(buffer.Byte(0)) err = buffer.AppendSupplier(buf.ReadFullFrom(reader, domainLength)) if err != nil { return } request.Domain = string(buffer.BytesFrom(-domainLength)) case AddrTypeIPv6: _, err = io.ReadFull(reader, request.IPv6[:]) if err != nil { return } default: err = errors.Format("Socks: Unexpected address type %d", request.AddrType) return } err = buffer.AppendSupplier(buf.ReadFullFrom(reader, 2)) if err != nil { return } request.Port = v2net.PortFromBytes(buffer.BytesFrom(-2)) return }
func (v *Server) handleUDPPayload(payload *buf.Buffer, session *proxy.SessionInfo) { source := session.Source log.Info("Socks: Client UDP connection from ", source) request, err := protocol.ReadUDPRequest(payload.Bytes()) payload.Release() if err != nil { log.Error("Socks: Failed to parse UDP request: ", err) return } if request.Data.Len() == 0 { request.Data.Release() return } if request.Fragment != 0 { log.Warning("Socks: Dropping fragmented UDP packets.") // TODO handle fragments request.Data.Release() return } log.Info("Socks: Send packet to ", request.Destination(), " with ", request.Data.Len(), " bytes") log.Access(source, request.Destination, log.AccessAccepted, "") v.udpServer.Dispatch(&proxy.SessionInfo{Source: source, Destination: request.Destination(), Inbound: v.meta}, request.Data, func(destination v2net.Destination, payload *buf.Buffer) { response := &protocol.Socks5UDPRequest{ Fragment: 0, Address: request.Destination().Address, Port: request.Destination().Port, Data: payload, } log.Info("Socks: Writing back UDP response with ", payload.Len(), " bytes to ", destination) udpMessage := buf.NewLocal(2048) response.Write(udpMessage) v.udpMutex.RLock() if !v.accepting { v.udpMutex.RUnlock() return } nBytes, err := v.udpHub.WriteTo(udpMessage.Bytes(), destination) v.udpMutex.RUnlock() udpMessage.Release() response.Data.Release() if err != nil { log.Error("Socks: failed to write UDP message (", nBytes, " bytes) to ", destination, ": ", err) } }) }
func TestReaderWriter(t *testing.T) { assert := assert.On(t) cache := buf.New() b := buf.NewLocal(256) b.AppendSupplier(serial.WriteString("abcd" + ENDING)) writer := NewHeaderWriter(b) err := writer.Write(cache) assert.Error(err).IsNil() assert.Int(cache.Len()).Equals(8) _, err = cache.Write([]byte{'e', 'f', 'g'}) assert.Error(err).IsNil() reader := &HeaderReader{} buffer, err := reader.Read(cache) assert.Error(err).IsNil() assert.Bytes(buffer.Bytes()).Equals([]byte{'e', 'f', 'g'}) }
func TestSinglePacket(t *testing.T) { assert := assert.On(t) tcpServer := &tcp.Server{ MsgProcessor: func(data []byte) []byte { buffer := make([]byte, 0, 2048) buffer = append(buffer, []byte("Processed: ")...) buffer = append(buffer, data...) return buffer }, } _, err := tcpServer.Start() assert.Error(err).IsNil() space := app.NewSpace() freedom := NewFreedomConnection( &Config{}, space, &proxy.OutboundHandlerMeta{ Address: v2net.AnyIP, StreamSettings: &internet.StreamConfig{ Network: v2net.Network_RawTCP, }, }) space.Initialize() traffic := ray.NewRay() data2Send := "Data to be sent to remote" payload := buf.NewLocal(2048) payload.Append([]byte(data2Send)) go freedom.Dispatch(v2net.TCPDestination(v2net.LocalHostIP, tcpServer.Port), payload, traffic) traffic.InboundInput().Close() respPayload, err := traffic.InboundOutput().Read() assert.Error(err).IsNil() assert.String(respPayload.String()).Equals("Processed: Data to be sent to remote") tcpServer.Close() }
func TestBufferedWriterLargePayload(t *testing.T) { assert := assert.On(t) content := buf.NewLocal(128 * 1024) writer := NewWriter(content) assert.Bool(writer.IsBuffered()).IsTrue() payload := make([]byte, 64*1024) rand.Read(payload) nBytes, err := writer.Write(payload[:512]) assert.Int(nBytes).Equals(512) assert.Error(err).IsNil() assert.Bool(content.IsEmpty()).IsTrue() nBytes, err = writer.Write(payload[512:]) assert.Error(err).IsNil() assert.Int(nBytes).Equals(64*1024 - 512) assert.Bytes(content.Bytes()).Equals(payload) }
func TestTCPRequest(t *testing.T) { assert := assert.On(t) request := &protocol.RequestHeader{ Version: Version, Command: protocol.RequestCommandTCP, Address: v2net.LocalHostIP, Option: RequestOptionOneTimeAuth, Port: 1234, User: &protocol.User{ Email: "*****@*****.**", Account: serial.ToTypedMessage(&Account{ Password: "******", CipherType: CipherType_CHACHA20, }), }, } data := buf.NewLocal(256) data.AppendSupplier(serial.WriteString("test string")) cache := buf.New() writer, err := WriteTCPRequest(request, cache) assert.Error(err).IsNil() writer.Write(data) decodedRequest, reader, err := ReadTCPSession(request.User, cache) assert.Error(err).IsNil() assert.Address(decodedRequest.Address).Equals(request.Address) assert.Port(decodedRequest.Port).Equals(request.Port) decodedData, err := reader.Read() assert.Error(err).IsNil() assert.String(decodedData.String()).Equals("test string") }
func ReadTCPSession(user *protocol.User, reader io.Reader) (*protocol.RequestHeader, buf.Reader, error) { rawAccount, err := user.GetTypedAccount() if err != nil { return nil, nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to parse account.") } account := rawAccount.(*ShadowsocksAccount) buffer := buf.NewLocal(512) defer buffer.Release() ivLen := account.Cipher.IVSize() err = buffer.AppendSupplier(buf.ReadFullFrom(reader, ivLen)) if err != nil { return nil, nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to read IV.") } iv := append([]byte(nil), buffer.BytesTo(ivLen)...) stream, err := account.Cipher.NewDecodingStream(account.Key, iv) if err != nil { return nil, nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to initialize decoding stream.") } reader = crypto.NewCryptionReader(stream, reader) authenticator := NewAuthenticator(HeaderKeyGenerator(account.Key, iv)) request := &protocol.RequestHeader{ Version: Version, User: user, Command: protocol.RequestCommandTCP, } buffer.Clear() err = buffer.AppendSupplier(buf.ReadFullFrom(reader, 1)) if err != nil { return nil, nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to read address type.") } addrType := (buffer.Byte(0) & 0x0F) if (buffer.Byte(0) & 0x10) == 0x10 { request.Option |= RequestOptionOneTimeAuth } if request.Option.Has(RequestOptionOneTimeAuth) && account.OneTimeAuth == Account_Disabled { return nil, nil, errors.New("Shadowsocks|TCP: Rejecting connection with OTA enabled, while server disables OTA.") } if !request.Option.Has(RequestOptionOneTimeAuth) && account.OneTimeAuth == Account_Enabled { return nil, nil, errors.New("Shadowsocks|TCP: Rejecting connection with OTA disabled, while server enables OTA.") } switch addrType { case AddrTypeIPv4: err := buffer.AppendSupplier(buf.ReadFullFrom(reader, 4)) if err != nil { return nil, nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to read IPv4 address.") } request.Address = v2net.IPAddress(buffer.BytesFrom(-4)) case AddrTypeIPv6: err := buffer.AppendSupplier(buf.ReadFullFrom(reader, 16)) if err != nil { return nil, nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to read IPv6 address.") } request.Address = v2net.IPAddress(buffer.BytesFrom(-16)) case AddrTypeDomain: err := buffer.AppendSupplier(buf.ReadFullFrom(reader, 1)) if err != nil { return nil, nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to read domain lenth.") } domainLength := int(buffer.BytesFrom(-1)[0]) err = buffer.AppendSupplier(buf.ReadFullFrom(reader, domainLength)) if err != nil { return nil, nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to read domain.") } request.Address = v2net.DomainAddress(string(buffer.BytesFrom(-domainLength))) default: // Check address validity after OTA verification. } err = buffer.AppendSupplier(buf.ReadFullFrom(reader, 2)) if err != nil { return nil, nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to read port.") } request.Port = v2net.PortFromBytes(buffer.BytesFrom(-2)) if request.Option.Has(RequestOptionOneTimeAuth) { actualAuth := make([]byte, AuthSize) authenticator.Authenticate(buffer.Bytes())(actualAuth) err := buffer.AppendSupplier(buf.ReadFullFrom(reader, AuthSize)) if err != nil { return nil, nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to read OTA.") } if !bytes.Equal(actualAuth, buffer.BytesFrom(-AuthSize)) { return nil, nil, errors.New("Shadowsocks|TCP: Invalid OTA") } } if request.Address == nil { return nil, nil, errors.New("Shadowsocks|TCP: Invalid remote address.") } var chunkReader buf.Reader if request.Option.Has(RequestOptionOneTimeAuth) { chunkReader = NewChunkReader(reader, NewAuthenticator(ChunkKeyGenerator(iv))) } else { chunkReader = buf.NewReader(reader) } return request, chunkReader, nil }
func WriteTCPRequest(request *protocol.RequestHeader, writer io.Writer) (buf.Writer, error) { user := request.User rawAccount, err := user.GetTypedAccount() if err != nil { return nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to parse account.") } account := rawAccount.(*ShadowsocksAccount) iv := make([]byte, account.Cipher.IVSize()) rand.Read(iv) _, err = writer.Write(iv) if err != nil { return nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to write IV.") } stream, err := account.Cipher.NewEncodingStream(account.Key, iv) if err != nil { return nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to create encoding stream.") } writer = crypto.NewCryptionWriter(stream, writer) header := buf.NewLocal(512) switch request.Address.Family() { case v2net.AddressFamilyIPv4: header.AppendBytes(AddrTypeIPv4) header.Append([]byte(request.Address.IP())) case v2net.AddressFamilyIPv6: header.AppendBytes(AddrTypeIPv6) header.Append([]byte(request.Address.IP())) case v2net.AddressFamilyDomain: header.AppendBytes(AddrTypeDomain, byte(len(request.Address.Domain()))) header.Append([]byte(request.Address.Domain())) default: return nil, errors.New("Shadowsocks|TCP: Unsupported address type: ", request.Address.Family()) } header.AppendSupplier(serial.WriteUint16(uint16(request.Port))) if request.Option.Has(RequestOptionOneTimeAuth) { header.SetByte(0, header.Byte(0)|0x10) authenticator := NewAuthenticator(HeaderKeyGenerator(account.Key, iv)) header.AppendSupplier(authenticator.Authenticate(header.Bytes())) } _, err = writer.Write(header.Bytes()) if err != nil { return nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to write header.") } var chunkWriter buf.Writer if request.Option.Has(RequestOptionOneTimeAuth) { chunkWriter = NewChunkWriter(writer, NewAuthenticator(ChunkKeyGenerator(iv))) } else { chunkWriter = buf.NewWriter(writer) } return chunkWriter, nil }