Browse Source

refactor(waf): 重构 Web 辅助服务

- 将 AidedWebService 接口更名为 AidedWebServiceInterface
- 将 aidedWebService 结构体更名为 AidedWebService
- 移除未使用的导入
- 删除了大量未使用的代码
- 新增 cdnweb.go 和 configure.go 文件,拆分功能代码
fusu 1 day ago
parent
commit
5b4868ba14

+ 22 - 695
internal/service/api/waf/web/aidedweb.go

@@ -4,78 +4,30 @@ import (
 	"context"
 	"encoding/json"
 	"fmt"
-	waf2 "github.com/go-nunu/nunu-layout-advanced/internal/service/api/waf"
-	"github.com/go-nunu/nunu-layout-advanced/internal/service/api/waf/common"
-	"net"
-
 	v1 "github.com/go-nunu/nunu-layout-advanced/api/v1"
 	"github.com/go-nunu/nunu-layout-advanced/internal/model"
 	"github.com/go-nunu/nunu-layout-advanced/internal/repository/api/waf"
 	"github.com/go-nunu/nunu-layout-advanced/internal/service"
 	"github.com/go-nunu/nunu-layout-advanced/internal/service/api/flexCdn"
+	waf2 "github.com/go-nunu/nunu-layout-advanced/internal/service/api/waf"
+	"github.com/go-nunu/nunu-layout-advanced/internal/service/api/waf/common"
 )
 
 // AidedWebService Web转发辅助服务接口
