mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-10-08 14:37:29 +08:00
feat: Fix issue where accessing with an unbound domain returns an error (#8014)
This commit is contained in:
parent
d36311cff1
commit
19a3967603
7 changed files with 143 additions and 32 deletions
|
@ -68,11 +68,14 @@ func (b *BaseApi) UpdateSetting(c *gin.Context) {
|
||||||
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := settingService.Update(req.Key, req.Value); err != nil {
|
if err := settingService.Update(req.Key, req.Value); err != nil {
|
||||||
helper.InternalServer(c, err)
|
helper.InternalServer(c, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if req.Key == "SecurityEntrance" {
|
||||||
|
entranceValue := base64.StdEncoding.EncodeToString([]byte(req.Value))
|
||||||
|
c.SetCookie("SecurityEntrance", entranceValue, 0, "", "", false, true)
|
||||||
|
}
|
||||||
helper.SuccessWithOutData(c)
|
helper.SuccessWithOutData(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@ package router
|
||||||
import (
|
import (
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/1Panel-dev/1Panel/core/app/repo"
|
||||||
|
"github.com/1Panel-dev/1Panel/core/utils/common"
|
||||||
"net/http"
|
"net/http"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -61,7 +63,7 @@ func checkEntrance(c *gin.Context) bool {
|
||||||
return string(entranceValue) == entrance
|
return string(entranceValue) == entrance
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleNoRoute(c *gin.Context) {
|
func handleNoRoute(c *gin.Context, resType string) {
|
||||||
resPage, err := service.NewIAuthService().GetResponsePage()
|
resPage, err := service.NewIAuthService().GetResponsePage()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.String(http.StatusInternalServerError, "Internal Server Error")
|
c.String(http.StatusInternalServerError, "Internal Server Error")
|
||||||
|
@ -73,6 +75,9 @@ func handleNoRoute(c *gin.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
file := fmt.Sprintf("html/%s.html", resPage)
|
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)
|
data, err := res.ErrorMsg.ReadFile(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.String(http.StatusInternalServerError, "Internal Server Error")
|
c.String(http.StatusInternalServerError, "Internal Server Error")
|
||||||
|
@ -110,6 +115,43 @@ func checkFrontendPath(c *gin.Context) bool {
|
||||||
return true
|
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) {
|
func setWebStatic(rootRouter *gin.RouterGroup) {
|
||||||
rootRouter.StaticFS("/public", http.FS(web.Favicon))
|
rootRouter.StaticFS("/public", http.FS(web.Favicon))
|
||||||
rootRouter.StaticFS("/favicon.ico", http.FS(web.Favicon))
|
rootRouter.StaticFS("/favicon.ico", http.FS(web.Favicon))
|
||||||
|
@ -128,17 +170,30 @@ func setWebStatic(rootRouter *gin.RouterGroup) {
|
||||||
rootRouter.GET("/"+entrance, func(c *gin.Context) {
|
rootRouter.GET("/"+entrance, func(c *gin.Context) {
|
||||||
currentEntrance := authService.GetSecurityEntrance()
|
currentEntrance := authService.GetSecurityEntrance()
|
||||||
if currentEntrance != entrance {
|
if currentEntrance != entrance {
|
||||||
handleNoRoute(c)
|
handleNoRoute(c, "")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
toIndexHtml(c)
|
toIndexHtml(c)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
rootRouter.GET("/", func(c *gin.Context) {
|
rootRouter.GET("/", func(c *gin.Context) {
|
||||||
if !checkEntrance(c) {
|
if !checkEntrance(c) && !checkSession(c) {
|
||||||
handleNoRoute(c)
|
handleNoRoute(c, "")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if !checkBindDomain(c) {
|
||||||
|
handleNoRoute(c, "err_domain")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !checkIPLimit(c) {
|
||||||
|
handleNoRoute(c, "err_ip_limit")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
entrance = authService.GetSecurityEntrance()
|
||||||
|
if entrance != "" {
|
||||||
|
entranceValue := base64.StdEncoding.EncodeToString([]byte(entrance))
|
||||||
|
c.SetCookie("SecurityEntrance", entranceValue, 0, "", "", false, true)
|
||||||
|
}
|
||||||
staticServer := http.FileServer(http.FS(web.IndexHtml))
|
staticServer := http.FileServer(http.FS(web.IndexHtml))
|
||||||
staticServer.ServeHTTP(c.Writer, c.Request)
|
staticServer.ServeHTTP(c.Writer, c.Request)
|
||||||
})
|
})
|
||||||
|
@ -173,6 +228,14 @@ func Routers() *gin.Engine {
|
||||||
}
|
}
|
||||||
|
|
||||||
Router.NoRoute(func(c *gin.Context) {
|
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) {
|
if checkFrontendPath(c) {
|
||||||
toIndexHtml(c)
|
toIndexHtml(c)
|
||||||
return
|
return
|
||||||
|
@ -181,7 +244,7 @@ func Routers() *gin.Engine {
|
||||||
toIndexHtml(c)
|
toIndexHtml(c)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
handleNoRoute(c)
|
handleNoRoute(c, "")
|
||||||
})
|
})
|
||||||
|
|
||||||
return Router
|
return Router
|
||||||
|
|
|
@ -2,12 +2,11 @@ package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"net"
|
"github.com/1Panel-dev/1Panel/core/utils/common"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/1Panel-dev/1Panel/core/app/api/v2/helper"
|
"github.com/1Panel-dev/1Panel/core/app/api/v2/helper"
|
||||||
"github.com/1Panel-dev/1Panel/core/app/repo"
|
"github.com/1Panel-dev/1Panel/core/app/repo"
|
||||||
"github.com/1Panel-dev/1Panel/core/global"
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -29,7 +28,7 @@ func WhiteAllow() gin.HandlerFunc {
|
||||||
if len(ip) == 0 {
|
if len(ip) == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if ip == clientIP || (strings.Contains(ip, "/") && checkIpInCidr(ip, clientIP)) {
|
if ip == clientIP || (strings.Contains(ip, "/") && common.CheckIpInCidr(ip, clientIP)) {
|
||||||
c.Next()
|
c.Next()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -41,26 +40,3 @@ func WhiteAllow() gin.HandlerFunc {
|
||||||
helper.ErrorWithDetail(c, 310, "ErrInternalServer", errors.New("IP address not allowed"))
|
helper.ErrorWithDetail(c, 310, "ErrInternalServer", errors.New("IP address not allowed"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkIpInCidr(cidr, checkIP string) bool {
|
|
||||||
ip, ipNet, err := net.ParseCIDR(cidr)
|
|
||||||
if err != nil {
|
|
||||||
global.LOG.Errorf("parse CIDR %s failed, err: %v", cidr, err)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
for ip := ip.Mask(ipNet.Mask); ipNet.Contains(ip); incIP(ip) {
|
|
||||||
if ip.String() == checkIP {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func incIP(ip net.IP) {
|
|
||||||
for j := len(ip) - 1; j >= 0; j-- {
|
|
||||||
ip[j]++
|
|
||||||
if ip[j] > 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -163,3 +163,26 @@ func GetLang(c *gin.Context) string {
|
||||||
}
|
}
|
||||||
return lang
|
return lang
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CheckIpInCidr(cidr, checkIP string) bool {
|
||||||
|
ip, ipNet, err := net.ParseCIDR(cidr)
|
||||||
|
if err != nil {
|
||||||
|
global.LOG.Errorf("parse CIDR %s failed, err: %v", cidr, err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for ip := ip.Mask(ipNet.Mask); ipNet.Contains(ip); incIP(ip) {
|
||||||
|
if ip.String() == checkIP {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func incIP(ip net.IP) {
|
||||||
|
for j := len(ip) - 1; j >= 0; j-- {
|
||||||
|
ip[j]++
|
||||||
|
if ip[j] > 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
36
frontend/src/assets/json/china/en.json
Normal file
36
frontend/src/assets/json/china/en.json
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
{
|
||||||
|
"Anhui": "Anhui",
|
||||||
|
"Beijing": "Beijing",
|
||||||
|
"Fujian": "Fujian",
|
||||||
|
"Gansu": "Gansu",
|
||||||
|
"Guangdong": "Guangdong",
|
||||||
|
"Guangxi": "Guangxi",
|
||||||
|
"Guizhou": "Guizhou",
|
||||||
|
"Hainan": "Hainan",
|
||||||
|
"Hebei": "Hebei",
|
||||||
|
"Henan": "Henan",
|
||||||
|
"Heilongjiang": "Heilongjiang",
|
||||||
|
"Hubei": "Hubei",
|
||||||
|
"Hunan": "Hunan",
|
||||||
|
"Jilin": "Jilin",
|
||||||
|
"Jiangsu": "Jiangsu",
|
||||||
|
"Jiangxi": "Jiangxi",
|
||||||
|
"Liaoning": "Liaoning",
|
||||||
|
"Inner Mongolia": "Inner Mongolia",
|
||||||
|
"Ningxia": "Ningxia",
|
||||||
|
"Qinghai": "Qinghai",
|
||||||
|
"Shandong": "Shandong",
|
||||||
|
"Shanxi": "Shanxi",
|
||||||
|
"Shaanxi": "Shaanxi",
|
||||||
|
"Shanghai": "Shanghai",
|
||||||
|
"Sichuan": "Sichuan",
|
||||||
|
"Tianjin": "Tianjin",
|
||||||
|
"Tibet": "Tibet",
|
||||||
|
"Xinjiang": "Xinjiang",
|
||||||
|
"Yunnan": "Yunnan",
|
||||||
|
"Zhejiang": "Zhejiang",
|
||||||
|
"Chongqing": "Chongqing",
|
||||||
|
"HongKong": "Hong Kong",
|
||||||
|
"Macao": "Macau",
|
||||||
|
"Taiwan": "Taiwan"
|
||||||
|
}
|
|
@ -766,3 +766,13 @@ export const encryptPassword = (password: string) => {
|
||||||
const passwordCipher = aesEncrypt(password, aesKey);
|
const passwordCipher = aesEncrypt(password, aesKey);
|
||||||
return `${keyCipher}:${passwordCipher}`;
|
return `${keyCipher}:${passwordCipher}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export async function loadJson(lang: string): Promise<Object> {
|
||||||
|
try {
|
||||||
|
lang = lang == 'zh' ? 'zh' : 'en';
|
||||||
|
const jsonModule = await import(`@/assets/json/china/${lang}.json`);
|
||||||
|
return jsonModule.default;
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error(`Language file not found: ${lang}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue