func (request *Socks5UDPRequest) Write(buffer *alloc.Buffer) { buffer.AppendBytes(0, 0, request.Fragment) switch { case request.Address.IsIPv4(): buffer.AppendBytes(AddrTypeIPv4).Append(request.Address.IP()) case request.Address.IsIPv6(): buffer.AppendBytes(AddrTypeIPv6).Append(request.Address.IP()) case request.Address.IsDomain(): buffer.AppendBytes(AddrTypeDomain, byte(len(request.Address.Domain()))).Append([]byte(request.Address.Domain())) } buffer.Append(request.Port.Bytes()) buffer.Append(request.Data.Value) }
func (this *VMessInboundHandler) generateCommand(buffer *alloc.Buffer) { cmd := byte(0) commandBytes := alloc.NewSmallBuffer().Clear() defer commandBytes.Release() if this.features != nil && this.features.Detour != nil { tag := this.features.Detour.ToTag if this.space.HasInboundHandlerManager() { handlerManager := this.space.InboundHandlerManager() handler, availableMin := handlerManager.GetHandler(tag) inboundHandler, ok := handler.(*VMessInboundHandler) if ok { if availableMin > 255 { availableMin = 255 } cmd = byte(1) log.Info("VMessIn: Pick detour handler for port ", inboundHandler.Port(), " for ", availableMin, " minutes.") user := inboundHandler.GetUser() saCmd := &command.SwitchAccount{ Port: inboundHandler.Port(), ID: user.ID.UUID(), AlterIds: serial.Uint16Literal(len(user.AlterIDs)), Level: user.Level, ValidMin: byte(availableMin), } saCmd.Marshal(commandBytes) } } } if cmd == 0 || commandBytes.Len()+4 > 256 { buffer.AppendBytes(byte(0), byte(0)) } else { buffer.AppendBytes(cmd, byte(commandBytes.Len()+4)) fnv1hash := fnv.New32a() fnv1hash.Write(commandBytes.Value) hashValue := fnv1hash.Sum32() buffer.AppendBytes(byte(hashValue>>24), byte(hashValue>>16), byte(hashValue>>8), byte(hashValue)) buffer.Append(commandBytes.Value) } }
func (r *Socks5Response) Write(buffer *alloc.Buffer) { buffer.AppendBytes(r.Version, r.Error, 0x00 /* reserved */, r.AddrType) switch r.AddrType { case 0x01: buffer.Append(r.IPv4[:]) case 0x03: buffer.AppendBytes(byte(len(r.Domain))) buffer.Append([]byte(r.Domain)) case 0x04: buffer.Append(r.IPv6[:]) } buffer.Append(r.Port.Bytes()) }
func (this *VMessInboundHandler) generateCommand(buffer *alloc.Buffer) { cmd := byte(0) commandBytes := alloc.NewSmallBuffer().Clear() defer commandBytes.Release() if this.features != nil && this.features.Detour != nil { tag := this.features.Detour.ToTag if this.space.HasInboundHandlerManager() { handlerManager := this.space.InboundHandlerManager() handler, availableSec := handlerManager.GetHandler(tag) inboundHandler, ok := handler.(*VMessInboundHandler) if ok { user := inboundHandler.GetUser() availableMin := availableSec / 60 if availableMin > 255 { availableMin = 255 } saCmd := &command.SwitchAccount{ Port: inboundHandler.Port(), ID: user.ID.UUID(), AlterIds: serial.Uint16Literal(len(user.AlterIDs)), Level: user.Level, ValidMin: byte(availableMin), } saCmd.Marshal(commandBytes) } } } if commandBytes.Len() > 256 { buffer.AppendBytes(byte(0), byte(0)) } else { buffer.AppendBytes(cmd, byte(commandBytes.Len())) buffer.Append(commandBytes.Value) } }
// 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 }
// ToBytes returns a VMessRequest in the form of byte array. func (request *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().UTC().Unix(), 30) hash := idHash.Hash(request.UserId.Bytes[:], counter) buffer.Append(hash) encryptionBegin := buffer.Len() buffer.AppendBytes(request.Version) buffer.Append(request.RequestIV) buffer.Append(request.RequestKey) buffer.Append(request.ResponseHeader) buffer.AppendBytes(request.Command) buffer.Append(request.Address.PortBytes()) switch { case request.Address.IsIPv4(): buffer.AppendBytes(addrTypeIPv4) buffer.Append(request.Address.IP()) case request.Address.IsIPv6(): buffer.AppendBytes(addrTypeIPv6) buffer.Append(request.Address.IP()) case request.Address.IsDomain(): buffer.AppendBytes(addrTypeDomain, byte(len(request.Address.Domain()))) buffer.Append([]byte(request.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 aesCipher, err := aes.NewCipher(request.UserId.CmdKey()) if err != nil { return nil, err } aesStream := cipher.NewCFBEncrypter(aesCipher, user.Int64Hash(counter)) aesStream.XORKeyStream(buffer.Value[encryptionBegin:encryptionEnd], buffer.Value[encryptionBegin:encryptionEnd]) return buffer, nil }