Skip to content

Commit 19a3967

Browse files
feat: Fix issue where accessing with an unbound domain returns an error (#8014)
1 parent d36311c commit 19a3967

File tree

7 files changed

+143
-32
lines changed

7 files changed

+143
-32
lines changed

core/app/api/v2/setting.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,14 @@ func (b *BaseApi) UpdateSetting(c *gin.Context) {
6868
if err := helper.CheckBindAndValidate(&req, c); err != nil {
6969
return
7070
}
71-
7271
if err := settingService.Update(req.Key, req.Value); err != nil {
7372
helper.InternalServer(c, err)
7473
return
7574
}
75+
if req.Key == "SecurityEntrance" {
76+
entranceValue := base64.StdEncoding.EncodeToString([]byte(req.Value))
77+
c.SetCookie("SecurityEntrance", entranceValue, 0, "", "", false, true)
78+
}
7679
helper.SuccessWithOutData(c)
7780
}
7881

core/init/router/router.go

Lines changed: 68 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package router
33
import (
44
"encoding/base64"
55
"fmt"
6+
"github.com/1Panel-dev/1Panel/core/app/repo"
7+
"github.com/1Panel-dev/1Panel/core/utils/common"
68
"net/http"
79
"regexp"
810
"strconv"
@@ -61,7 +63,7 @@ func checkEntrance(c *gin.Context) bool {
6163
return string(entranceValue) == entrance
6264
}
6365

64-
func handleNoRoute(c *gin.Context) {
66+
func handleNoRoute(c *gin.Context, resType string) {
6567
resPage, err := service.NewIAuthService().GetResponsePage()
6668
if err != nil {
6769
c.String(http.StatusInternalServerError, "Internal Server Error")
@@ -73,6 +75,9 @@ func handleNoRoute(c *gin.Context) {
7375
}
7476

7577
file := fmt.Sprintf("html/%s.html", resPage)
78+
if resPage == "200" && resType != "" {
79+
file = fmt.Sprintf("html/200_%s.html", resType)
80+
}
7681
data, err := res.ErrorMsg.ReadFile(file)
7782
if err != nil {
7883
c.String(http.StatusInternalServerError, "Internal Server Error")
@@ -110,6 +115,43 @@ func checkFrontendPath(c *gin.Context) bool {
110115
return true
111116
}
112117

118+
func checkBindDomain(c *gin.Context) bool {
119+
settingRepo := repo.NewISettingRepo()
120+
status, _ := settingRepo.Get(repo.WithByKey("BindDomain"))
121+
if len(status.Value) == 0 {
122+
return true
123+
}
124+
domains := c.Request.Host
125+
parts := strings.Split(c.Request.Host, ":")
126+
if len(parts) > 0 {
127+
domains = parts[0]
128+
}
129+
return domains == status.Value
130+
}
131+
132+
func checkIPLimit(c *gin.Context) bool {
133+
settingRepo := repo.NewISettingRepo()
134+
status, _ := settingRepo.Get(repo.WithByKey("AllowIPs"))
135+
if len(status.Value) == 0 {
136+
return true
137+
}
138+
clientIP := c.ClientIP()
139+
for _, ip := range strings.Split(status.Value, ",") {
140+
if len(ip) == 0 {
141+
continue
142+
}
143+
if ip == clientIP || (strings.Contains(ip, "/") && common.CheckIpInCidr(ip, clientIP)) {
144+
return true
145+
}
146+
}
147+
return false
148+
}
149+
150+
func checkSession(c *gin.Context) bool {
151+
_, err := global.SESSION.Get(c)
152+
return err == nil
153+
}
154+
113155
func setWebStatic(rootRouter *gin.RouterGroup) {
114156
rootRouter.StaticFS("/public", http.FS(web.Favicon))
115157
rootRouter.StaticFS("/favicon.ico", http.FS(web.Favicon))
@@ -128,17 +170,30 @@ func setWebStatic(rootRouter *gin.RouterGroup) {
128170
rootRouter.GET("/"+entrance, func(c *gin.Context) {
129171
currentEntrance := authService.GetSecurityEntrance()
130172
if currentEntrance != entrance {
131-
handleNoRoute(c)
173+
handleNoRoute(c, "")
132174
return
133175
}
134176
toIndexHtml(c)
135177
})
136178
}
137179
rootRouter.GET("/", func(c *gin.Context) {
138-
if !checkEntrance(c) {
139-
handleNoRoute(c)
180+
if !checkEntrance(c) && !checkSession(c) {
181+
handleNoRoute(c, "")
140182
return
141183
}
184+
if !checkBindDomain(c) {
185+
handleNoRoute(c, "err_domain")
186+
return
187+
}
188+
if !checkIPLimit(c) {
189+
handleNoRoute(c, "err_ip_limit")
190+
return
191+
}
192+
entrance = authService.GetSecurityEntrance()
193+
if entrance != "" {
194+
entranceValue := base64.StdEncoding.EncodeToString([]byte(entrance))
195+
c.SetCookie("SecurityEntrance", entranceValue, 0, "", "", false, true)
196+
}
142197
staticServer := http.FileServer(http.FS(web.IndexHtml))
143198
staticServer.ServeHTTP(c.Writer, c.Request)
144199
})
@@ -173,6 +228,14 @@ func Routers() *gin.Engine {
173228
}
174229

175230
Router.NoRoute(func(c *gin.Context) {
231+
if !checkBindDomain(c) {
232+
handleNoRoute(c, "err_domain")
233+
return
234+
}
235+
if !checkIPLimit(c) {
236+
handleNoRoute(c, "err_ip_limit")
237+
return
238+
}
176239
if checkFrontendPath(c) {
177240
toIndexHtml(c)
178241
return
@@ -181,7 +244,7 @@ func Routers() *gin.Engine {
181244
toIndexHtml(c)
182245
return
183246
}
184-
handleNoRoute(c)
247+
handleNoRoute(c, "")
185248
})
186249

187250
return Router

core/middleware/ip_limit.go

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,11 @@ package middleware
22

33
import (
44
"errors"
5-
"net"
5+
"github.com/1Panel-dev/1Panel/core/utils/common"
66
"strings"
77

88
"github.com/1Panel-dev/1Panel/core/app/api/v2/helper"
99
"github.com/1Panel-dev/1Panel/core/app/repo"
10-
"github.com/1Panel-dev/1Panel/core/global"
1110
"github.com/gin-gonic/gin"
1211
)
1312

@@ -29,7 +28,7 @@ func WhiteAllow() gin.HandlerFunc {
2928
if len(ip) == 0 {
3029
continue
3130
}
32-
if ip == clientIP || (strings.Contains(ip, "/") && checkIpInCidr(ip, clientIP)) {
31+
if ip == clientIP || (strings.Contains(ip, "/") && common.CheckIpInCidr(ip, clientIP)) {
3332
c.Next()
3433
return
3534
}
@@ -41,26 +40,3 @@ func WhiteAllow() gin.HandlerFunc {
4140
helper.ErrorWithDetail(c, 310, "ErrInternalServer", errors.New("IP address not allowed"))
4241
}
4342
}
44-
45-
func checkIpInCidr(cidr, checkIP string) bool {
46-
ip, ipNet, err := net.ParseCIDR(cidr)
47-
if err != nil {
48-
global.LOG.Errorf("parse CIDR %s failed, err: %v", cidr, err)
49-
return false
50-
}
51-
for ip := ip.Mask(ipNet.Mask); ipNet.Contains(ip); incIP(ip) {
52-
if ip.String() == checkIP {
53-
return true
54-
}
55-
}
56-
return false
57-
}
58-
59-
func incIP(ip net.IP) {
60-
for j := len(ip) - 1; j >= 0; j-- {
61-
ip[j]++
62-
if ip[j] > 0 {
63-
break
64-
}
65-
}
66-
}

core/utils/common/common.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,3 +163,26 @@ func GetLang(c *gin.Context) string {
163163
}
164164
return lang
165165
}
166+
167+
func CheckIpInCidr(cidr, checkIP string) bool {
168+
ip, ipNet, err := net.ParseCIDR(cidr)
169+
if err != nil {
170+
global.LOG.Errorf("parse CIDR %s failed, err: %v", cidr, err)
171+
return false
172+
}
173+
for ip := ip.Mask(ipNet.Mask); ipNet.Contains(ip); incIP(ip) {
174+
if ip.String() == checkIP {
175+
return true
176+
}
177+
}
178+
return false
179+
}
180+
181+
func incIP(ip net.IP) {
182+
for j := len(ip) - 1; j >= 0; j-- {
183+
ip[j]++
184+
if ip[j] > 0 {
185+
break
186+
}
187+
}
188+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{
2+
"Anhui": "Anhui",
3+
"Beijing": "Beijing",
4+
"Fujian": "Fujian",
5+
"Gansu": "Gansu",
6+
"Guangdong": "Guangdong",
7+
"Guangxi": "Guangxi",
8+
"Guizhou": "Guizhou",
9+
"Hainan": "Hainan",
10+
"Hebei": "Hebei",
11+
"Henan": "Henan",
12+
"Heilongjiang": "Heilongjiang",
13+
"Hubei": "Hubei",
14+
"Hunan": "Hunan",
15+
"Jilin": "Jilin",
16+
"Jiangsu": "Jiangsu",
17+
"Jiangxi": "Jiangxi",
18+
"Liaoning": "Liaoning",
19+
"Inner Mongolia": "Inner Mongolia",
20+
"Ningxia": "Ningxia",
21+
"Qinghai": "Qinghai",
22+
"Shandong": "Shandong",
23+
"Shanxi": "Shanxi",
24+
"Shaanxi": "Shaanxi",
25+
"Shanghai": "Shanghai",
26+
"Sichuan": "Sichuan",
27+
"Tianjin": "Tianjin",
28+
"Tibet": "Tibet",
29+
"Xinjiang": "Xinjiang",
30+
"Yunnan": "Yunnan",
31+
"Zhejiang": "Zhejiang",
32+
"Chongqing": "Chongqing",
33+
"HongKong": "Hong Kong",
34+
"Macao": "Macau",
35+
"Taiwan": "Taiwan"
36+
}

frontend/src/utils/util.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -766,3 +766,13 @@ export const encryptPassword = (password: string) => {
766766
const passwordCipher = aesEncrypt(password, aesKey);
767767
return `${keyCipher}:${passwordCipher}`;
768768
};
769+
770+
export async function loadJson(lang: string): Promise<Object> {
771+
try {
772+
lang = lang == 'zh' ? 'zh' : 'en';
773+
const jsonModule = await import(`@/assets/json/china/${lang}.json`);
774+
return jsonModule.default;
775+
} catch (error) {
776+
throw new Error(`Language file not found: ${lang}`);
777+
}
778+
}

0 commit comments

Comments
 (0)