mirror of
https://gitee.com/samwaf/SamWaf.git
synced 2026-08-31 01:41:39 +08:00
feat:add domain whitelist
#IJQNEX
This commit is contained in:
@@ -440,6 +440,66 @@ func (w *WafVpConfigApi) UpdateNoticeTitleApi(c *gin.Context) {
|
||||
response.OkWithDetailed(resp, "更新通知标题成功", c)
|
||||
}
|
||||
|
||||
// GetDomainWhitelistApi 获取管理端域名白名单
|
||||
// @Summary 获取管理端域名白名单
|
||||
// @Description 获取当前管理端允许访问的域名白名单配置
|
||||
// @Tags 管理端配置
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {object} response.Response "获取域名白名单成功"
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /vipconfig/getDomainWhitelist [get]
|
||||
func (w *WafVpConfigApi) GetDomainWhitelistApi(c *gin.Context) {
|
||||
resp := response2.WafVpConfigDomainWhitelistGetResp{
|
||||
DomainWhitelist: global.GWAF_DOMAIN_WHITELIST,
|
||||
}
|
||||
response.OkWithDetailed(resp, "获取域名白名单成功", c)
|
||||
}
|
||||
|
||||
// UpdateDomainWhitelistApi 更新管理端域名白名单
|
||||
// @Summary 更新管理端域名白名单
|
||||
// @Description 更新管理端允许访问的域名白名单(多个域名用逗号分隔,为空表示不限制)
|
||||
// @Tags 管理端配置
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param data body request.WafVpConfigDomainWhitelistUpdateReq true "域名白名单配置"
|
||||
// @Success 200 {object} response.Response "更新域名白名单成功"
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /vipconfig/updateDomainWhitelist [post]
|
||||
func (w *WafVpConfigApi) UpdateDomainWhitelistApi(c *gin.Context) {
|
||||
var req request.WafVpConfigDomainWhitelistUpdateReq
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.FailWithMessage("解析请求失败", c)
|
||||
return
|
||||
}
|
||||
|
||||
// 若白名单非空,当前访问域名必须在列表中,防止把自己锁在外面
|
||||
if strings.TrimSpace(req.DomainWhitelist) != "" {
|
||||
host := c.Request.Host
|
||||
hostname, _, err := net.SplitHostPort(host)
|
||||
if err != nil {
|
||||
hostname = host
|
||||
}
|
||||
selfIncluded := false
|
||||
for _, d := range strings.Split(req.DomainWhitelist, ",") {
|
||||
if strings.TrimSpace(d) == hostname {
|
||||
selfIncluded = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !selfIncluded {
|
||||
response.FailWithMessage(fmt.Sprintf("当前访问域名(%s)不在新白名单中,保存后将无法访问管理端,请先将当前域名加入白名单", hostname), c)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if err := wafconfig.UpdateDomainWhitelist(req.DomainWhitelist); err != nil {
|
||||
response.FailWithMessage("更新域名白名单失败: "+err.Error(), c)
|
||||
} else {
|
||||
response.OkWithMessage("更新域名白名单成功", c)
|
||||
}
|
||||
}
|
||||
|
||||
// RestartManagerApi 重启管理端
|
||||
// @Summary 重启管理端
|
||||
// @Description 触发管理端1秒后重启,请等待5-10秒后重新访问
|
||||
|
||||
@@ -77,6 +77,7 @@ var (
|
||||
|
||||
//管理端访问控制
|
||||
GWAF_IP_WHITELIST string = "0.0.0.0/0,::/0" //IP白名单 后台默认放行所有
|
||||
GWAF_DOMAIN_WHITELIST string = "" //域名白名单,为空时不限制,多个用逗号分隔
|
||||
GWAF_SSL_ENABLE bool = false //是否启用SSL证书
|
||||
GWAF_SECURITY_ENTRY_ENABLE bool = false //是否启用安全路径入口
|
||||
GWAF_SECURITY_ENTRY_PATH string = "" //安全路径(18位随机码)
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"SamWaf/global"
|
||||
"github.com/gin-gonic/gin"
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// DomainWhitelist 域名白名单中间件
|
||||
// 为空时不限制;非空时仅允许 Host 匹配的域名访问(忽略端口)。
|
||||
func DomainWhitelist() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
whitelist := strings.TrimSpace(global.GWAF_DOMAIN_WHITELIST)
|
||||
if whitelist == "" {
|
||||
c.Next()
|
||||
return
|
||||
}
|
||||
|
||||
host := c.Request.Host
|
||||
hostname, _, err := net.SplitHostPort(host)
|
||||
if err != nil {
|
||||
hostname = host
|
||||
}
|
||||
|
||||
for _, domain := range strings.Split(whitelist, ",") {
|
||||
if strings.TrimSpace(domain) == hostname {
|
||||
c.Next()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
c.AbortWithStatusJSON(http.StatusForbidden, gin.H{
|
||||
"message": "Access denied",
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -26,3 +26,8 @@ type WafVpConfigSecurityEntryUpdateReq struct {
|
||||
type WafVpConfigNoticeTitleUpdateReq struct {
|
||||
NoticeTitle string `json:"notice_title"` // 通知消息标题前缀,用于区分多实例
|
||||
}
|
||||
|
||||
// WafVpConfigDomainWhitelistUpdateReq 域名白名单更新请求
|
||||
type WafVpConfigDomainWhitelistUpdateReq struct {
|
||||
DomainWhitelist string `json:"domain_whitelist"` // 多个域名用逗号分隔,为空表示不限制
|
||||
}
|
||||
|
||||
@@ -25,3 +25,8 @@ type WafVpConfigSecurityEntryGetResp struct {
|
||||
type WafVpConfigNoticeTitleGetResp struct {
|
||||
NoticeTitle string `json:"notice_title"` // 通知消息标题前缀
|
||||
}
|
||||
|
||||
// WafVpConfigDomainWhitelistGetResp 域名白名单获取响应
|
||||
type WafVpConfigDomainWhitelistGetResp struct {
|
||||
DomainWhitelist string `json:"domain_whitelist"`
|
||||
}
|
||||
|
||||
@@ -22,4 +22,6 @@ func (receiver *WafVpConfigRouter) InitWafVpConfigRouter(group *gin.RouterGroup)
|
||||
router.POST("/api/v1/vipconfig/updateSecurityEntry", wafVpConfigApi.UpdateSecurityEntryApi)
|
||||
router.GET("/api/v1/vipconfig/getNoticeTitle", wafVpConfigApi.GetNoticeTitleApi)
|
||||
router.POST("/api/v1/vipconfig/updateNoticeTitle", wafVpConfigApi.UpdateNoticeTitleApi)
|
||||
router.GET("/api/v1/vipconfig/getDomainWhitelist", wafVpConfigApi.GetDomainWhitelistApi)
|
||||
router.POST("/api/v1/vipconfig/updateDomainWhitelist", wafVpConfigApi.UpdateDomainWhitelistApi)
|
||||
}
|
||||
|
||||
@@ -155,6 +155,14 @@ func LoadAndInitConfig() {
|
||||
configChanged = true
|
||||
}
|
||||
|
||||
//配置和提取域名白名单
|
||||
if config.IsSet("security.domain_whitelist") {
|
||||
global.GWAF_DOMAIN_WHITELIST = config.GetString("security.domain_whitelist")
|
||||
} else {
|
||||
config.Set("security.domain_whitelist", global.GWAF_DOMAIN_WHITELIST)
|
||||
configChanged = true
|
||||
}
|
||||
|
||||
//配置和提取SSL启用状态
|
||||
if config.IsSet("security.ssl_enable") {
|
||||
global.GWAF_SSL_ENABLE = config.GetBool("security.ssl_enable")
|
||||
@@ -355,6 +363,48 @@ func UpdateIpWhitelist(ipWhitelist string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateDomainWhitelist 更新域名白名单配置
|
||||
func UpdateDomainWhitelist(domainWhitelist string) error {
|
||||
currentTime := time.Now().Format("2006-01-02 15:04:05.000")
|
||||
|
||||
configDir := utils.GetCurrentDir() + "/conf/"
|
||||
if _, err := os.Stat(configDir); os.IsNotExist(err) {
|
||||
if err := os.MkdirAll(configDir, os.ModePerm); err != nil {
|
||||
fmt.Printf("%s\tERROR\t创建config目录失败:%v\n", currentTime, err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
config := viper.New()
|
||||
config.AddConfigPath(configDir)
|
||||
config.SetConfigName("config")
|
||||
config.SetConfigType("yml")
|
||||
|
||||
if err := config.ReadInConfig(); err != nil {
|
||||
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
|
||||
fmt.Printf("%s\tWARN\t找不到配置文件..\n", currentTime)
|
||||
config.Set("local_port", global.GWAF_LOCAL_SERVER_PORT)
|
||||
if err = config.SafeWriteConfig(); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
fmt.Printf("%s\tERROR\t配置文件出错..\n", currentTime)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
config.Set("security.domain_whitelist", domainWhitelist)
|
||||
global.GWAF_DOMAIN_WHITELIST = domainWhitelist
|
||||
|
||||
if err := config.WriteConfig(); err != nil {
|
||||
fmt.Printf("%s\tERROR\twrite config failed:%v\n", currentTime, err)
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("%s\tINFO\tDomain whitelist config updated\n", currentTime)
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateSslEnable 更新SSL启用状态配置
|
||||
func UpdateSslEnable(sslEnable bool) error {
|
||||
// 格式化当前时间为指定格式
|
||||
|
||||
@@ -98,12 +98,12 @@ func (h *securityPathHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
|
||||
func (web *WafWebManager) initRouter(r *gin.Engine) {
|
||||
|
||||
PublicRouterGroup := r.Group("")
|
||||
PublicRouterGroup.Use(middleware.SecApi(), middleware.IPWhitelist(), middleware.ReplayProtect())
|
||||
PublicRouterGroup.Use(middleware.SecApi(), middleware.IPWhitelist(), middleware.DomainWhitelist(), middleware.ReplayProtect())
|
||||
router.PublicApiGroupApp.InitLoginRouter(PublicRouterGroup)
|
||||
router.PublicApiGroupApp.InitCenterRouter(PublicRouterGroup) //注册中心接收接口
|
||||
|
||||
RouterGroup := r.Group("")
|
||||
RouterGroup.Use(middleware.Auth(), middleware.ReplayProtect(), middleware.OpenApiLogMiddleware(), middleware.CenterApi(), middleware.SecApi(), middleware.GinGlobalExceptionMiddleWare(), middleware.IPWhitelist()) //TODO 中心管控 特定
|
||||
RouterGroup.Use(middleware.Auth(), middleware.ReplayProtect(), middleware.OpenApiLogMiddleware(), middleware.CenterApi(), middleware.SecApi(), middleware.GinGlobalExceptionMiddleWare(), middleware.IPWhitelist(), middleware.DomainWhitelist()) //TODO 中心管控 特定
|
||||
{
|
||||
router.ApiGroupApp.InitHostRouter(RouterGroup)
|
||||
router.ApiGroupApp.InitLogRouter(RouterGroup)
|
||||
|
||||
Reference in New Issue
Block a user