-type AidedWebService interface {
-	// 验证相关
-	ValidateAddRequest(ctx context.Context, req *v1.WebForwardingRequest, require common.RequireResponse) error
-	ValidateEditRequest(ctx context.Context, req *v1.WebForwardingRequest) error
-	ValidateDeletePermission(oldHostId int, hostId int) error
-	
-	// CDN网站管理
-	CreateCdnWebsite(ctx context.Context, formData v1.Website) (int64, error)
-	UpdateCdnConfiguration(ctx context.Context, req *v1.WebForwardingRequest, oldData *model.WebForwarding, tag string, formData v1.Website) error
-	DeleteCdnServer(ctx context.Context, cdnWebId int) error
-	
-	// 源站管理
-	AddOriginsToWebsite(ctx context.Context, req *v1.WebForwardingRequest, webId int64) (map[string]int64, error)
-	UpdateOriginServers(ctx context.Context, req *v1.WebForwardingRequest, oldData *model.WebForwarding, ipData *model.WebForwardingRule) error
-	
-	// 功能配置管理
-	ConfigureWebsocket(ctx context.Context, webId int64) error
-	ConfigureProxyProtocol(ctx context.Context, proxy bool, cdnWebId int64) error
-	ConfigureCCProtection(ctx context.Context, ccConfig v1.CcConfigRequest, webId int64) error
-	ConfigureWafFirewall(ctx context.Context, webId int64, groupId int) error
-	
-	// 异步任务处理
-	ProcessAsyncTasks(ctx context.Context, req *v1.WebForwardingRequest, require common.RequireResponse)
-	ProcessIpWhitelistChanges(ctx context.Context, req *v1.WebForwardingRequest, ipData *model.WebForwardingRule) error
-	ProcessDeleteIpWhitelist(ctx context.Context, id int) error
-	ProcessDomainWhitelistChanges(ctx context.Context, req *v1.WebForwardingRequest, oldData *model.WebForwarding, require common.RequireResponse) error
-	ProcessDeleteDomainWhitelist(ctx context.Context, oldData *model.WebForwarding, uid int) error
-	
-	// 数据库操作
-	SaveToDatabase(ctx context.Context, req *v1.WebForwardingRequest, require common.RequireResponse, webId int64, cdnOriginIds map[string]int64) (int, error)
-	UpdateDatabaseRecords(ctx context.Context, req *v1.WebForwardingRequest, require common.RequireResponse, ipData *model.WebForwardingRule) error
-	CleanupDatabaseRecords(ctx context.Context, id int) error
-	
-	// SSL证书管理
-	ProcessSSLCertificate(ctx context.Context, req *v1.WebForwardingRequest, cdnUid int) error
-	ProcessSSLCertificateUpdate(ctx context.Context, req *v1.WebForwardingRequest, oldData *model.WebForwarding, cdnUid int) error
-	CleanupSSLCertificate(ctx context.Context, oldData *model.WebForwarding) error
-	
+type AidedWebServiceInterface interface {
 	// 数据准备辅助函数
 	PrepareWafData(ctx context.Context, req *v1.WebForwardingRequest) (common.RequireResponse, v1.Website, error)
 	BuildProxyConfig(ctx context.Context, req *v1.WebForwardingRequest, gatewayIps []string) (v1.TypeJSON, error)
 	BulidFormData(ctx context.Context, formData v1.Website) (v1.WebsiteSend, error)
-	
+
 	// 协议判断辅助函数
 	GetProtocolType(isHttps int) string
 	IsHttpsProtocol(isHttps int) bool
-	
+
 	// 模型构建辅助函数
 	BuildWebForwardingModel(req *v1.WebForwardingDataRequest, ruleId int, require common.RequireResponse) *model.WebForwarding
 	BuildWebRuleModel(reqData *v1.WebForwardingDataRequest, require common.RequireResponse, localDbId int, cdnOriginIds map[string]int64) *model.WebForwardingRule
-	
-	// 列表差异处理辅助函数
-	FindDifferenceList(oldList, newList []v1.BackendList) (added, removed []v1.BackendList)
-	WashDifferentIp(newIpList []string, oldIpList []string) (addedDenyIps []string, removedDenyIps []string)
-	
-	// 日志配置辅助函数
-	EditLog(ctx context.Context, webId int64) error
-	
-	// 废弃的方法(保持向后兼容)
-	CreateOriginServers(ctx context.Context, req *v1.WebForwardingRequest) (map[string]int64, error)
+
 }
 
 func NewAidedWebService(
@@ -90,8 +42,8 @@ func NewAidedWebService(
 	ccIpList waf2.CcIpListService,
 	gatewayIp common.GatewayipService,
 	globalLimitRep waf.GlobalLimitRepository,
-) AidedWebService {
-	return &aidedWebService{
+) *AidedWebService {
+	return &AidedWebService{
 		Service:                 service,
 		webForwardingRepository: webForwardingRepository,
 		wafformatter:            wafformatter,
@@ -106,7 +58,7 @@ func NewAidedWebService(
 	}
 }
 
-type aidedWebService struct {
+type AidedWebService struct {
 	*service.Service
 	webForwardingRepository waf.WebForwardingRepository
 	wafformatter            common.WafFormatterService
@@ -126,7 +78,7 @@ const (
 	isHttp        = 0
 	protocolHttps = "https"
 	protocolHttp  = "http"
-	
+
 	// 默认配置常量
 	defaultNodeClusterId = 2
 	proxyProtocolVersion = 1
@@ -136,7 +88,7 @@ const (
 
 // BuildWebForwardingModel 辅助函数,用于构建通用的 WebForwarding 模型
 // ruleId 是从 WAF 系统获取的 ID
-func (s *aidedWebService) BuildWebForwardingModel(req *v1.WebForwardingDataRequest, ruleId int, require common.RequireResponse) *model.WebForwarding {
+func (s *AidedWebService) BuildWebForwardingModel(req *v1.WebForwardingDataRequest, ruleId int, require common.RequireResponse) *model.WebForwarding {
 	return &model.WebForwarding{
 		HostId:          require.HostId,
 		CdnWebId:        ruleId,
@@ -159,7 +111,7 @@ func (s *aidedWebService) BuildWebForwardingModel(req *v1.WebForwardingDataReque
 }
 
 // BuildWebRuleModel 构建WebForwardingRule模型
-func (s *aidedWebService) BuildWebRuleModel(reqData *v1.WebForwardingDataRequest, require common.RequireResponse, localDbId int, cdnOriginIds map[string]int64) *model.WebForwardingRule {
+func (s *AidedWebService) BuildWebRuleModel(reqData *v1.WebForwardingDataRequest, require common.RequireResponse, localDbId int, cdnOriginIds map[string]int64) *model.WebForwardingRule {
 	return &model.WebForwardingRule{
 		Uid:          require.Uid,
 		HostId:       require.HostId,
@@ -170,7 +122,7 @@ func (s *aidedWebService) BuildWebRuleModel(reqData *v1.WebForwardingDataRequest
 }
 
 // getRequire 获取前置配置
-func (s *aidedWebService) getRequire (ctx context.Context, req *v1.WebForwardingRequest) (common.RequireResponse, error) {
+func (s *AidedWebService) getRequire (ctx context.Context, req *v1.WebForwardingRequest) (common.RequireResponse, error) {
 	// 1. 获取基础配置
 	require, err := s.wafformatter.Require(ctx, v1.GlobalRequire{
 		HostId:  req.HostId,
@@ -190,7 +142,7 @@ func (s *aidedWebService) getRequire (ctx context.Context, req *v1.WebForwarding
 
 // PrepareWafData 准备WAF数据
 // 职责:协调整个流程,负责获取前置配置和组装最终的 formData。
-func (s *aidedWebService) PrepareWafData(ctx context.Context, req *v1.WebForwardingRequest) (common.RequireResponse, v1.Website, error) {
+func (s *AidedWebService) PrepareWafData(ctx context.Context, req *v1.WebForwardingRequest) (common.RequireResponse, v1.Website, error) {
 
 	// 1. 获取前置配置
 	require, err := s.getRequire(ctx, req)
@@ -246,7 +198,7 @@ func (s *aidedWebService) PrepareWafData(ctx context.Context, req *v1.WebForward
 }
 
 
-func (s *aidedWebService) buildSslPolicy(ctx context.Context, data *v1.WebForwardingDataRequest) (v1.SslPolicyRef, error) {
+func (s *AidedWebService) buildSslPolicy(ctx context.Context, data *v1.WebForwardingDataRequest) (v1.SslPolicyRef, error) {
 	// 如果不是 HTTPS,直接返回关闭状态的 SSL 策略
 	if data.IsHttps != isHttps {
 		return v1.SslPolicyRef{
@@ -276,7 +228,7 @@ func (s *aidedWebService) buildSslPolicy(ctx context.Context, data *v1.WebForwar
 
 // BuildProxyConfig 构建代理配置
 // 职责:专门负责处理 HTTP/HTTPS 的差异,并生成对应的 JSON 配置。
-func (s *aidedWebService) BuildProxyConfig(ctx context.Context, req *v1.WebForwardingRequest, gatewayIps []string) (v1.TypeJSON, error) {
+func (s *AidedWebService) BuildProxyConfig(ctx context.Context, req *v1.WebForwardingRequest, gatewayIps []string) (v1.TypeJSON, error) {
 	// 第一步:构建 SSL 策略。所有复杂的 if/else 都被封装在辅助函数中
 	sslPolicy, err := s.buildSslPolicy(ctx, &req.WebForwardingData)
 	if err != nil {
@@ -314,132 +266,11 @@ func (s *aidedWebService) BuildProxyConfig(ctx context.Context, req *v1.WebForwa
 	return jsonData, nil
 }
 
-// FindDifferenceList 查找两个列表的差异
-func (s *aidedWebService) FindDifferenceList(oldList, newList []v1.BackendList) (added, removed []v1.BackendList) {
-	diff := make(map[v1.BackendList]int)
-
-	// 1. 遍历旧列表,为每个元素计数 +1
-	for _, item := range oldList {
-		diff[item]++
-	}
-
-	// 2. 遍历新列表,为每个元素计数 -1
-	for _, item := range newList {
-		diff[item]--
-	}
-
-	// 3. 遍历 diff map 来找出差异
-	for item, count := range diff {
-		if count > 0 {
-			// 如果 count > 0,说明这个元素在 oldList 中但不在 newList 中
-			removed = append(removed, item)
-		} else if count < 0 {
-			// 如果 count < 0,说明这个元素在 newList 中但不在 oldList 中
-			added = append(added, item)
-		}
-		// 如果 count == 0,说明元素在两个列表中都存在,不做任何操作
-	}
-
-	return added, removed
-}
-
-// WashDifferentIp 清洗IP差异 - 并发版本
-func (s *aidedWebService) WashDifferentIp(newIpList []string, oldIpList []string) (addedDenyIps []string, removedDenyIps []string) {
-	// 并发验证并过滤有效IP
-	oldAllowIps := s.filterValidIpsConcurrently(oldIpList)
-	newAllowIps := s.filterValidIpsConcurrently(newIpList)
-
-	addedDenyIps, removedDenyIps = s.wafformatter.FindIpDifferences(oldAllowIps, newAllowIps)
-	return addedDenyIps, removedDenyIps
-}
-
-// filterValidIpsConcurrently 并发过滤有效IP地址
-func (s *aidedWebService) filterValidIpsConcurrently(ipList []string) []string {
-	if len(ipList) == 0 {
-		return nil
-	}
-
-	// 小于10个IP时不使用并发,避免overhead
-	if len(ipList) < 10 {
-		return s.filterValidIpsSequentially(ipList)
-	}
-
-	type ipResult struct {
-		ip    string
-		valid bool
-		index int
-	}
-
-	resultChan := make(chan ipResult, len(ipList))
-	semaphore := make(chan struct{}, 20) // 限制并发数为20
-
-	// 启动goroutine验证IP
-	for i, ip := range ipList {
-		go func(ip string, index int) {
-			semaphore <- struct{}{} // 获取信号量
-			defer func() { <-semaphore }() // 释放信号量
-
-			valid := net.ParseIP(ip) != nil
-			resultChan <- ipResult{ip: ip, valid: valid, index: index}
-		}(ip, i)
-	}
-
-	// 收集结果并保持原始顺序
-	results := make([]ipResult, len(ipList))
-	for i := 0; i < len(ipList); i++ {
-		result := <-resultChan
-		results[result.index] = result
-	}
-	close(resultChan)
-
-	// 按原始顺序提取有效IP
-	var validIps []string
-	for _, result := range results {
-		if result.valid {
-			validIps = append(validIps, result.ip)
-		}
-	}
-
-	return validIps
-}
-
-// filterValidIpsSequentially 顺序过滤有效IP地址(用于小数据集)
-func (s *aidedWebService) filterValidIpsSequentially(ipList []string) []string {
-	var validIps []string
-	for _, ip := range ipList {
-		if net.ParseIP(ip) != nil {
-			validIps = append(validIps, ip)
-		}
-	}
-	return validIps
-}
 
-// EditLog 修改日志配置
-func (s *aidedWebService) EditLog(ctx context.Context, webId int64) error {
-	webConfigId, err := s.webForwardingRepository.GetWebConfigId(ctx, webId)
-	if err != nil {
-		return err
-	}
 
-	if err := s.cdn.EditWebLog(ctx, webConfigId, v1.WebLog{
-		IsPrior:            false,
-		IsOn:               true,
-		Fields:             []int64{1, 2, 6, 7},
-		Status1:            true,
-		Status2:            true,
-		Status3:            true,
-		Status4:            true,
-		Status5:            true,
-		FirewallOnly:       false,
-		EnableClientClosed: false,
-	}); err != nil {
-		return err
-	}
-	return nil
-}
 
 // BulidFormData 构建表单数据
-func (s *aidedWebService) BulidFormData(ctx context.Context, formData v1.Website) (v1.WebsiteSend, error) {
+func (s *AidedWebService) BulidFormData(ctx context.Context, formData v1.Website) (v1.WebsiteSend, error) {
 	httpJSON, err := json.Marshal(formData.HttpJSON)
 	if err != nil {
 		return v1.WebsiteSend{}, err
@@ -472,60 +303,12 @@ func (s *aidedWebService) BulidFormData(ctx context.Context, formData v1.Website
 }
 
 
-// ProcessSSLCertificate 处理SSL证书
-func (s *aidedWebService) ProcessSSLCertificate(ctx context.Context, req *v1.WebForwardingRequest, cdnUid int) error {
-	if !s.IsHttpsProtocol(req.WebForwardingData.IsHttps) {
-		return nil // 非HTTPS协议不需要处理SSL证书
-	}
-
-	// 添加SSL证书
-	sslCertId, err := s.sslCert.AddSSLCert(ctx, v1.SSL{
-		Name:        req.WebForwardingData.Domain,
-		Domain:      req.WebForwardingData.Domain,
-		CertData:    req.WebForwardingData.HttpsCert,
-		KeyData:     req.WebForwardingData.HttpsKey,
-		CdnUserId:   cdnUid,
-		Description: req.WebForwardingData.Comment,
-	})
-	if err != nil {
-		return fmt.Errorf("添加SSL证书失败: %w", err)
-	}
-
-	// 更新请求中的证书ID
-	req.WebForwardingData.SslCertId = sslCertId
 
-	// 编辑SSL策略
-	if err := s.sslCert.EditSslPolicy(ctx, req.WebForwardingData.SslPolicyId, []int64{sslCertId}, "add"); err != nil {
-		return fmt.Errorf("编辑SSL策略失败: %w", err)
-	}
 
-	return nil
-}
-
-// CreateOriginServers 创建源站服务器
-func (s *aidedWebService) CreateOriginServers(ctx context.Context, req *v1.WebForwardingRequest) (map[string]int64, error) {
-	cdnOriginIds := make(map[string]int64)
-
-	for _, backend := range req.WebForwardingData.BackendList {
-		apiType := s.GetProtocolType(backend.IsHttps)
-
-		id, err := s.wafformatter.AddOrigin(ctx, v1.WebJson{
-			ApiType:     apiType,
-			BackendList: backend.Addr,
-			Host:        backend.CustomHost,
-			Comment:     req.WebForwardingData.Comment,
-		})
-		if err != nil {
-			return nil, fmt.Errorf("添加源站 %s 失败: %w", backend.Addr, err)
-		}
-		cdnOriginIds[backend.Addr] = id
-	}
 
-	return cdnOriginIds, nil
-}
 
 // GetProtocolType 获取协议类型字符串
-func (s *aidedWebService) GetProtocolType(isHttps int) string {
+func (s *AidedWebService) GetProtocolType(isHttps int) string {
 	if s.IsHttpsProtocol(isHttps) {
 		return protocolHttps
 	}
@@ -533,113 +316,24 @@ func (s *aidedWebService) GetProtocolType(isHttps int) string {
 }
 
 // IsHttpsProtocol 判断是否为HTTPS协议
-func (s *aidedWebService) IsHttpsProtocol(httpsFlag int) bool {
+func (s *AidedWebService) IsHttpsProtocol(httpsFlag int) bool {
 	return httpsFlag == isHttps
 }
 
-// ValidateAddRequest 验证添加请求
-func (s *aidedWebService) ValidateAddRequest(ctx context.Context, req *v1.WebForwardingRequest, require common.RequireResponse) error {
-	if err := s.wafformatter.ValidateWafDomainCount(ctx, v1.GlobalRequire{
-		HostId:  req.HostId,
-		Domain:  req.WebForwardingData.Domain,
-		Comment: req.WebForwardingData.Comment,
-		Uid:     req.Uid,
-	}); err != nil {
-		return fmt.Errorf("域名数量验证失败: %w", err)
-	}
 
-	if err := s.wafformatter.ValidateWafPortCount(ctx, require.HostId); err != nil {
-		return fmt.Errorf("端口数量验证失败: %w", err)
-	}
 
-	protocol := s.GetProtocolType(req.WebForwardingData.IsHttps)
-	if err := s.wafformatter.VerifyPort(ctx, protocol, int64(req.WebForwardingData.Id), req.WebForwardingData.Port, int64(require.HostId), req.WebForwardingData.Domain); err != nil {
-		return fmt.Errorf("端口 %d 验证失败: %w", req.WebForwardingData.Port, err)
-	}
 
-	return nil
-}
 
-// ValidateEditRequest 验证编辑请求
-func (s *aidedWebService) ValidateEditRequest(ctx context.Context, req *v1.WebForwardingRequest) error {
-	if err := s.wafformatter.ValidateWafDomainCount(ctx, v1.GlobalRequire{
-		HostId:  req.HostId,
-		Domain:  req.WebForwardingData.Domain,
-		Comment: req.WebForwardingData.Comment,
-		Uid:     req.Uid,
-	}); err != nil {
-		return fmt.Errorf("域名数量验证失败: %w", err)
-	}
-
-	protocol := s.GetProtocolType(req.WebForwardingData.IsHttps)
-	if err := s.wafformatter.VerifyPort(ctx, protocol, int64(req.WebForwardingData.Id), req.WebForwardingData.Port, int64(req.HostId), req.WebForwardingData.Domain); err != nil {
-		return fmt.Errorf("端口 %d 验证失败: %w", req.WebForwardingData.Port, err)
-	}
-
-	return nil
-}
 
-// ValidateDeletePermission 验证删除权限
-func (s *aidedWebService) ValidateDeletePermission(oldHostId int, hostId int) error {
-	if oldHostId != hostId {
-		return fmt.Errorf("用户权限不足")
-	}
-	return nil
-}
-
-// CreateCdnWebsite 创建CDN网站
-func (s *aidedWebService) CreateCdnWebsite(ctx context.Context, formData v1.Website) (int64, error) {
-	formDataSend, err := s.BulidFormData(ctx, formData)
-	if err != nil {
-		return 0, fmt.Errorf("构建表单数据失败: %w", err)
-	}
-
-	webId, err := s.cdn.CreateWebsite(ctx, formDataSend)
-	if err != nil {
-		return 0, fmt.Errorf("创建CDN网站失败: %w", err)
-	}
 
-	return webId, nil
-}
 
-// UpdateCdnConfiguration 更新CDN配置
-func (s *aidedWebService) UpdateCdnConfiguration(ctx context.Context, req *v1.WebForwardingRequest, oldData *model.WebForwarding, tag string, formData v1.Website) error {
-	// 修改网站端口、协议或证书
-	if oldData.Port != req.WebForwardingData.Port || oldData.IsHttps != req.WebForwardingData.IsHttps || 
-		oldData.HttpsCert != req.WebForwardingData.HttpsCert || oldData.HttpsKey != req.WebForwardingData.HttpsKey {
-		
-		if err := s.updateWebsiteProtocolAndCert(ctx, req.WebForwardingData.IsHttps, int64(oldData.CdnWebId), formData); err != nil {
-			return err
-		}
-	}
 
-	// 修改网站域名
-	if oldData.Domain != req.WebForwardingData.Domain {
-		if err := s.updateWebsiteDomain(ctx, req.WebForwardingData.Domain, int64(oldData.CdnWebId)); err != nil {
-			return err
-		}
-	}
 
-	// 修改网站名字
-	if oldData.Comment != req.WebForwardingData.Comment {
-		if err := s.updateWebsiteBasicInfo(ctx, int64(oldData.CdnWebId), tag); err != nil {
-			return err
-		}
-	}
 
-	return nil
-}
 
-// DeleteCdnServer 删除CDN服务器
-func (s *aidedWebService) DeleteCdnServer(ctx context.Context, cdnWebId int) error {
-	if err := s.cdn.DelServer(ctx, int64(cdnWebId)); err != nil {
-		return fmt.Errorf("删除CDN服务器失败: %w", err)
-	}
-	return nil
-}
 
 // updateWebsiteProtocolAndCert 更新网站协议和证书
-func (s *aidedWebService) updateWebsiteProtocolAndCert(ctx context.Context, isHttps int, cdnWebId int64,  formData v1.Website) error {
+func (s *AidedWebService) updateWebsiteProtocolAndCert(ctx context.Context, isHttps int, cdnWebId int64,  formData v1.Website) error {
 
 
 	// 切换协议
@@ -686,7 +380,7 @@ func (s *aidedWebService) updateWebsiteProtocolAndCert(ctx context.Context, isHt
 }
 
 // updateWebsiteDomain 更新网站域名
-func (s *aidedWebService) updateWebsiteDomain(ctx context.Context, domain string, cdnWebId int64) error {
+func (s *AidedWebService) updateWebsiteDomain(ctx context.Context, domain string, cdnWebId int64) error {
 	type serverName struct {
 		Name string `json:"name" form:"name"`
 		Type string `json:"type" form:"type"`
@@ -712,7 +406,7 @@ func (s *aidedWebService) updateWebsiteDomain(ctx context.Context, domain string
 }
 
 // updateWebsiteBasicInfo 更新网站基本信息
-func (s *aidedWebService) updateWebsiteBasicInfo(ctx context.Context, cdnWebId int64, tag string) error {
+func (s *AidedWebService) updateWebsiteBasicInfo(ctx context.Context, cdnWebId int64, tag string) error {
 	// 通过globalLimitRep获取节点ID,这是项目中现有的方法
 	nodeId, err := s.globalLimitRep.GetNodeId(ctx, int(cdnWebId))
 	if err != nil {
@@ -726,378 +420,11 @@ func (s *aidedWebService) updateWebsiteBasicInfo(ctx context.Context, cdnWebId i
 	return nil
 }
 
-// AddOriginsToWebsite 添加源站到网站
-func (s *aidedWebService) AddOriginsToWebsite(ctx context.Context, req *v1.WebForwardingRequest, webId int64) (map[string]int64, error) {
-	cdnOriginIds, err := s.CreateOriginServers(ctx, req)
-	if err != nil {
-		return nil, fmt.Errorf("创建源站服务器失败: %w", err)
-	}
 
-	// 添加源站到网站
-	for _, originId := range cdnOriginIds {
-		if err := s.cdn.AddServerOrigin(ctx, webId, originId); err != nil {
-			return nil, fmt.Errorf("添加源站到网站失败: %w", err)
-		}
-	}
 
-	return cdnOriginIds, nil
-}
 
-// UpdateOriginServers 更新源站服务器
-func (s *aidedWebService) UpdateOriginServers(ctx context.Context, req *v1.WebForwardingRequest, oldData *model.WebForwarding, ipData *model.WebForwardingRule) error {
-	addOrigins, delOrigins := s.FindDifferenceList(ipData.BackendList, req.WebForwardingData.BackendList)
-	addedIds := make(map[string]int64)
-
-	// 添加新源站
-	for _, v := range addOrigins {
-		apiType := s.GetProtocolType(v.IsHttps)
-		id, err := s.wafformatter.AddOrigin(ctx, v1.WebJson{
-			ApiType:     apiType,
-			BackendList: v.Addr,
-			Host:        v.CustomHost,
-			Comment:     req.WebForwardingData.Comment,
-		})
-		if err != nil {
-			return fmt.Errorf("添加源站 %s 失败: %w", v.Addr, err)
-		}
-		addedIds[v.Addr] = id
-	}
 
-	// 将新源站添加到网站
-	for _, v := range addedIds {
-		if err := s.cdn.AddServerOrigin(ctx, int64(oldData.CdnWebId), v); err != nil {
-			return fmt.Errorf("添加源站到网站失败: %w", err)
-		}
-	}
 
-	// 删除旧源站
-	for k, v := range ipData.CdnOriginIds {
-		for _, ip := range delOrigins {
-			if k == ip.Addr {
-				if err := s.cdn.DelServerOrigin(ctx, int64(oldData.CdnWebId), v); err != nil {
-					return fmt.Errorf("删除源站失败: %w", err)
-				}
-				delete(ipData.CdnOriginIds, k)
-			}
-		}
-	}
 
-	// 合并新的源站ID
-	for k, v := range addedIds {
-		ipData.CdnOriginIds[k] = v
-	}
 
-	return nil
-}
-
-// ConfigureWebsocket 配置WebSocket
-func (s *aidedWebService) ConfigureWebsocket(ctx context.Context, webId int64) error {
-	websocketId, err := s.websocket.AddWebsocket(ctx)
-	if err != nil {
-		return fmt.Errorf("添加WebSocket失败: %w", err)
-	}
 
-	if err := s.websocket.EnableOrDisable(ctx, webId, websocketId, true, false); err != nil {
-		return fmt.Errorf("启用WebSocket失败: %w", err)
-	}
-
-	return nil
-}
-
-// ConfigureProxyProtocol 配置代理协议
-func (s *aidedWebService) ConfigureProxyProtocol(ctx context.Context, proxy bool, cdnWebId int64) error {
-	if err := s.proxy.EditProxy(ctx, cdnWebId, v1.ProxyProtocolJSON{
-		IsOn:    proxy,
-		Version: proxyProtocolVersion,
-	}); err != nil {
-		return fmt.Errorf("启用代理协议失败: %w", err)
-	}
-	return nil
-}
-
-// ConfigureCCProtection 配置CC防护
-func (s *aidedWebService) ConfigureCCProtection(ctx context.Context, ccConfig v1.CcConfigRequest, webId int64) error {
-	if err := s.cc.EditCcConfig(ctx, webId, ccConfig); err != nil {
-		return fmt.Errorf("配置CC防护失败: %w", err)
-	}
-	return nil
-}
-
-// ConfigureWafFirewall 配置WAF防火墙
-func (s *aidedWebService) ConfigureWafFirewall(ctx context.Context, webId int64, groupId int) error {
-	if err := s.ccIpList.AddCcIpListPolicy(ctx, webId, int64(groupId)); err != nil {
-		return fmt.Errorf("配置WAF防火墙失败: %w", err)
-	}
-	return nil
-}
-
-// ProcessAsyncTasks 处理异步任务
-func (s *aidedWebService) ProcessAsyncTasks(ctx context.Context, req *v1.WebForwardingRequest, require common.RequireResponse) {
-	// 域名白名单处理
-	if req.WebForwardingData.Domain != "" {
-		go func() {
-			doMain, err := s.wafformatter.ConvertToWildcardDomain(ctx, req.WebForwardingData.Domain)
-			if err != nil {
-				return
-			}
-			if len(require.GatewayIps) == 0 {
-				return
-			}
-			firstIp, err := s.gatewayIp.GetGatewayipByHostIdFirst(ctx, int64(require.HostId), int64(require.Uid))
-			if err != nil {
-				return
-			}
-			s.wafformatter.PublishDomainWhitelistTask(doMain, firstIp, "add")
-		}()
-	}
-
-	// 源站IP白名单处理
-	if req.WebForwardingData.BackendList != nil {
-		go func() {
-			var ips []string
-			for _, v := range req.WebForwardingData.BackendList {
-				ip, _, err := net.SplitHostPort(v.Addr)
-				if err != nil {
-					continue
-				}
-				ips = append(ips, ip)
-			}
-			if len(ips) > 0 {
-				s.wafformatter.PublishIpWhitelistTask(ips, "add", "", "white")
-			}
-		}()
-	}
-}
-
-// ProcessIpWhitelistChanges 处理IP白名单变更
-func (s *aidedWebService) ProcessIpWhitelistChanges(ctx context.Context, req *v1.WebForwardingRequest, ipData *model.WebForwardingRule) error {
-	var oldIps, newIps []string
-
-	// 提取旧IP列表
-	for _, v := range ipData.BackendList {
-		ip, _, err := net.SplitHostPort(v.Addr)
-		if err != nil {
-			return fmt.Errorf("解析旧IP地址失败: %w", err)
-		}
-		oldIps = append(oldIps, ip)
-	}
-
-	// 提取新IP列表
-	for _, v := range req.WebForwardingData.BackendList {
-		ip, _, err := net.SplitHostPort(v.Addr)
-		if err != nil {
-			return fmt.Errorf("解析新IP地址失败: %w", err)
-		}
-		newIps = append(newIps, ip)
-	}
-
-	// 查找IP差异
-	addedIps, removedIps := s.wafformatter.FindIpDifferences(oldIps, newIps)
-
-	// 异步处理添加的IP
-	if len(addedIps) > 0 {
-		go s.wafformatter.PublishIpWhitelistTask(addedIps, "add", "", "white")
-	}
-
-	// 异步处理删除的IP
-	if len(removedIps) > 0 {
-		go func() {
-			ipsToDelist, err := s.wafformatter.WashDelIps(ctx, removedIps)
-			if err != nil {
-				return
-			}
-			if len(ipsToDelist) > 0 {
-				s.wafformatter.PublishIpWhitelistTask(ipsToDelist, "del", "0", "white")
-			}
-		}()
-	}
-
-	return nil
-}
-
-// ProcessDeleteIpWhitelist 处理删除IP白名单
-func (s *aidedWebService) ProcessDeleteIpWhitelist(ctx context.Context, id int) error {
-	ipData, err := s.webForwardingRepository.GetWebForwardingIpsByID(ctx, id)
-	if err != nil {
-		return fmt.Errorf("获取IP数据失败: %w", err)
-	}
-
-	if ipData != nil && len(ipData.BackendList) > 0 {
-		var ips []string
-		for _, v := range ipData.BackendList {
-			ip, _, err := net.SplitHostPort(v.Addr)
-			if err != nil {
-				continue
-			}
-			ips = append(ips, ip)
-		}
-
-		if len(ips) > 0 {
-			go func() {
-				ipsToDelist, err := s.wafformatter.WashDelIps(ctx, ips)
-				if err != nil {
-					return
-				}
-				if len(ipsToDelist) > 0 {
-					s.wafformatter.PublishIpWhitelistTask(ipsToDelist, "del", "0", "white")
-				}
-			}()
-		}
-	}
-
-	return nil
-}
-
-// ProcessDomainWhitelistChanges 处理域名白名单变更
-func (s *aidedWebService) ProcessDomainWhitelistChanges(ctx context.Context, req *v1.WebForwardingRequest, oldData *model.WebForwarding, require common.RequireResponse) error {
-	if oldData.Domain != req.WebForwardingData.Domain {
-		firstIp, err := s.gatewayIp.GetGatewayipByHostIdFirst(ctx, int64(req.HostId), int64(req.Uid))
-		if err != nil {
-			return fmt.Errorf("获取网关IP失败: %w", err)
-		}
-
-		newDomain, err := s.wafformatter.ConvertToWildcardDomain(ctx, req.WebForwardingData.Domain)
-		if err != nil {
-			return fmt.Errorf("转换新域名失败: %w", err)
-		}
-
-		oldDomain, err := s.wafformatter.ConvertToWildcardDomain(ctx, oldData.Domain)
-		if err != nil {
-			return fmt.Errorf("转换旧域名失败: %w", err)
-		}
-
-		if len(require.GatewayIps) == 0 {
-			return fmt.Errorf("网关组不存在")
-		}
-
-		// 检查旧域名使用数量
-		count, err := s.webForwardingRepository.GetDomainCount(ctx, req.HostId, oldData.Domain)
-		if err != nil {
-			return fmt.Errorf("获取域名使用数量失败: %w", err)
-		}
-
-		// 异步处理域名白名单变更
-		go func() {
-			if count < 2 {
-				s.wafformatter.PublishDomainWhitelistTask(oldDomain, firstIp, "del")
-			}
-			s.wafformatter.PublishDomainWhitelistTask(newDomain, firstIp, "add")
-		}()
-	}
-
-	return nil
-}
-
-// ProcessDeleteDomainWhitelist 处理删除域名白名单
-func (s *aidedWebService) ProcessDeleteDomainWhitelist(ctx context.Context, oldData *model.WebForwarding, uid int) error {
-	if oldData.Domain != "" {
-		firstIp, err := s.gatewayIp.GetGatewayipByHostIdFirst(ctx, int64(oldData.HostId), int64(uid))
-		if err != nil {
-			return fmt.Errorf("获取网关IP失败: %w", err)
-		}
-
-		doMain, err := s.wafformatter.ConvertToWildcardDomain(ctx, oldData.Domain)
-		if err != nil {
-			return fmt.Errorf("转换域名失败: %w", err)
-		}
-
-		go s.wafformatter.PublishDomainWhitelistTask(doMain, firstIp, "del")
-	}
-
-	return nil
-}
-
-// SaveToDatabase 保存到数据库
-func (s *aidedWebService) SaveToDatabase(ctx context.Context, req *v1.WebForwardingRequest, require common.RequireResponse, webId int64, cdnOriginIds map[string]int64) (int, error) {
-	webModel := s.BuildWebForwardingModel(&req.WebForwardingData, int(webId), require)
-
-	id, err := s.webForwardingRepository.AddWebForwarding(ctx, webModel)
-	if err != nil {
-		return 0, fmt.Errorf("添加Web转发记录失败: %w", err)
-	}
-
-	webRuleModel := s.BuildWebRuleModel(&req.WebForwardingData, require, id, cdnOriginIds)
-	if _, err = s.webForwardingRepository.AddWebForwardingIps(ctx, *webRuleModel); err != nil {
-		return 0, fmt.Errorf("添加Web转发规则失败: %w", err)
-	}
-
-	return id, nil
-}
-
-// UpdateDatabaseRecords 更新数据库记录
-func (s *aidedWebService) UpdateDatabaseRecords(ctx context.Context, req *v1.WebForwardingRequest, require common.RequireResponse, ipData *model.WebForwardingRule) error {
-	webModel := s.BuildWebForwardingModel(&req.WebForwardingData, req.WebForwardingData.CdnWebId, require)
-	webModel.Id = req.WebForwardingData.Id
-
-	if err := s.webForwardingRepository.EditWebForwarding(ctx, webModel); err != nil {
-		return fmt.Errorf("更新Web转发记录失败: %w", err)
-	}
-
-	webRuleModel := s.BuildWebRuleModel(&req.WebForwardingData, require, req.WebForwardingData.Id, ipData.CdnOriginIds)
-	if err := s.webForwardingRepository.EditWebForwardingIps(ctx, *webRuleModel); err != nil {
-		return fmt.Errorf("更新Web转发规则失败: %w", err)
-	}
-
-	return nil
-}
-
-// CleanupDatabaseRecords 清理数据库记录
-func (s *aidedWebService) CleanupDatabaseRecords(ctx context.Context, id int) error {
-	if err := s.webForwardingRepository.DeleteWebForwarding(ctx, int64(id)); err != nil {
-		return fmt.Errorf("删除Web转发记录失败: %w", err)
-	}
-
-	if err := s.webForwardingRepository.DeleteWebForwardingIpsById(ctx, id); err != nil {
-		return fmt.Errorf("删除Web转发规则失败: %w", err)
-	}
-
-	return nil
-}
-
-// ProcessSSLCertificateUpdate 处理SSL证书更新
-func (s *aidedWebService) ProcessSSLCertificateUpdate(ctx context.Context, req *v1.WebForwardingRequest, oldData *model.WebForwarding, cdnUid int) error {
-	if !s.IsHttpsProtocol(req.WebForwardingData.IsHttps) {
-		return nil // 非HTTPS协议不需要处理SSL证书
-	}
-
-	// 如果证书ID为0
-	if oldData.SslCertId == 0 {
-		err := s.ProcessSSLCertificate(ctx, req, cdnUid)
-		if err != nil {
-			return fmt.Errorf("处理SSL证书失败: %w", err)
-		}
-		return nil
-	}
-
-	// 如果证书内容有变化
-	if oldData.HttpsCert != req.WebForwardingData.HttpsCert || oldData.HttpsKey != req.WebForwardingData.HttpsKey {
-		if err := s.sslCert.EditSSLCert(ctx, v1.SSL{
-			Name:        req.WebForwardingData.Domain,
-			CertId:      oldData.SslCertId,
-			CertData:    req.WebForwardingData.HttpsCert,
-			KeyData:     req.WebForwardingData.HttpsKey,
-			CdnUserId:   cdnUid,
-			Domain:      req.WebForwardingData.Domain,
-			Description: req.WebForwardingData.Comment,
-		}); err != nil {
-			return fmt.Errorf("更新SSL证书失败: %w", err)
-		}
-	}
-
-	return nil
-}
-
-// CleanupSSLCertificate 清理SSL证书
-func (s *aidedWebService) CleanupSSLCertificate(ctx context.Context, oldData *model.WebForwarding) error {
-	if oldData.SslCertId != 0 {
-		if err := s.cdn.DelSSLCert(ctx, int64(oldData.SslCertId)); err != nil {
-			return fmt.Errorf("删除SSL证书失败: %w", err)
-		}
-
-		if err := s.sslCert.EditSslPolicy(ctx, int64(oldData.SslPolicyId), []int64{int64(oldData.SslCertId)}, "del"); err != nil {
-			return fmt.Errorf("删除SSL策略失败: %w", err)
-		}
-	}
-
-	return nil
-}

+ 61 - 0
internal/service/api/waf/web/cdnweb.go

@@ -0,0 +1,61 @@
+package web
+
+import (
+	"context"
+	"fmt"
+	v1 "github.com/go-nunu/nunu-layout-advanced/api/v1"
+	"github.com/go-nunu/nunu-layout-advanced/internal/model"
+)
+
+// CreateCdnWebsite 创建CDN网站
+func (s *AidedWebService) CreateCdnWebsite(ctx context.Context, formData v1.Website) (int64, error) {
+	formDataSend, err := s.BulidFormData(ctx, formData)
+	if err != nil {
+		return 0, fmt.Errorf("构建表单数据失败: %w", err)
+	}
+
+	webId, err := s.cdn.CreateWebsite(ctx, formDataSend)
+	if err != nil {
+		return 0, fmt.Errorf("创建CDN网站失败: %w", err)
+	}
+
+	return webId, nil
+}
+
+
+// UpdateCdnConfiguration 更新CDN配置
+func (s *AidedWebService) UpdateCdnConfiguration(ctx context.Context, req *v1.WebForwardingRequest, oldData *model.WebForwarding, tag string, formData v1.Website) error {
+	// 修改网站端口、协议或证书
+	if oldData.Port != req.WebForwardingData.Port || oldData.IsHttps != req.WebForwardingData.IsHttps ||
+		oldData.HttpsCert != req.WebForwardingData.HttpsCert || oldData.HttpsKey != req.WebForwardingData.HttpsKey {
+
+		if err := s.updateWebsiteProtocolAndCert(ctx, req.WebForwardingData.IsHttps, int64(oldData.CdnWebId), formData); err != nil {
+			return err
+		}
+	}
+
+	// 修改网站域名
+	if oldData.Domain != req.WebForwardingData.Domain {
+		if err := s.updateWebsiteDomain(ctx, req.WebForwardingData.Domain, int64(oldData.CdnWebId)); err != nil {
+			return err
+		}
+	}
+
+	// 修改网站名字
+	if oldData.Comment != req.WebForwardingData.Comment {
+		if err := s.updateWebsiteBasicInfo(ctx, int64(oldData.CdnWebId), tag); err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
+
+// DeleteCdnServer 删除CDN服务器
+func (s *AidedWebService) DeleteCdnServer(ctx context.Context, cdnWebId int) error {
+	if err := s.cdn.DelServer(ctx, int64(cdnWebId)); err != nil {
+		return fmt.Errorf("删除CDN服务器失败: %w", err)
+	}
+	return nil
+}

+ 48 - 0
internal/service/api/waf/web/configure.go

@@ -0,0 +1,48 @@
+package web
+
+import (
+	"context"
+	"fmt"
+	v1 "github.com/go-nunu/nunu-layout-advanced/api/v1"
+)
+
+// ConfigureWebsocket 配置WebSocket
+func (s *AidedWebService) ConfigureWebsocket(ctx context.Context, webId int64) error {
+	websocketId, err := s.websocket.AddWebsocket(ctx)
+	if err != nil {
+		return fmt.Errorf("添加WebSocket失败: %w", err)
+	}
+
+	if err := s.websocket.EnableOrDisable(ctx, webId, websocketId, true, false); err != nil {
+		return fmt.Errorf("启用WebSocket失败: %w", err)
+	}
+
+	return nil
+}
+
+// ConfigureProxyProtocol 配置代理协议
+func (s *AidedWebService) ConfigureProxyProtocol(ctx context.Context, proxy bool, cdnWebId int64) error {
+	if err := s.proxy.EditProxy(ctx, cdnWebId, v1.ProxyProtocolJSON{
+		IsOn:    proxy,
+		Version: proxyProtocolVersion,
+	}); err != nil {
+		return fmt.Errorf("启用代理协议失败: %w", err)
+	}
+	return nil
+}
+
+// ConfigureCCProtection 配置CC防护
+func (s *AidedWebService) ConfigureCCProtection(ctx context.Context, ccConfig v1.CcConfigRequest, webId int64) error {
+	if err := s.cc.EditCcConfig(ctx, webId, ccConfig); err != nil {
+		return fmt.Errorf("配置CC防护失败: %w", err)
+	}
+	return nil
+}
+
+// ConfigureWafFirewall 配置WAF防火墙
+func (s *AidedWebService) ConfigureWafFirewall(ctx context.Context, webId int64, groupId int) error {
+	if err := s.ccIpList.AddCcIpListPolicy(ctx, webId, int64(groupId)); err != nil {
+		return fmt.Errorf("配置WAF防火墙失败: %w", err)
+	}
+	return nil
+}

+ 57 - 0
internal/service/api/waf/web/database.go

@@ -0,0 +1,57 @@
+package web
+
+import (
+	"context"
+	"fmt"
+	v1 "github.com/go-nunu/nunu-layout-advanced/api/v1"
+	"github.com/go-nunu/nunu-layout-advanced/internal/model"
+	"github.com/go-nunu/nunu-layout-advanced/internal/service/api/waf/common"
+)
+
+// SaveToDatabase 保存到数据库
+func (s *AidedWebService) SaveToDatabase(ctx context.Context, req *v1.WebForwardingRequest, require common.RequireResponse, webId int64, cdnOriginIds map[string]int64) (int, error) {
+	webModel := s.BuildWebForwardingModel(&req.WebForwardingData, int(webId), require)
+
+	id, err := s.webForwardingRepository.AddWebForwarding(ctx, webModel)
+	if err != nil {
+		return 0, fmt.Errorf("添加Web转发记录失败: %w", err)
+	}
+
+	webRuleModel := s.BuildWebRuleModel(&req.WebForwardingData, require, id, cdnOriginIds)
+	if _, err = s.webForwardingRepository.AddWebForwardingIps(ctx, *webRuleModel); err != nil {
+		return 0, fmt.Errorf("添加Web转发规则失败: %w", err)
+	}
+
+	return id, nil
+}
+
+// UpdateDatabaseRecords 更新数据库记录
+func (s *AidedWebService) UpdateDatabaseRecords(ctx context.Context, req *v1.WebForwardingRequest, require common.RequireResponse, ipData *model.WebForwardingRule) error {
+	webModel := s.BuildWebForwardingModel(&req.WebForwardingData, req.WebForwardingData.CdnWebId, require)
+	webModel.Id = req.WebForwardingData.Id
+
+	if err := s.webForwardingRepository.EditWebForwarding(ctx, webModel); err != nil {
+		return fmt.Errorf("更新Web转发记录失败: %w", err)
+	}
+
+	webRuleModel := s.BuildWebRuleModel(&req.WebForwardingData, require, req.WebForwardingData.Id, ipData.CdnOriginIds)
+	if err := s.webForwardingRepository.EditWebForwardingIps(ctx, *webRuleModel); err != nil {
+		return fmt.Errorf("更新Web转发规则失败: %w", err)
+	}
+
+	return nil
+}
+
+// CleanupDatabaseRecords 清理数据库记录
+func (s *AidedWebService) CleanupDatabaseRecords(ctx context.Context, id int) error {
+	if err := s.webForwardingRepository.DeleteWebForwarding(ctx, int64(id)); err != nil {
+		return fmt.Errorf("删除Web转发记录失败: %w", err)
+	}
+
+	if err := s.webForwardingRepository.DeleteWebForwardingIpsById(ctx, id); err != nil {
+		return fmt.Errorf("删除Web转发规则失败: %w", err)
+	}
+
+	return nil
+}
+

+ 107 - 0
internal/service/api/waf/web/helper.go

@@ -0,0 +1,107 @@
+package web
+
+import (
+	v1 "github.com/go-nunu/nunu-layout-advanced/api/v1"
+	"net"
+)
+
+// FindDifferenceList 查找两个列表的差异
+func (s *AidedWebService) FindDifferenceList(oldList, newList []v1.BackendList) (added, removed []v1.BackendList) {
+	diff := make(map[v1.BackendList]int)
+
+	// 1. 遍历旧列表,为每个元素计数 +1
+	for _, item := range oldList {
+		diff[item]++
+	}
+
+	// 2. 遍历新列表,为每个元素计数 -1
+	for _, item := range newList {
+		diff[item]--
+	}
+
+	// 3. 遍历 diff map 来找出差异
+	for item, count := range diff {
+		if count > 0 {
+			// 如果 count > 0,说明这个元素在 oldList 中但不在 newList 中
+			removed = append(removed, item)
+		} else if count < 0 {
+			// 如果 count < 0,说明这个元素在 newList 中但不在 oldList 中
+			added = append(added, item)
+		}
+		// 如果 count == 0,说明元素在两个列表中都存在,不做任何操作
+	}
+
+	return added, removed
+}
+
+// WashDifferentIp 清洗IP差异 - 并发版本
+func (s *AidedWebService) WashDifferentIp(newIpList []string, oldIpList []string) (addedDenyIps []string, removedDenyIps []string) {
+	// 并发验证并过滤有效IP
+	oldAllowIps := s.filterValidIpsConcurrently(oldIpList)
+	newAllowIps := s.filterValidIpsConcurrently(newIpList)
+
+	addedDenyIps, removedDenyIps = s.wafformatter.FindIpDifferences(oldAllowIps, newAllowIps)
+	return addedDenyIps, removedDenyIps
+}
+
+// filterValidIpsConcurrently 并发过滤有效IP地址
+func (s *AidedWebService) filterValidIpsConcurrently(ipList []string) []string {
+	if len(ipList) == 0 {
+		return nil
+	}
+
+	// 小于10个IP时不使用并发,避免overhead
+	if len(ipList) < 10 {
+		return s.filterValidIpsSequentially(ipList)
+	}
+
+	type ipResult struct {
+		ip    string
+		valid bool
+		index int
+	}
+
+	resultChan := make(chan ipResult, len(ipList))
+	semaphore := make(chan struct{}, 20) // 限制并发数为20
+
+	// 启动goroutine验证IP
+	for i, ip := range ipList {
+		go func(ip string, index int) {
+			semaphore <- struct{}{} // 获取信号量
+			defer func() { <-semaphore }() // 释放信号量
+
+			valid := net.ParseIP(ip) != nil
+			resultChan <- ipResult{ip: ip, valid: valid, index: index}
+		}(ip, i)
+	}
+
+	// 收集结果并保持原始顺序
+	results := make([]ipResult, len(ipList))
+	for i := 0; i < len(ipList); i++ {
+		result := <-resultChan
+		results[result.index] = result
+	}
+	close(resultChan)
+
+	// 按原始顺序提取有效IP
+	var validIps []string
+	for _, result := range results {
+		if result.valid {
+			validIps = append(validIps, result.ip)
+		}
+	}
+
+	return validIps
+}
+
+// filterValidIpsSequentially 顺序过滤有效IP地址(用于小数据集)
+func (s *AidedWebService) filterValidIpsSequentially(ipList []string) []string {
+	var validIps []string
+	for _, ip := range ipList {
+		if net.ParseIP(ip) != nil {
+			validIps = append(validIps, ip)
+		}
+	}
+	return validIps
+}
+

+ 30 - 0
internal/service/api/waf/web/log.go

@@ -0,0 +1,30 @@
+package web
+
+import (
+	"context"
+	v1 "github.com/go-nunu/nunu-layout-advanced/api/v1"
+)
+
+// EditLog 修改日志配置
+func (s *AidedWebService) EditLog(ctx context.Context, webId int64) error {
+	webConfigId, err := s.webForwardingRepository.GetWebConfigId(ctx, webId)
+	if err != nil {
+		return err
+	}
+
+	if err := s.cdn.EditWebLog(ctx, webConfigId, v1.WebLog{
+		IsPrior:            false,
+		IsOn:               true,
+		Fields:             []int64{1, 2, 6, 7},
+		Status1:            true,
+		Status2:            true,
+		Status3:            true,
+		Status4:            true,
+		Status5:            true,
+		FirewallOnly:       false,
+		EnableClientClosed: false,
+	}); err != nil {
+		return err
+	}
+	return nil
+}

+ 95 - 0
internal/service/api/waf/web/origin.go

@@ -0,0 +1,95 @@
+package web
+
+import (
+	"context"
+	"fmt"
+	v1 "github.com/go-nunu/nunu-layout-advanced/api/v1"
+	"github.com/go-nunu/nunu-layout-advanced/internal/model"
+)
+
+// CreateOriginServers 创建源站服务器
+func (s *AidedWebService) CreateOriginServers(ctx context.Context, req *v1.WebForwardingRequest) (map[string]int64, error) {
+	cdnOriginIds := make(map[string]int64)
+
+	for _, backend := range req.WebForwardingData.BackendList {
+		apiType := s.GetProtocolType(backend.IsHttps)
+
+		id, err := s.wafformatter.AddOrigin(ctx, v1.WebJson{
+			ApiType:     apiType,
+			BackendList: backend.Addr,
+			Host:        backend.CustomHost,
+			Comment:     req.WebForwardingData.Comment,
+		})
+		if err != nil {
+			return nil, fmt.Errorf("添加源站 %s 失败: %w", backend.Addr, err)
+		}
+		cdnOriginIds[backend.Addr] = id
+	}
+
+	return cdnOriginIds, nil
+}
+
+
+// AddOriginsToWebsite 添加源站到网站
+func (s *AidedWebService) AddOriginsToWebsite(ctx context.Context, req *v1.WebForwardingRequest, webId int64) (map[string]int64, error) {
+	cdnOriginIds, err := s.CreateOriginServers(ctx, req)
+	if err != nil {
+		return nil, fmt.Errorf("创建源站服务器失败: %w", err)
+	}
+
+	// 添加源站到网站
+	for _, originId := range cdnOriginIds {
+		if err := s.cdn.AddServerOrigin(ctx, webId, originId); err != nil {
+			return nil, fmt.Errorf("添加源站到网站失败: %w", err)
+		}
+	}
+
+	return cdnOriginIds, nil
+}
+
+// UpdateOriginServers 更新源站服务器
+func (s *AidedWebService) UpdateOriginServers(ctx context.Context, req *v1.WebForwardingRequest, oldData *model.WebForwarding, ipData *model.WebForwardingRule) error {
+	addOrigins, delOrigins := s.FindDifferenceList(ipData.BackendList, req.WebForwardingData.BackendList)
+	addedIds := make(map[string]int64)
+
+	// 添加新源站
+	for _, v := range addOrigins {
+		apiType := s.GetProtocolType(v.IsHttps)
+		id, err := s.wafformatter.AddOrigin(ctx, v1.WebJson{
+			ApiType:     apiType,
+			BackendList: v.Addr,
+			Host:        v.CustomHost,
+			Comment:     req.WebForwardingData.Comment,
+		})
+		if err != nil {
+			return fmt.Errorf("添加源站 %s 失败: %w", v.Addr, err)
+		}
+		addedIds[v.Addr] = id
+	}
+
+	// 将新源站添加到网站
+	for _, v := range addedIds {
+		if err := s.cdn.AddServerOrigin(ctx, int64(oldData.CdnWebId), v); err != nil {
+			return fmt.Errorf("添加源站到网站失败: %w", err)
+		}
+	}
+
+	// 删除旧源站
+	for k, v := range ipData.CdnOriginIds {
+		for _, ip := range delOrigins {
+			if k == ip.Addr {
+				if err := s.cdn.DelServerOrigin(ctx, int64(oldData.CdnWebId), v); err != nil {
+					return fmt.Errorf("删除源站失败: %w", err)
+				}
+				delete(ipData.CdnOriginIds, k)
+			}
+		}
+	}
+
+	// 合并新的源站ID
+	for k, v := range addedIds {
+		ipData.CdnOriginIds[k] = v
+	}
+
+	return nil
+}

+ 186 - 0
internal/service/api/waf/web/process.go

@@ -0,0 +1,186 @@
+package web
+
+import (
+	"context"
+	"fmt"
+	v1 "github.com/go-nunu/nunu-layout-advanced/api/v1"
+	"github.com/go-nunu/nunu-layout-advanced/internal/model"
+	"github.com/go-nunu/nunu-layout-advanced/internal/service/api/waf/common"
+	"net"
+)
+
+// ProcessAsyncTasks 处理异步任务
+func (s *AidedWebService) ProcessAsyncTasks(ctx context.Context, req *v1.WebForwardingRequest, require common.RequireResponse) {
+	// 域名白名单处理
+	if req.WebForwardingData.Domain != "" {
+		go func() {
+			doMain, err := s.wafformatter.ConvertToWildcardDomain(ctx, req.WebForwardingData.Domain)
+			if err != nil {
+				return
+			}
+			if len(require.GatewayIps) == 0 {
+				return
+			}
+			firstIp, err := s.gatewayIp.GetGatewayipByHostIdFirst(ctx, int64(require.HostId), int64(require.Uid))
+			if err != nil {
+				return
+			}
+			s.wafformatter.PublishDomainWhitelistTask(doMain, firstIp, "add")
+		}()
+	}
+
+	// 源站IP白名单处理
+	if req.WebForwardingData.BackendList != nil {
+		go func() {
+			var ips []string
+			for _, v := range req.WebForwardingData.BackendList {
+				ip, _, err := net.SplitHostPort(v.Addr)
+				if err != nil {
+					continue
+				}
+				ips = append(ips, ip)
+			}
+			if len(ips) > 0 {
+				s.wafformatter.PublishIpWhitelistTask(ips, "add", "", "white")
+			}
+		}()
+	}
+}
+
+// ProcessIpWhitelistChanges 处理IP白名单变更
+func (s *AidedWebService) ProcessIpWhitelistChanges(ctx context.Context, req *v1.WebForwardingRequest, ipData *model.WebForwardingRule) error {
+	var oldIps, newIps []string
+
+	// 提取旧IP列表
+	for _, v := range ipData.BackendList {
+		ip, _, err := net.SplitHostPort(v.Addr)
+		if err != nil {
+			return fmt.Errorf("解析旧IP地址失败: %w", err)
+		}
+		oldIps = append(oldIps, ip)
+	}
+
+	// 提取新IP列表
+	for _, v := range req.WebForwardingData.BackendList {
+		ip, _, err := net.SplitHostPort(v.Addr)
+		if err != nil {
+			return fmt.Errorf("解析新IP地址失败: %w", err)
+		}
+		newIps = append(newIps, ip)
+	}
+
+	// 查找IP差异
+	addedIps, removedIps := s.wafformatter.FindIpDifferences(oldIps, newIps)
+
+	// 异步处理添加的IP
+	if len(addedIps) > 0 {
+		go s.wafformatter.PublishIpWhitelistTask(addedIps, "add", "", "white")
+	}
+
+	// 异步处理删除的IP
+	if len(removedIps) > 0 {
+		go func() {
+			ipsToDelist, err := s.wafformatter.WashDelIps(ctx, removedIps)
+			if err != nil {
+				return
+			}
+			if len(ipsToDelist) > 0 {
+				s.wafformatter.PublishIpWhitelistTask(ipsToDelist, "del", "0", "white")
+			}
+		}()
+	}
+
+	return nil
+}
+
+// ProcessDeleteIpWhitelist 处理删除IP白名单
+func (s *AidedWebService) ProcessDeleteIpWhitelist(ctx context.Context, id int) error {
+	ipData, err := s.webForwardingRepository.GetWebForwardingIpsByID(ctx, id)
+	if err != nil {
+		return fmt.Errorf("获取IP数据失败: %w", err)
+	}
+
+	if ipData != nil && len(ipData.BackendList) > 0 {
+		var ips []string
+		for _, v := range ipData.BackendList {
+			ip, _, err := net.SplitHostPort(v.Addr)
+			if err != nil {
+				continue
+			}
+			ips = append(ips, ip)
+		}
+
+		if len(ips) > 0 {
+			go func() {
+				ipsToDelist, err := s.wafformatter.WashDelIps(ctx, ips)
+				if err != nil {
+					return
+				}
+				if len(ipsToDelist) > 0 {
+					s.wafformatter.PublishIpWhitelistTask(ipsToDelist, "del", "0", "white")
+				}
+			}()
+		}
+	}
+
+	return nil
+}
+
+// ProcessDomainWhitelistChanges 处理域名白名单变更
+func (s *AidedWebService) ProcessDomainWhitelistChanges(ctx context.Context, req *v1.WebForwardingRequest, oldData *model.WebForwarding, require common.RequireResponse) error {
+	if oldData.Domain != req.WebForwardingData.Domain {
+		firstIp, err := s.gatewayIp.GetGatewayipByHostIdFirst(ctx, int64(req.HostId), int64(req.Uid))
+		if err != nil {
+			return fmt.Errorf("获取网关IP失败: %w", err)
+		}
+
+		newDomain, err := s.wafformatter.ConvertToWildcardDomain(ctx, req.WebForwardingData.Domain)
+		if err != nil {
+			return fmt.Errorf("转换新域名失败: %w", err)
+		}
+
+		oldDomain, err := s.wafformatter.ConvertToWildcardDomain(ctx, oldData.Domain)
+		if err != nil {
+			return fmt.Errorf("转换旧域名失败: %w", err)
+		}
+
+		if len(require.GatewayIps) == 0 {
+			return fmt.Errorf("网关组不存在")
+		}
+
+		// 检查旧域名使用数量
+		count, err := s.webForwardingRepository.GetDomainCount(ctx, req.HostId, oldData.Domain)
+		if err != nil {
+			return fmt.Errorf("获取域名使用数量失败: %w", err)
+		}
+
+		// 异步处理域名白名单变更
+		go func() {
+			if count < 2 {
+				s.wafformatter.PublishDomainWhitelistTask(oldDomain, firstIp, "del")
+			}
+			s.wafformatter.PublishDomainWhitelistTask(newDomain, firstIp, "add")
+		}()
+	}
+
+	return nil
+}
+
+// ProcessDeleteDomainWhitelist 处理删除域名白名单
+func (s *AidedWebService) ProcessDeleteDomainWhitelist(ctx context.Context, oldData *model.WebForwarding, uid int) error {
+	if oldData.Domain != "" {
+		firstIp, err := s.gatewayIp.GetGatewayipByHostIdFirst(ctx, int64(oldData.HostId), int64(uid))
+		if err != nil {
+			return fmt.Errorf("获取网关IP失败: %w", err)
+		}
+
+		doMain, err := s.wafformatter.ConvertToWildcardDomain(ctx, oldData.Domain)
+		if err != nil {
+			return fmt.Errorf("转换域名失败: %w", err)
+		}
+
+		go s.wafformatter.PublishDomainWhitelistTask(doMain, firstIp, "del")
+	}
+
+	return nil
+}

+ 87 - 0
internal/service/api/waf/web/sslcert.go

@@ -0,0 +1,87 @@
+package web
+
+import (
+	"context"
+	"fmt"
+	v1 "github.com/go-nunu/nunu-layout-advanced/api/v1"
+	"github.com/go-nunu/nunu-layout-advanced/internal/model"
+)
+
+
+// ProcessSSLCertificate 处理SSL证书
+func (s *AidedWebService) ProcessSSLCertificate(ctx context.Context, req *v1.WebForwardingRequest, cdnUid int) error {
+	if !s.IsHttpsProtocol(req.WebForwardingData.IsHttps) {
+		return nil // 非HTTPS协议不需要处理SSL证书
+	}
+
+	// 添加SSL证书
+	sslCertId, err := s.sslCert.AddSSLCert(ctx, v1.SSL{
+		Name:        req.WebForwardingData.Domain,
+		Domain:      req.WebForwardingData.Domain,
+		CertData:    req.WebForwardingData.HttpsCert,
+		KeyData:     req.WebForwardingData.HttpsKey,
+		CdnUserId:   cdnUid,
+		Description: req.WebForwardingData.Comment,
+	})
+	if err != nil {
+		return fmt.Errorf("添加SSL证书失败: %w", err)
+	}
+
+	// 更新请求中的证书ID
+	req.WebForwardingData.SslCertId = sslCertId
+
+	// 编辑SSL策略
+	if err := s.sslCert.EditSslPolicy(ctx, req.WebForwardingData.SslPolicyId, []int64{sslCertId}, "add"); err != nil {
+		return fmt.Errorf("编辑SSL策略失败: %w", err)
+	}
+
+	return nil
+}
+
+// ProcessSSLCertificateUpdate 处理SSL证书更新
+func (s *AidedWebService) ProcessSSLCertificateUpdate(ctx context.Context, req *v1.WebForwardingRequest, oldData *model.WebForwarding, cdnUid int) error {
+	if !s.IsHttpsProtocol(req.WebForwardingData.IsHttps) {
+		return nil // 非HTTPS协议不需要处理SSL证书
+	}
+
+	// 如果证书ID为0
+	if oldData.SslCertId == 0 {
+		err := s.ProcessSSLCertificate(ctx, req, cdnUid)
+		if err != nil {
+			return fmt.Errorf("处理SSL证书失败: %w", err)
+		}
+		return nil
+	}
+
+	// 如果证书内容有变化
+	if oldData.HttpsCert != req.WebForwardingData.HttpsCert || oldData.HttpsKey != req.WebForwardingData.HttpsKey {
+		if err := s.sslCert.EditSSLCert(ctx, v1.SSL{
+			Name:        req.WebForwardingData.Domain,
+			CertId:      oldData.SslCertId,
+			CertData:    req.WebForwardingData.HttpsCert,
+			KeyData:     req.WebForwardingData.HttpsKey,
+			CdnUserId:   cdnUid,
+			Domain:      req.WebForwardingData.Domain,
+			Description: req.WebForwardingData.Comment,
+		}); err != nil {
+			return fmt.Errorf("更新SSL证书失败: %w", err)
+		}
+	}
+
+	return nil
+}
+
+// CleanupSSLCertificate 清理SSL证书
+func (s *AidedWebService) CleanupSSLCertificate(ctx context.Context, oldData *model.WebForwarding) error {
+	if oldData.SslCertId != 0 {
+		if err := s.cdn.DelSSLCert(ctx, int64(oldData.SslCertId)); err != nil {
+			return fmt.Errorf("删除SSL证书失败: %w", err)
+		}
+
+		if err := s.sslCert.EditSslPolicy(ctx, int64(oldData.SslPolicyId), []int64{int64(oldData.SslCertId)}, "del"); err != nil {
+			return fmt.Errorf("删除SSL策略失败: %w", err)
+		}
+	}
+
+	return nil
+}

+ 60 - 0
internal/service/api/waf/web/valid.go

@@ -0,0 +1,60 @@
+package web
+
+import (
+	"context"
+	"fmt"
+	v1 "github.com/go-nunu/nunu-layout-advanced/api/v1"
+	"github.com/go-nunu/nunu-layout-advanced/internal/service/api/waf/common"
+)
+
+// ValidateAddRequest 验证添加请求
+func (s *AidedWebService) ValidateAddRequest(ctx context.Context, req *v1.WebForwardingRequest, require common.RequireResponse) error {
+	if err := s.wafformatter.ValidateWafDomainCount(ctx, v1.GlobalRequire{
+		HostId:  req.HostId,
+		Domain:  req.WebForwardingData.Domain,
+		Comment: req.WebForwardingData.Comment,
+		Uid:     req.Uid,
+	}); err != nil {
+		return fmt.Errorf("域名数量验证失败: %w", err)
+	}
+
+	if err := s.wafformatter.ValidateWafPortCount(ctx, require.HostId); err != nil {
+		return fmt.Errorf("端口数量验证失败: %w", err)
+	}
+
+	protocol := s.GetProtocolType(req.WebForwardingData.IsHttps)
+	if err := s.wafformatter.VerifyPort(ctx, protocol, int64(req.WebForwardingData.Id), req.WebForwardingData.Port, int64(require.HostId), req.WebForwardingData.Domain); err != nil {
+		return fmt.Errorf("端口 %d 验证失败: %w", req.WebForwardingData.Port, err)
+	}
+
+	return nil
+}
+
+
+// ValidateEditRequest 验证编辑请求
+func (s *AidedWebService) ValidateEditRequest(ctx context.Context, req *v1.WebForwardingRequest) error {
+	if err := s.wafformatter.ValidateWafDomainCount(ctx, v1.GlobalRequire{
+		HostId:  req.HostId,
+		Domain:  req.WebForwardingData.Domain,
+		Comment: req.WebForwardingData.Comment,
+		Uid:     req.Uid,
+	}); err != nil {
+		return fmt.Errorf("域名数量验证失败: %w", err)
+	}
+
+	protocol := s.GetProtocolType(req.WebForwardingData.IsHttps)
+	if err := s.wafformatter.VerifyPort(ctx, protocol, int64(req.WebForwardingData.Id), req.WebForwardingData.Port, int64(req.HostId), req.WebForwardingData.Domain); err != nil {
+		return fmt.Errorf("端口 %d 验证失败: %w", req.WebForwardingData.Port, err)
+	}
+
+	return nil
+}
+
+
+// ValidateDeletePermission 验证删除权限
+func (s *AidedWebService) ValidateDeletePermission(oldHostId int, hostId int) error {
+	if oldHostId != hostId {
+		return fmt.Errorf("用户权限不足")
+	}
+	return nil
+}

+ 2 - 2
internal/service/api/waf/web/webforwarding.go

@@ -40,7 +40,7 @@ func NewWebForwardingService(
 	websocket flexCdn.WebsocketService,
 	cc waf2.CcService,
 	ccIpList waf2.CcIpListService,
-	aidedWeb AidedWebService,
+	aidedWeb *AidedWebService,
 ) WebForwardingService {
 	return &webForwardingService{
 		Service:                 service,
@@ -81,7 +81,7 @@ type webForwardingService struct {
 	websocket flexCdn.WebsocketService
 	cc        waf2.CcService
 	ccIpList  waf2.CcIpListService
-	aidedWeb  AidedWebService
+	aidedWeb  *AidedWebService
 }