Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions core/init/router/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,16 @@ package router

import (
"context"
"github.com/1Panel-dev/1Panel/core/app/repo"
"github.com/1Panel-dev/1Panel/core/cmd/server/res"
"github.com/1Panel-dev/1Panel/core/constant"
"github.com/1Panel-dev/1Panel/core/global"
"github.com/1Panel-dev/1Panel/core/utils/security"
"net"
"net/http"
"net/http/httputil"
"os"
"strconv"
"strings"

"github.com/1Panel-dev/1Panel/core/app/api/v2/helper"
Expand Down Expand Up @@ -38,6 +44,13 @@ func Proxy() gin.HandlerFunc {
currentNode = c.Request.Header.Get("CurrentNode")
}

if strings.HasPrefix(c.Request.URL.Path, "/api/v2/") && !checkSession(c) {
data, _ := res.ErrorMsg.ReadFile("html/401.html")
c.Data(401, "text/html; charset=utf-8", data)
c.Abort()
return
}

if !strings.HasPrefix(c.Request.URL.Path, "/api/v2/core") && (currentNode == "local" || len(currentNode) == 0 || currentNode == "127.0.0.1") {
sockPath := "/etc/1panel/agent.sock"
if _, err := os.Stat(sockPath); err != nil {
Expand All @@ -58,6 +71,13 @@ func Proxy() gin.HandlerFunc {
req.URL.Host = "unix"
},
Transport: transport,
ModifyResponse: func(response *http.Response) error {
if response.StatusCode == 404 {
security.HandleNotSecurity(c, "")
c.Abort()
}
return nil
},
}
proxy.ServeHTTP(c.Writer, c.Request)
c.Abort()
Expand All @@ -67,3 +87,22 @@ func Proxy() gin.HandlerFunc {
c.Abort()
}
}

func checkSession(c *gin.Context) bool {
psession, err := global.SESSION.Get(c)
if err != nil {
return false
}
settingRepo := repo.NewISettingRepo()
setting, err := settingRepo.Get(repo.WithByKey("SessionTimeout"))
if err != nil {
return false
}
lifeTime, _ := strconv.Atoi(setting.Value)
httpsSetting, err := settingRepo.Get(repo.WithByKey("SSL"))
if err != nil {
return false
}
_ = global.SESSION.Set(c, psession, httpsSetting.Value == constant.StatusEnable, lifeTime)
return true
}
171 changes: 9 additions & 162 deletions core/init/router/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,157 +3,26 @@ package router
import (
"encoding/base64"
"fmt"
"net/http"
"path"
"regexp"
"strconv"
"strings"

"github.com/1Panel-dev/1Panel/core/app/repo"
"github.com/1Panel-dev/1Panel/core/utils/common"

"github.com/1Panel-dev/1Panel/core/app/service"
"github.com/1Panel-dev/1Panel/core/cmd/server/res"
"github.com/1Panel-dev/1Panel/core/constant"

"github.com/1Panel-dev/1Panel/core/cmd/server/docs"
"github.com/1Panel-dev/1Panel/core/cmd/server/web"
"github.com/1Panel-dev/1Panel/core/global"
"github.com/1Panel-dev/1Panel/core/i18n"
"github.com/1Panel-dev/1Panel/core/middleware"
rou "github.com/1Panel-dev/1Panel/core/router"
"github.com/1Panel-dev/1Panel/core/utils/security"
"github.com/gin-contrib/gzip"
"github.com/gin-gonic/gin"
swaggerfiles "github.com/swaggo/files"
ginSwagger "github.com/swaggo/gin-swagger"
"net/http"
"path"
)

var (
Router *gin.Engine
)

func toIndexHtml(c *gin.Context) {
c.Writer.Header().Set("Content-Type", "text/html; charset=utf-8")
c.Writer.WriteHeader(http.StatusOK)
_, _ = c.Writer.Write(web.IndexByte)
c.Writer.Flush()
}

func isEntrancePath(c *gin.Context) bool {
entrance := service.NewIAuthService().GetSecurityEntrance()
if entrance != "" && strings.TrimSuffix(c.Request.URL.Path, "/") == "/"+entrance {
return true
}
return false
}

func checkEntrance(c *gin.Context) bool {
authService := service.NewIAuthService()
entrance := authService.GetSecurityEntrance()
if entrance == "" {
return true
}

cookieValue, err := c.Cookie("SecurityEntrance")
if err != nil {
return false
}
entranceValue, err := base64.StdEncoding.DecodeString(cookieValue)
if err != nil {
return false
}
return string(entranceValue) == entrance
}

func handleNoRoute(c *gin.Context, resType string) {
resPage, err := service.NewIAuthService().GetResponsePage()
if err != nil {
c.String(http.StatusInternalServerError, "Internal Server Error")
return
}
if resPage == "444" {
c.String(444, "")
return
}

file := fmt.Sprintf("html/%s.html", resPage)
if resPage == "200" && resType != "" {
file = fmt.Sprintf("html/200_%s.html", resType)
}
data, err := res.ErrorMsg.ReadFile(file)
if err != nil {
c.String(http.StatusInternalServerError, "Internal Server Error")
return
}
statusCode, err := strconv.Atoi(resPage)
if err != nil {
c.String(http.StatusInternalServerError, "Internal Server Error")
return
}
c.Data(statusCode, "text/html; charset=utf-8", data)
}

func isFrontendPath(c *gin.Context) bool {
reqUri := strings.TrimSuffix(c.Request.URL.Path, "/")
if _, ok := constant.WebUrlMap[reqUri]; ok {
return true
}
for _, route := range constant.DynamicRoutes {
if match, _ := regexp.MatchString(route, reqUri); match {
return true
}
}
return false
}

func checkFrontendPath(c *gin.Context) bool {
if !isFrontendPath(c) {
return false
}
authService := service.NewIAuthService()
if authService.GetSecurityEntrance() != "" {
return authService.IsLogin(c)
}
return true
}

func checkBindDomain(c *gin.Context) bool {
settingRepo := repo.NewISettingRepo()
status, _ := settingRepo.Get(repo.WithByKey("BindDomain"))
if len(status.Value) == 0 {
return true
}
domains := c.Request.Host
parts := strings.Split(c.Request.Host, ":")
if len(parts) > 0 {
domains = parts[0]
}
return domains == status.Value
}

func checkIPLimit(c *gin.Context) bool {
settingRepo := repo.NewISettingRepo()
status, _ := settingRepo.Get(repo.WithByKey("AllowIPs"))
if len(status.Value) == 0 {
return true
}
clientIP := c.ClientIP()
for _, ip := range strings.Split(status.Value, ",") {
if len(ip) == 0 {
continue
}
if ip == clientIP || (strings.Contains(ip, "/") && common.CheckIpInCidr(ip, clientIP)) {
return true
}
}
return false
}

func checkSession(c *gin.Context) bool {
_, err := global.SESSION.Get(c)
return err == nil
}

func setWebStatic(rootRouter *gin.RouterGroup) {
rootRouter.StaticFS("/public", http.FS(web.Favicon))
rootRouter.StaticFS("/favicon.ico", http.FS(web.Favicon))
Expand All @@ -172,23 +41,14 @@ func setWebStatic(rootRouter *gin.RouterGroup) {
rootRouter.GET("/"+entrance, func(c *gin.Context) {
currentEntrance := authService.GetSecurityEntrance()
if currentEntrance != entrance {
handleNoRoute(c, "")
security.HandleNotSecurity(c, "")
return
}
toIndexHtml(c)
security.ToIndexHtml(c)
})
}
rootRouter.GET("/", func(c *gin.Context) {
if !checkEntrance(c) && !checkSession(c) {
handleNoRoute(c, "")
return
}
if !checkBindDomain(c) {
handleNoRoute(c, "err_domain")
return
}
if !checkIPLimit(c) {
handleNoRoute(c, "err_ip_limit")
if !security.CheckSecurity(c) {
return
}
entrance = authService.GetSecurityEntrance()
Expand Down Expand Up @@ -229,26 +89,13 @@ func Routers() *gin.Engine {
router.InitRouter(PrivateGroup)
}

Router.Use(middleware.SessionAuth())
Router.Use(middleware.ApiAuth())
Router.Use(Proxy())
Router.NoRoute(func(c *gin.Context) {
if !checkBindDomain(c) {
handleNoRoute(c, "err_domain")
return
}
if !checkIPLimit(c) {
handleNoRoute(c, "err_ip_limit")
return
}
if checkFrontendPath(c) {
toIndexHtml(c)
return
}
if isEntrancePath(c) {
toIndexHtml(c)
if !security.HandleNotRoute(c) {
return
}
handleNoRoute(c, "")
security.HandleNotSecurity(c, "")
})

return Router
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are several changes made and improvements suggested in this code snippet:

  1. Imports: Some imports have been added back to fix compilation errors.

  2. Function Moves:

    • toIndexHtml was moved into the security package since it handles index HTML rendering which is security-related now.
    • handleNoRoute, checkEntrance, checkFrontendPath, checkBindDomain, checkIPLimit, and checkSession were all converted to security.*.
  3. Logic Changes:

    • The authentication logic has been consolidated under middleware.ApiAuth() for API routes.
    • No-route handling functions (handleNoRoute and related checks) have been deprecated and replaced with corresponding methods in the security package like HandleNotSecurity and HandleNotRoute.
  4. Documentation Update:

    • Comments mentioning isFrontendPath, checkFrontendPath, checkSession, etc., have been removed as these are no longer needed after consolidation.
  5. Variable Renames:

    • Certain variables like entrance were renamed within their respective packages to avoid conflicts or misidentification.
  6. Consistent Function Calls:

    • Most function calls across the file now use lowercase letters unless necessary (e.g., CheckSecurity instead of checkSecurity) to adhere to Go coding standards.

These changes aim to improve consistency, maintainability, and clarity, especially in areas dealing with security-related paths and functionality.

Expand Down
Loading
Loading