func ReadVMessUDP(buffer []byte, userset user.UserSet) (*VMessUDP, error) { userHash := buffer[:user.IDBytesLen] userId, timeSec, valid := userset.GetUser(userHash) if !valid { return nil, errors.NewAuthenticationError(userHash) } buffer = buffer[user.IDBytesLen:] aesCipher, err := aes.NewCipher(userId.CmdKey()) if err != nil { return nil, err } aesStream := cipher.NewCFBDecrypter(aesCipher, user.Int64Hash(timeSec)) aesStream.XORKeyStream(buffer, buffer) fnvHash := binary.BigEndian.Uint32(buffer[:4]) fnv1a := fnv.New32a() fnv1a.Write(buffer[4:]) fnvHashActual := fnv1a.Sum32() if fnvHash != fnvHashActual { log.Warning("Unexpected fhv hash %d, should be %d", fnvHashActual, fnvHash) return nil, errors.NewCorruptedPacketError() } buffer = buffer[4:] vmess := &VMessUDP{ user: *userId, version: buffer[0], token: binary.BigEndian.Uint16(buffer[1:3]), } // buffer[3] is reserved port := binary.BigEndian.Uint16(buffer[4:6]) addrType := buffer[6] var address v2net.Address switch addrType { case addrTypeIPv4: address = v2net.IPAddress(buffer[7:11], port) buffer = buffer[11:] case addrTypeIPv6: address = v2net.IPAddress(buffer[7:23], port) buffer = buffer[23:] case addrTypeDomain: domainLength := buffer[7] domain := string(buffer[8 : 8+domainLength]) address = v2net.DomainAddress(domain, port) buffer = buffer[8+domainLength:] default: log.Warning("Unexpected address type %d", addrType) return nil, errors.NewCorruptedPacketError() } vmess.address = address vmess.data = buffer return vmess, nil }
func (server *SocksServer) handleSocks5(reader *v2net.TimeOutReader, writer io.Writer, auth protocol.Socks5AuthenticationRequest) error { expectedAuthMethod := protocol.AuthNotRequired if server.config.IsPassword() { expectedAuthMethod = protocol.AuthUserPass } if !auth.HasAuthMethod(expectedAuthMethod) { authResponse := protocol.NewAuthenticationResponse(protocol.AuthNoMatchingMethod) err := protocol.WriteAuthentication(writer, authResponse) if err != nil { log.Error("Socks failed to write authentication: %v", err) return err } log.Warning("Socks client doesn't support allowed any auth methods.") return errors.NewInvalidOperationError("Unsupported auth methods.") } authResponse := protocol.NewAuthenticationResponse(expectedAuthMethod) err := protocol.WriteAuthentication(writer, authResponse) if err != nil { log.Error("Socks failed to write authentication: %v", err) return err } if server.config.IsPassword() { upRequest, err := protocol.ReadUserPassRequest(reader) if err != nil { log.Error("Socks failed to read username and password: %v", err) return err } status := byte(0) if !upRequest.IsValid(server.config.Username, server.config.Password) { status = byte(0xFF) } upResponse := protocol.NewSocks5UserPassResponse(status) err = protocol.WriteUserPassResponse(writer, upResponse) if err != nil { log.Error("Socks failed to write user pass response: %v", err) return err } if status != byte(0) { err = errors.NewAuthenticationError(upRequest.AuthDetail()) log.Warning(err.Error()) return err } } request, err := protocol.ReadRequest(reader) if err != nil { log.Error("Socks failed to read request: %v", err) return err } response := protocol.NewSocks5Response() if request.Command == protocol.CmdUdpAssociate && server.config.UDPEnabled { return server.handleUDP(reader, writer) } if request.Command == protocol.CmdBind || request.Command == protocol.CmdUdpAssociate { response := protocol.NewSocks5Response() response.Error = protocol.ErrorCommandNotSupported err = protocol.WriteResponse(writer, response) if err != nil { log.Error("Socks failed to write response: %v", err) return err } log.Warning("Unsupported socks command %d", request.Command) return errors.NewInvalidOperationError("Socks command " + strconv.Itoa(int(request.Command))) } response.Error = protocol.ErrorSuccess response.Port = request.Port response.AddrType = request.AddrType switch response.AddrType { case protocol.AddrTypeIPv4: copy(response.IPv4[:], request.IPv4[:]) case protocol.AddrTypeIPv6: copy(response.IPv6[:], request.IPv6[:]) case protocol.AddrTypeDomain: response.Domain = request.Domain } err = protocol.WriteResponse(writer, response) if err != nil { log.Error("Socks failed to write response: %v", err) return err } dest := request.Destination() data, err := v2net.ReadFrom(reader) if err != nil { return err } packet := v2net.NewPacket(dest, data, true) server.transport(reader, writer, packet) return nil }
func (server *SocksServer) handleSocks5(reader *v2net.TimeOutReader, writer io.Writer, auth protocol.Socks5AuthenticationRequest) error { expectedAuthMethod := protocol.AuthNotRequired if server.config.IsPassword() { expectedAuthMethod = protocol.AuthUserPass } if !auth.HasAuthMethod(expectedAuthMethod) { authResponse := protocol.NewAuthenticationResponse(protocol.AuthNoMatchingMethod) err := protocol.WriteAuthentication(writer, authResponse) if err != nil { log.Error("Socks failed to write authentication: %v", err) return err } log.Warning("Socks client doesn't support allowed any auth methods.") return errors.NewInvalidOperationError("Unsupported auth methods.") } authResponse := protocol.NewAuthenticationResponse(expectedAuthMethod) err := protocol.WriteAuthentication(writer, authResponse) if err != nil { log.Error("Socks failed to write authentication: %v", err) return err } if server.config.IsPassword() { upRequest, err := protocol.ReadUserPassRequest(reader) if err != nil { log.Error("Socks failed to read username and password: %v", err) return err } status := byte(0) if !server.config.HasAccount(upRequest.Username(), upRequest.Password()) { status = byte(0xFF) } upResponse := protocol.NewSocks5UserPassResponse(status) err = protocol.WriteUserPassResponse(writer, upResponse) if err != nil { log.Error("Socks failed to write user pass response: %v", err) return err } if status != byte(0) { err = errors.NewAuthenticationError(upRequest.AuthDetail()) log.Warning(err.Error()) return err } } request, err := protocol.ReadRequest(reader) if err != nil { log.Error("Socks failed to read request: %v", err) return err } if request.Command == protocol.CmdUdpAssociate && server.config.UDPEnabled { return server.handleUDP(reader, writer) } response := protocol.NewSocks5Response() if request.Command == protocol.CmdBind || request.Command == protocol.CmdUdpAssociate { response := protocol.NewSocks5Response() response.Error = protocol.ErrorCommandNotSupported responseBuffer := alloc.NewSmallBuffer().Clear() response.Write(responseBuffer) _, err = writer.Write(responseBuffer.Value) responseBuffer.Release() if err != nil { log.Error("Socks failed to write response: %v", err) return err } log.Warning("Unsupported socks command %d", request.Command) return errors.NewInvalidOperationError("Socks command " + strconv.Itoa(int(request.Command))) } response.Error = protocol.ErrorSuccess // Some SOCKS software requires a value other than dest. Let's fake one: response.Port = uint16(1717) response.AddrType = protocol.AddrTypeIPv4 response.IPv4[0] = 0 response.IPv4[1] = 0 response.IPv4[2] = 0 response.IPv4[3] = 0 responseBuffer := alloc.NewSmallBuffer().Clear() response.Write(responseBuffer) _, err = writer.Write(responseBuffer.Value) responseBuffer.Release() if err != nil { log.Error("Socks failed to write response: %v", err) return err } dest := request.Destination() data, err := v2net.ReadFrom(reader, nil) if err != nil { return err } packet := v2net.NewPacket(dest, data, true) server.transport(reader, writer, packet) return nil }
func (server *SocksServer) HandleConnection(connection net.Conn) error { defer connection.Close() reader := v2net.NewTimeOutReader(4, connection) auth, auth4, err := protocol.ReadAuthentication(reader) if err != nil && !errors.HasCode(err, 1000) { log.Error("Socks failed to read authentication: %v", err) return err } var dest v2net.Destination // TODO refactor this part if errors.HasCode(err, 1000) { result := protocol.Socks4RequestGranted if auth4.Command == protocol.CmdBind { result = protocol.Socks4RequestRejected } socks4Response := protocol.NewSocks4AuthenticationResponse(result, auth4.Port, auth4.IP[:]) connection.Write(socks4Response.ToBytes(nil)) if result == protocol.Socks4RequestRejected { return errors.NewInvalidOperationError("Socks4 command " + strconv.Itoa(int(auth4.Command))) } dest = v2net.NewTCPDestination(v2net.IPAddress(auth4.IP[:], auth4.Port)) } else { expectedAuthMethod := protocol.AuthNotRequired if server.config.IsPassword() { expectedAuthMethod = protocol.AuthUserPass } if !auth.HasAuthMethod(expectedAuthMethod) { authResponse := protocol.NewAuthenticationResponse(protocol.AuthNoMatchingMethod) err = protocol.WriteAuthentication(connection, authResponse) if err != nil { log.Error("Socks failed to write authentication: %v", err) return err } log.Warning("Socks client doesn't support allowed any auth methods.") return errors.NewInvalidOperationError("Unsupported auth methods.") } authResponse := protocol.NewAuthenticationResponse(expectedAuthMethod) err = protocol.WriteAuthentication(connection, authResponse) if err != nil { log.Error("Socks failed to write authentication: %v", err) return err } if server.config.IsPassword() { upRequest, err := protocol.ReadUserPassRequest(reader) if err != nil { log.Error("Socks failed to read username and password: %v", err) return err } status := byte(0) if !upRequest.IsValid(server.config.Username, server.config.Password) { status = byte(0xFF) } upResponse := protocol.NewSocks5UserPassResponse(status) err = protocol.WriteUserPassResponse(connection, upResponse) if err != nil { log.Error("Socks failed to write user pass response: %v", err) return err } if status != byte(0) { err = errors.NewAuthenticationError(upRequest.AuthDetail()) log.Warning(err.Error()) return err } } request, err := protocol.ReadRequest(reader) if err != nil { log.Error("Socks failed to read request: %v", err) return err } response := protocol.NewSocks5Response() if request.Command == protocol.CmdBind || request.Command == protocol.CmdUdpAssociate { response := protocol.NewSocks5Response() response.Error = protocol.ErrorCommandNotSupported err = protocol.WriteResponse(connection, response) if err != nil { log.Error("Socks failed to write response: %v", err) return err } log.Warning("Unsupported socks command %d", request.Command) return errors.NewInvalidOperationError("Socks command " + strconv.Itoa(int(request.Command))) } response.Error = protocol.ErrorSuccess response.Port = request.Port response.AddrType = request.AddrType switch response.AddrType { case protocol.AddrTypeIPv4: copy(response.IPv4[:], request.IPv4[:]) case protocol.AddrTypeIPv6: copy(response.IPv6[:], request.IPv6[:]) case protocol.AddrTypeDomain: response.Domain = request.Domain } err = protocol.WriteResponse(connection, response) if err != nil { log.Error("Socks failed to write response: %v", err) return err } dest = request.Destination() } ray := server.vPoint.DispatchToOutbound(v2net.NewTCPPacket(dest)) input := ray.InboundInput() output := ray.InboundOutput() var readFinish, writeFinish sync.Mutex readFinish.Lock() writeFinish.Lock() go dumpInput(reader, input, &readFinish) go dumpOutput(connection, output, &writeFinish) writeFinish.Lock() return nil }
// Read reads a VMessRequest from a byte stream. func (r *VMessRequestReader) Read(reader io.Reader) (*VMessRequest, error) { buffer := make([]byte, 256) nBytes, err := reader.Read(buffer[:user.IDBytesLen]) if err != nil { return nil, err } log.Debug("Read user hash: %v", buffer[:nBytes]) userId, timeSec, valid := r.vUserSet.GetUser(buffer[:nBytes]) if !valid { return nil, errors.NewAuthenticationError(buffer[:nBytes]) } aesCipher, err := aes.NewCipher(userId.CmdKey()) if err != nil { return nil, err } aesStream := cipher.NewCFBDecrypter(aesCipher, user.Int64Hash(timeSec)) decryptor := v2io.NewCryptionReader(aesStream, reader) if err != nil { return nil, err } nBytes, err = decryptor.Read(buffer[:41]) if err != nil { return nil, err } bufferLen := nBytes request := &VMessRequest{ UserId: *userId, Version: buffer[0], } if request.Version != Version { return nil, errors.NewProtocolVersionError(int(request.Version)) } copy(request.RequestIV[:], buffer[1:17]) // 16 bytes copy(request.RequestKey[:], buffer[17:33]) // 16 bytes copy(request.ResponseHeader[:], buffer[33:37]) // 4 bytes request.Command = buffer[37] port := binary.BigEndian.Uint16(buffer[38:40]) switch buffer[40] { case addrTypeIPv4: _, err = decryptor.Read(buffer[41:45]) // 4 bytes bufferLen += 4 if err != nil { return nil, err } request.Address = v2net.IPAddress(buffer[41:45], port) case addrTypeIPv6: _, err = decryptor.Read(buffer[41:57]) // 16 bytes bufferLen += 16 if err != nil { return nil, err } request.Address = v2net.IPAddress(buffer[41:57], port) case addrTypeDomain: _, err = decryptor.Read(buffer[41:42]) if err != nil { return nil, err } domainLength := int(buffer[41]) _, err = decryptor.Read(buffer[42 : 42+domainLength]) if err != nil { return nil, err } bufferLen += 1 + domainLength request.Address = v2net.DomainAddress(string(buffer[42:42+domainLength]), port) } _, err = decryptor.Read(buffer[bufferLen : bufferLen+4]) if err != nil { return nil, err } fnv1a := fnv.New32a() fnv1a.Write(buffer[:bufferLen]) actualHash := fnv1a.Sum32() expectedHash := binary.BigEndian.Uint32(buffer[bufferLen : bufferLen+4]) if actualHash != expectedHash { return nil, errors.NewCorruptedPacketError() } return request, nil }