예제 #1
0
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
}
예제 #2
0
func (this *VMessInboundHandler) HandleConnection(connection *net.TCPConn) error {
	defer connection.Close()

	connReader := v2net.NewTimeOutReader(16, connection)
	requestReader := protocol.NewVMessRequestReader(this.clients)

	request, err := requestReader.Read(connReader)
	if err != nil {
		log.Access(connection.RemoteAddr().String(), "", log.AccessRejected, err.Error())
		log.Warning("VMessIn: Invalid request from (%s): %v", connection.RemoteAddr().String(), err)
		return err
	}
	log.Access(connection.RemoteAddr().String(), request.Address.String(), log.AccessAccepted, "")
	log.Debug("VMessIn: Received request for %s", request.Address.String())

	ray := this.space.PacketDispatcher().DispatchToOutbound(v2net.NewPacket(request.Destination(), nil, true))
	input := ray.InboundInput()
	output := ray.InboundOutput()
	var readFinish, writeFinish sync.Mutex
	readFinish.Lock()
	writeFinish.Lock()

	userSettings := vmess.GetUserSettings(request.User.Level)
	connReader.SetTimeOut(userSettings.PayloadReadTimeout)
	go handleInput(request, connReader, input, &readFinish)

	responseKey := md5.Sum(request.RequestKey)
	responseIV := md5.Sum(request.RequestIV)

	aesStream, err := v2crypto.NewAesEncryptionStream(responseKey[:], responseIV[:])
	if err != nil {
		log.Error("VMessIn: Failed to create AES decryption stream: %v", err)
		close(input)
		return err
	}

	responseWriter := v2crypto.NewCryptionWriter(aesStream, connection)

	// Optimize for small response packet
	buffer := alloc.NewLargeBuffer().Clear()
	defer buffer.Release()
	buffer.AppendBytes(request.ResponseHeader[0] ^ request.ResponseHeader[1])
	buffer.AppendBytes(request.ResponseHeader[2] ^ request.ResponseHeader[3])
	buffer.AppendBytes(byte(0), byte(0))

	if data, open := <-output; open {
		buffer.Append(data.Value)
		data.Release()
		responseWriter.Write(buffer.Value)
		go handleOutput(request, responseWriter, output, &writeFinish)
		writeFinish.Lock()
	}

	connection.CloseWrite()
	readFinish.Lock()

	return nil
}
예제 #3
0
파일: vmess.go 프로젝트: yorkzhy/v2ray-core
// ToBytes returns a VMessRequest in the form of byte array.
func (this *VMessRequest) ToBytes(timestampGenerator RandomTimestampGenerator, buffer *alloc.Buffer) (*alloc.Buffer, error) {
	if buffer == nil {
		buffer = alloc.NewSmallBuffer().Clear()
	}

	timestamp := timestampGenerator.Next()
	idHash := IDHash(this.User.AnyValidID().Bytes())
	idHash.Write(timestamp.Bytes())

	hashStart := buffer.Len()
	buffer.Slice(0, hashStart+16)
	idHash.Sum(buffer.Value[hashStart:hashStart])

	encryptionBegin := buffer.Len()

	buffer.AppendBytes(this.Version)
	buffer.Append(this.RequestIV)
	buffer.Append(this.RequestKey)
	buffer.AppendBytes(this.ResponseHeader, this.Option, byte(0), byte(0))
	buffer.AppendBytes(this.Command)
	buffer.Append(this.Port.Bytes())

	switch {
	case this.Address.IsIPv4():
		buffer.AppendBytes(addrTypeIPv4)
		buffer.Append(this.Address.IP())
	case this.Address.IsIPv6():
		buffer.AppendBytes(addrTypeIPv6)
		buffer.Append(this.Address.IP())
	case this.Address.IsDomain():
		buffer.AppendBytes(addrTypeDomain, byte(len(this.Address.Domain())))
		buffer.Append([]byte(this.Address.Domain()))
	}

	encryptionEnd := buffer.Len()

	fnv1a := fnv.New32a()
	fnv1a.Write(buffer.Value[encryptionBegin:encryptionEnd])

	fnvHash := fnv1a.Sum32()
	buffer.AppendBytes(byte(fnvHash>>24), byte(fnvHash>>16), byte(fnvHash>>8), byte(fnvHash))
	encryptionEnd += 4

	timestampHash := md5.New()
	timestampHash.Write(timestamp.HashBytes())
	iv := timestampHash.Sum(nil)
	aesStream, err := v2crypto.NewAesEncryptionStream(this.User.ID.CmdKey(), iv)
	if err != nil {
		return nil, err
	}
	aesStream.XORKeyStream(buffer.Value[encryptionBegin:encryptionEnd], buffer.Value[encryptionBegin:encryptionEnd])

	return buffer, nil
}
예제 #4
0
func (this *VMessOutboundHandler) handleRequest(conn net.Conn, request *protocol.VMessRequest, firstPacket v2net.Packet, input <-chan *alloc.Buffer, finish *sync.Mutex) {
	defer finish.Unlock()
	aesStream, err := v2crypto.NewAesEncryptionStream(request.RequestKey[:], request.RequestIV[:])
	if err != nil {
		log.Error("VMessOut: Failed to create AES encryption stream: ", err)
		return
	}
	encryptRequestWriter := v2crypto.NewCryptionWriter(aesStream, conn)

	buffer := alloc.NewBuffer().Clear()
	defer buffer.Release()
	buffer, err = request.ToBytes(protocol.NewRandomTimestampGenerator(protocol.Timestamp(time.Now().Unix()), 30), buffer)
	if err != nil {
		log.Error("VMessOut: Failed to serialize VMess request: ", err)
		return
	}

	// Send first packet of payload together with request, in favor of small requests.
	firstChunk := firstPacket.Chunk()
	moreChunks := firstPacket.MoreChunks()

	for firstChunk == nil && moreChunks {
		firstChunk, moreChunks = <-input
	}

	if firstChunk == nil && !moreChunks {
		log.Warning("VMessOut: Nothing to send. Existing...")
		return
	}

	if request.IsChunkStream() {
		vmessio.Authenticate(firstChunk)
	}

	aesStream.XORKeyStream(firstChunk.Value, firstChunk.Value)
	buffer.Append(firstChunk.Value)
	firstChunk.Release()

	_, err = conn.Write(buffer.Value)
	if err != nil {
		log.Error("VMessOut: Failed to write VMess request: ", err)
		return
	}

	if moreChunks {
		var streamWriter v2io.Writer
		streamWriter = v2io.NewAdaptiveWriter(encryptRequestWriter)
		if request.IsChunkStream() {
			streamWriter = vmessio.NewAuthChunkWriter(streamWriter)
		}
		v2io.ChanToWriter(streamWriter, input)
	}
	return
}
예제 #5
0
// ToBytes returns a VMessRequest in the form of byte array.
func (this *VMessRequest) ToBytes(idHash user.CounterHash, randomRangeInt64 user.RandomInt64InRange, buffer *alloc.Buffer) (*alloc.Buffer, error) {
	if buffer == nil {
		buffer = alloc.NewSmallBuffer().Clear()
	}

	counter := randomRangeInt64(time.Now().Unix(), 30)
	hash := idHash.Hash(this.User.ID().Bytes[:], counter)

	buffer.Append(hash)

	encryptionBegin := buffer.Len()

	buffer.AppendBytes(this.Version)
	buffer.Append(this.RequestIV)
	buffer.Append(this.RequestKey)
	buffer.Append(this.ResponseHeader)
	buffer.AppendBytes(this.Command)
	buffer.Append(this.Address.PortBytes())

	switch {
	case this.Address.IsIPv4():
		buffer.AppendBytes(addrTypeIPv4)
		buffer.Append(this.Address.IP())
	case this.Address.IsIPv6():
		buffer.AppendBytes(addrTypeIPv6)
		buffer.Append(this.Address.IP())
	case this.Address.IsDomain():
		buffer.AppendBytes(addrTypeDomain, byte(len(this.Address.Domain())))
		buffer.Append([]byte(this.Address.Domain()))
	}

	encryptionEnd := buffer.Len()

	fnv1a := fnv.New32a()
	fnv1a.Write(buffer.Value[encryptionBegin:encryptionEnd])

	fnvHash := fnv1a.Sum32()
	buffer.AppendBytes(byte(fnvHash>>24), byte(fnvHash>>16), byte(fnvHash>>8), byte(fnvHash))
	encryptionEnd += 4

	aesStream, err := v2crypto.NewAesEncryptionStream(this.User.ID().CmdKey(), user.Int64Hash(counter))
	if err != nil {
		return nil, err
	}
	aesStream.XORKeyStream(buffer.Value[encryptionBegin:encryptionEnd], buffer.Value[encryptionBegin:encryptionEnd])

	return buffer, nil
}
예제 #6
0
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, 0x00})
	err := MarshalCommand(header.Command, encryptionWriter)
	if err != nil {
		encryptionWriter.Write([]byte{0x00, 0x00})
	}
}
예제 #7
0
func handleRequest(conn net.Conn, request *protocol.VMessRequest, firstPacket v2net.Packet, input <-chan *alloc.Buffer, finish *sync.Mutex) {
	defer finish.Unlock()
	aesStream, err := v2crypto.NewAesEncryptionStream(request.RequestKey[:], request.RequestIV[:])
	if err != nil {
		log.Error("VMessOut: Failed to create AES encryption stream: %v", err)
		return
	}
	encryptRequestWriter := v2crypto.NewCryptionWriter(aesStream, conn)

	buffer := alloc.NewBuffer().Clear()
	defer buffer.Release()
	buffer, err = request.ToBytes(user.NewTimeHash(user.HMACHash{}), user.GenerateRandomInt64InRange, buffer)
	if err != nil {
		log.Error("VMessOut: Failed to serialize VMess request: %v", err)
		return
	}

	// Send first packet of payload together with request, in favor of small requests.
	firstChunk := firstPacket.Chunk()
	moreChunks := firstPacket.MoreChunks()

	for firstChunk == nil && moreChunks {
		firstChunk, moreChunks = <-input
	}

	if firstChunk == nil && !moreChunks {
		log.Warning("VMessOut: Nothing to send. Existing...")
		return
	}

	aesStream.XORKeyStream(firstChunk.Value, firstChunk.Value)
	buffer.Append(firstChunk.Value)
	firstChunk.Release()

	_, err = conn.Write(buffer.Value)
	if err != nil {
		log.Error("VMessOut: Failed to write VMess request: %v", err)
		return
	}

	if moreChunks {
		v2net.ChanToWriter(encryptRequestWriter, input)
	}
	return
}
예제 #8
0
func (this *ClientSession) EncodeRequestHeader(header *protocol.RequestHeader, writer io.Writer) {
	timestamp := protocol.NewTimestampGenerator(protocol.NowTime(), 30)()
	idHash := this.idHash(header.User.AnyValidID().Bytes())
	idHash.Write(timestamp.Bytes())
	writer.Write(idHash.Sum(nil))

	buffer := alloc.NewSmallBuffer().Clear()
	defer buffer.Release()

	buffer.AppendBytes(Version)
	buffer.Append(this.requestBodyIV)
	buffer.Append(this.requestBodyKey)
	buffer.AppendBytes(this.responseHeader, byte(header.Option), byte(0), byte(0))
	buffer.AppendBytes(byte(header.Command))
	buffer.Append(header.Port.Bytes())

	switch {
	case header.Address.IsIPv4():
		buffer.AppendBytes(AddrTypeIPv4)
		buffer.Append(header.Address.IP())
	case header.Address.IsIPv6():
		buffer.AppendBytes(AddrTypeIPv6)
		buffer.Append(header.Address.IP())
	case header.Address.IsDomain():
		buffer.AppendBytes(AddrTypeDomain, byte(len(header.Address.Domain())))
		buffer.Append([]byte(header.Address.Domain()))
	}

	fnv1a := fnv.New32a()
	fnv1a.Write(buffer.Value)

	fnvHash := fnv1a.Sum32()
	buffer.AppendBytes(byte(fnvHash>>24), byte(fnvHash>>16), byte(fnvHash>>8), byte(fnvHash))

	timestampHash := md5.New()
	timestampHash.Write(hashTimestamp(timestamp))
	iv := timestampHash.Sum(nil)
	aesStream := crypto.NewAesEncryptionStream(header.User.ID.CmdKey(), iv)
	aesStream.XORKeyStream(buffer.Value, buffer.Value)
	writer.Write(buffer.Value)

	return
}
예제 #9
0
func (this *ClientSession) EncodeRequestHeader(header *protocol.RequestHeader, writer io.Writer) {
	timestamp := protocol.NewTimestampGenerator(protocol.NowTime(), 30)()
	idHash := this.idHash(header.User.Account.(*protocol.VMessAccount).AnyValidID().Bytes())
	idHash.Write(timestamp.Bytes(nil))
	writer.Write(idHash.Sum(nil))

	buffer := make([]byte, 0, 512)
	buffer = append(buffer, Version)
	buffer = append(buffer, this.requestBodyIV...)
	buffer = append(buffer, this.requestBodyKey...)
	buffer = append(buffer, this.responseHeader, byte(header.Option), byte(0), byte(0), byte(header.Command))
	buffer = header.Port.Bytes(buffer)

	switch {
	case header.Address.IsIPv4():
		buffer = append(buffer, AddrTypeIPv4)
		buffer = append(buffer, header.Address.IP()...)
	case header.Address.IsIPv6():
		buffer = append(buffer, AddrTypeIPv6)
		buffer = append(buffer, header.Address.IP()...)
	case header.Address.IsDomain():
		buffer = append(buffer, AddrTypeDomain, byte(len(header.Address.Domain())))
		buffer = append(buffer, header.Address.Domain()...)
	}

	fnv1a := fnv.New32a()
	fnv1a.Write(buffer)

	buffer = fnv1a.Sum(buffer)

	timestampHash := md5.New()
	timestampHash.Write(hashTimestamp(timestamp))
	iv := timestampHash.Sum(nil)
	account := header.User.Account.(*protocol.VMessAccount)
	aesStream := crypto.NewAesEncryptionStream(account.ID.CmdKey(), iv)
	aesStream.XORKeyStream(buffer, buffer)
	writer.Write(buffer)

	return
}
예제 #10
0
func (this *ClientSession) EncodeRequestBody(writer io.Writer) io.Writer {
	aesStream := crypto.NewAesEncryptionStream(this.requestBodyKey, this.requestBodyIV)
	return crypto.NewCryptionWriter(aesStream, writer)
}
예제 #11
0
func (this *VMessInboundHandler) HandleConnection(connection *hub.TCPConn) {
	defer connection.Close()

	connReader := v2net.NewTimeOutReader(16, connection)
	requestReader := protocol.NewVMessRequestReader(this.clients)

	request, err := requestReader.Read(connReader)
	if err != nil {
		log.Access(connection.RemoteAddr(), serial.StringLiteral(""), log.AccessRejected, serial.StringLiteral(err.Error()))
		log.Warning("VMessIn: Invalid request from ", connection.RemoteAddr(), ": ", err)
		return
	}
	log.Access(connection.RemoteAddr(), request.Address, log.AccessAccepted, serial.StringLiteral(""))
	log.Debug("VMessIn: Received request for ", request.Address)

	ray := this.packetDispatcher.DispatchToOutbound(v2net.NewPacket(request.Destination(), nil, true))
	input := ray.InboundInput()
	output := ray.InboundOutput()
	var readFinish, writeFinish sync.Mutex
	readFinish.Lock()
	writeFinish.Lock()

	userSettings := vmess.GetUserSettings(request.User.Level)
	connReader.SetTimeOut(userSettings.PayloadReadTimeout)
	go handleInput(request, connReader, input, &readFinish)

	responseKey := md5.Sum(request.RequestKey)
	responseIV := md5.Sum(request.RequestIV)

	aesStream, err := v2crypto.NewAesEncryptionStream(responseKey[:], responseIV[:])
	if err != nil {
		log.Error("VMessIn: Failed to create AES decryption stream: ", err)
		close(input)
		return
	}

	responseWriter := v2crypto.NewCryptionWriter(aesStream, connection)

	// Optimize for small response packet
	buffer := alloc.NewLargeBuffer().Clear()
	defer buffer.Release()
	buffer.AppendBytes(request.ResponseHeader, byte(0))
	this.generateCommand(buffer)

	if data, open := <-output; open {
		if request.IsChunkStream() {
			vmessio.Authenticate(data)
		}
		buffer.Append(data.Value)
		data.Release()
		responseWriter.Write(buffer.Value)
		go func(finish *sync.Mutex) {
			var writer v2io.Writer
			writer = v2io.NewAdaptiveWriter(responseWriter)
			if request.IsChunkStream() {
				writer = vmessio.NewAuthChunkWriter(writer)
			}
			v2io.ChanToWriter(writer, output)
			finish.Unlock()
		}(&writeFinish)
		writeFinish.Lock()
	}

	connection.CloseWrite()
	readFinish.Lock()
}
예제 #12
0
func (this *AesCfb) NewEncodingStream(key []byte, iv []byte) (cipher.Stream, error) {
	stream := crypto.NewAesEncryptionStream(key, iv)
	return stream, nil
}