// if success, ret equals 0, otherwise greater than 0 func doLogin(req *msg.ControlReq, c *conn.Conn) (ret int64, info string) { ret = 1 if req.PrivilegeMode && !server.PrivilegeMode { info = fmt.Sprintf("ProxyName [%s], PrivilegeMode is disabled in frps", req.ProxyName) log.Warn("info") return } var ( s *server.ProxyServer ok bool ) s, ok = server.ProxyServers[req.ProxyName] if req.PrivilegeMode && req.Type == consts.NewCtlConn { log.Debug("ProxyName [%s], doLogin and privilege mode is enabled", req.ProxyName) } else { if !ok { info = fmt.Sprintf("ProxyName [%s] is not exist", req.ProxyName) log.Warn(info) return } } // check authKey or privilegeKey nowTime := time.Now().Unix() if req.PrivilegeMode { privilegeKey := pcrypto.GetAuthKey(req.ProxyName + server.PrivilegeToken + fmt.Sprintf("%d", req.Timestamp)) // privilegeKey avaiable in 15 minutes if nowTime-req.Timestamp > 15*60 { info = fmt.Sprintf("ProxyName [%s], privilege mode authorization timeout", req.ProxyName) log.Warn(info) return } else if req.PrivilegeKey != privilegeKey { info = fmt.Sprintf("ProxyName [%s], privilege mode authorization failed", req.ProxyName) log.Warn(info) return } } else { authKey := pcrypto.GetAuthKey(req.ProxyName + s.AuthToken + fmt.Sprintf("%d", req.Timestamp)) // authKey avaiable in 15 minutes if nowTime-req.Timestamp > 15*60 { info = fmt.Sprintf("ProxyName [%s], authorization timeout", req.ProxyName) log.Warn(info) return } else if req.AuthKey != authKey { info = fmt.Sprintf("ProxyName [%s], authorization failed", req.ProxyName) log.Warn(info) return } } // control conn if req.Type == consts.NewCtlConn { if req.PrivilegeMode { s = server.NewProxyServerFromCtlMsg(req) err := server.CreateProxy(s) if err != nil { info = fmt.Sprintf("ProxyName [%s], %v", req.ProxyName, err) log.Warn(info) return } } if s.Status == consts.Working { info = fmt.Sprintf("ProxyName [%s], already in use", req.ProxyName) log.Warn(info) return } // check if vhost_port is set if s.Type == "http" && server.VhostHttpMuxer == nil { info = fmt.Sprintf("ProxyName [%s], type [http] not support when vhost_http_port is not set", req.ProxyName) log.Warn(info) return } if s.Type == "https" && server.VhostHttpsMuxer == nil { info = fmt.Sprintf("ProxyName [%s], type [https] not support when vhost_https_port is not set", req.ProxyName) log.Warn(info) return } // set infomations from frpc s.UseEncryption = req.UseEncryption s.UseGzip = req.UseGzip // start proxy and listen for user connections, no block err := s.Start(c) if err != nil { info = fmt.Sprintf("ProxyName [%s], start proxy error: %v", req.ProxyName, err) log.Warn(info) return } log.Info("ProxyName [%s], start proxy success", req.ProxyName) if req.PrivilegeMode { log.Info("ProxyName [%s], created by PrivilegeMode", req.ProxyName) } } else if req.Type == consts.NewWorkConn { // work conn if s.Status != consts.Working { log.Warn("ProxyName [%s], is not working when it gets one new work connnection", req.ProxyName) return } // the connection will close after join over s.RegisterNewWorkConn(c) } else { info = fmt.Sprintf("Unsupport login message type [%d]", req.Type) log.Warn("Unsupport login message type [%d]", req.Type) return } ret = 0 return }