func (v *ClientSession) EncodeRequestBody(request *protocol.RequestHeader, writer io.Writer) buf.Writer { var authWriter io.Writer if request.Security.Is(protocol.SecurityType_NONE) { if request.Option.Has(protocol.RequestOptionChunkStream) { auth := &crypto.AEADAuthenticator{ AEAD: new(FnvAuthenticator), NonceGenerator: crypto.NoOpBytesGenerator{}, AdditionalDataGenerator: crypto.NoOpBytesGenerator{}, } authWriter = crypto.NewAuthenticationWriter(auth, writer) } else { authWriter = writer } } else if request.Security.Is(protocol.SecurityType_LEGACY) { aesStream := crypto.NewAesEncryptionStream(v.requestBodyKey, v.requestBodyIV) cryptionWriter := crypto.NewCryptionWriter(aesStream, writer) if request.Option.Has(protocol.RequestOptionChunkStream) { auth := &crypto.AEADAuthenticator{ AEAD: new(FnvAuthenticator), NonceGenerator: crypto.NoOpBytesGenerator{}, AdditionalDataGenerator: crypto.NoOpBytesGenerator{}, } authWriter = crypto.NewAuthenticationWriter(auth, cryptionWriter) } else { authWriter = cryptionWriter } } else if request.Security.Is(protocol.SecurityType_AES128_GCM) { block, _ := aes.NewCipher(v.requestBodyKey) aead, _ := cipher.NewGCM(block) auth := &crypto.AEADAuthenticator{ AEAD: aead, NonceGenerator: &ChunkNonceGenerator{ Nonce: append([]byte(nil), v.requestBodyIV...), Size: aead.NonceSize(), }, AdditionalDataGenerator: crypto.NoOpBytesGenerator{}, } authWriter = crypto.NewAuthenticationWriter(auth, writer) } else if request.Security.Is(protocol.SecurityType_CHACHA20_POLY1305) { aead, _ := chacha20poly1305.New(GenerateChacha20Poly1305Key(v.requestBodyKey)) auth := &crypto.AEADAuthenticator{ AEAD: aead, NonceGenerator: &ChunkNonceGenerator{ Nonce: append([]byte(nil), v.requestBodyIV...), Size: aead.NonceSize(), }, AdditionalDataGenerator: crypto.NoOpBytesGenerator{}, } authWriter = crypto.NewAuthenticationWriter(auth, writer) } return buf.NewWriter(authWriter) }
func (this *ServerSession) EncodeResponseHeader(header *protocol.ResponseHeader, writer io.Writer) { responseBodyKey := md5.Sum(this.requestBodyKey) responseBodyIV := md5.Sum(this.requestBodyIV) this.responseBodyKey = responseBodyKey[:] this.responseBodyIV = responseBodyIV[:] aesStream := crypto.NewAesEncryptionStream(this.responseBodyKey, this.responseBodyIV) encryptionWriter := crypto.NewCryptionWriter(aesStream, writer) this.responseWriter = encryptionWriter encryptionWriter.Write([]byte{this.responseHeader, byte(header.Option)}) err := MarshalCommand(header.Command, encryptionWriter) if err != nil { encryptionWriter.Write([]byte{0x00, 0x00}) } }
func WriteTCPResponse(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.") } return buf.NewWriter(crypto.NewCryptionWriter(stream, writer)), 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 }
func (this *ClientSession) EncodeRequestBody(writer io.Writer) io.Writer { aesStream := crypto.NewAesEncryptionStream(this.requestBodyKey, this.requestBodyIV) return crypto.NewCryptionWriter(aesStream, writer) }
func (this *Server) handlerUDPPayload(payload *alloc.Buffer, session *proxy.SessionInfo) { defer payload.Release() source := session.Source ivLen := this.config.Cipher.IVSize() iv := payload.Value[:ivLen] key := this.config.Key payload.SliceFrom(ivLen) stream, err := this.config.Cipher.NewDecodingStream(key, iv) if err != nil { log.Error("Shadowsocks: Failed to create decoding stream: ", err) return } reader := crypto.NewCryptionReader(stream, payload) request, err := ReadRequest(reader, NewAuthenticator(HeaderKeyGenerator(key, iv)), true) if err != nil { if err != io.EOF { log.Access(source, "", log.AccessRejected, err) log.Warning("Shadowsocks: Invalid request from ", source, ": ", err) } return } //defer request.Release() dest := v2net.UDPDestination(request.Address, request.Port) log.Access(source, dest, log.AccessAccepted, "") log.Info("Shadowsocks: Tunnelling request to ", dest) this.udpServer.Dispatch(&proxy.SessionInfo{Source: source, Destination: dest}, request.DetachUDPPayload(), func(destination v2net.Destination, payload *alloc.Buffer) { defer payload.Release() response := alloc.NewBuffer().Slice(0, ivLen) defer response.Release() rand.Read(response.Value) respIv := response.Value stream, err := this.config.Cipher.NewEncodingStream(key, respIv) if err != nil { log.Error("Shadowsocks: Failed to create encoding stream: ", err) return } writer := crypto.NewCryptionWriter(stream, response) switch request.Address.Family() { case v2net.AddressFamilyIPv4: writer.Write([]byte{AddrTypeIPv4}) writer.Write(request.Address.IP()) case v2net.AddressFamilyIPv6: writer.Write([]byte{AddrTypeIPv6}) writer.Write(request.Address.IP()) case v2net.AddressFamilyDomain: writer.Write([]byte{AddrTypeDomain, byte(len(request.Address.Domain()))}) writer.Write([]byte(request.Address.Domain())) } writer.Write(request.Port.Bytes(nil)) writer.Write(payload.Value) if request.OTA { respAuth := NewAuthenticator(HeaderKeyGenerator(key, respIv)) respAuth.Authenticate(response.Value, response.Value[ivLen:]) } this.udpHub.WriteTo(response.Value, source) }) }
func (this *Server) handleConnection(conn internet.Connection) { defer conn.Close() buffer := alloc.NewSmallBuffer() defer buffer.Release() timedReader := v2net.NewTimeOutReader(16, conn) defer timedReader.Release() bufferedReader := v2io.NewBufferedReader(timedReader) defer bufferedReader.Release() ivLen := this.config.Cipher.IVSize() _, err := io.ReadFull(bufferedReader, buffer.Value[:ivLen]) if err != nil { if err != io.EOF { log.Access(conn.RemoteAddr(), "", log.AccessRejected, err) log.Warning("Shadowsocks: Failed to read IV: ", err) } return } iv := buffer.Value[:ivLen] key := this.config.Key stream, err := this.config.Cipher.NewDecodingStream(key, iv) if err != nil { log.Error("Shadowsocks: Failed to create decoding stream: ", err) return } reader := crypto.NewCryptionReader(stream, bufferedReader) request, err := ReadRequest(reader, NewAuthenticator(HeaderKeyGenerator(key, iv)), false) if err != nil { log.Access(conn.RemoteAddr(), "", log.AccessRejected, err) log.Warning("Shadowsocks: Invalid request from ", conn.RemoteAddr(), ": ", err) return } defer request.Release() bufferedReader.SetCached(false) userSettings := protocol.GetUserSettings(this.config.Level) timedReader.SetTimeOut(userSettings.PayloadReadTimeout) dest := v2net.TCPDestination(request.Address, request.Port) log.Access(conn.RemoteAddr(), dest, log.AccessAccepted, "") log.Info("Shadowsocks: Tunnelling request to ", dest) ray := this.packetDispatcher.DispatchToOutbound(this.meta, &proxy.SessionInfo{ Source: v2net.DestinationFromAddr(conn.RemoteAddr()), Destination: dest, }) defer ray.InboundOutput().Release() var writeFinish sync.Mutex writeFinish.Lock() go func() { if payload, err := ray.InboundOutput().Read(); err == nil { payload.SliceBack(ivLen) rand.Read(payload.Value[:ivLen]) stream, err := this.config.Cipher.NewEncodingStream(key, payload.Value[:ivLen]) if err != nil { log.Error("Shadowsocks: Failed to create encoding stream: ", err) return } stream.XORKeyStream(payload.Value[ivLen:], payload.Value[ivLen:]) conn.Write(payload.Value) payload.Release() writer := crypto.NewCryptionWriter(stream, conn) v2writer := v2io.NewAdaptiveWriter(writer) v2io.Pipe(ray.InboundOutput(), v2writer) writer.Release() v2writer.Release() } writeFinish.Unlock() }() var payloadReader v2io.Reader if request.OTA { payloadAuth := NewAuthenticator(ChunkKeyGenerator(iv)) payloadReader = NewChunkReader(reader, payloadAuth) } else { payloadReader = v2io.NewAdaptiveReader(reader) } v2io.Pipe(payloadReader, ray.InboundInput()) ray.InboundInput().Close() payloadReader.Release() writeFinish.Lock() }
func WriteTCPRequest(request *protocol.RequestHeader, writer io.Writer) (v2io.Writer, error) { user := request.User rawAccount, err := user.GetTypedAccount() if err != nil { return nil, errors.New("Shadowsocks|TCP: Failed to parse account: " + err.Error()) } account := rawAccount.(*ShadowsocksAccount) iv := make([]byte, account.Cipher.IVSize()) rand.Read(iv) _, err = writer.Write(iv) if err != nil { return nil, errors.New("Shadowsocks|TCP: Failed to write IV: " + err.Error()) } stream, err := account.Cipher.NewEncodingStream(account.Key, iv) if err != nil { return nil, errors.New("Shadowsocks|TCP: Failed to create encoding stream: " + err.Error()) } writer = crypto.NewCryptionWriter(stream, writer) header := alloc.NewLocalBuffer(512).Clear() 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. ") } header.AppendUint16(uint16(request.Port)) if request.Option.Has(RequestOptionOneTimeAuth) { header.Value[0] |= 0x10 authenticator := NewAuthenticator(HeaderKeyGenerator(account.Key, iv)) header.Value = authenticator.Authenticate(header.Value, header.Value) } _, err = writer.Write(header.Value) if err != nil { return nil, errors.New("Shadowsocks|TCP: Failed to write header: " + err.Error()) } var chunkWriter v2io.Writer if request.Option.Has(RequestOptionOneTimeAuth) { chunkWriter = NewChunkWriter(writer, NewAuthenticator(ChunkKeyGenerator(iv))) } else { chunkWriter = v2io.NewAdaptiveWriter(writer) } return chunkWriter, nil }