优化白名单与通道提取功能
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
## TODO
|
||||
|
||||
异常展示全部信息,只返回 bizerr 的内容,控制台打印全部 err 内容
|
||||
|
||||
|
||||
错误提示增强,展示整链路信息
|
||||
|
||||
ip 提取频率限制,在 ensure 函数加逻辑,通过 redis 或者 pg 计算分钟内提取次数,只允许每分钟提取 30 次
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package handlers
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"platform/pkg/env"
|
||||
"platform/pkg/u"
|
||||
"platform/web/auth"
|
||||
@@ -97,6 +98,18 @@ func CreateWhitelist(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
// 创建白名单
|
||||
uid := authCtx.User.ID
|
||||
err = g.Redsync.WithLock(whitelistKey(uid), func() error {
|
||||
count, err := q.Whitelist.Where(
|
||||
q.Whitelist.UserID.Eq(uid),
|
||||
).Count()
|
||||
if err != nil {
|
||||
return core.NewServErr("获取白名单数量失败", err)
|
||||
}
|
||||
if count >= 5 {
|
||||
return core.NewBizErr("白名单数量已达上限")
|
||||
}
|
||||
|
||||
err = q.Whitelist.Create(&m.Whitelist{
|
||||
UserID: authCtx.User.ID,
|
||||
IP: u.Z(ip),
|
||||
@@ -106,6 +119,12 @@ func CreateWhitelist(c *fiber.Ctx) error {
|
||||
return core.NewServErr("添加白名单失败", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -206,3 +225,7 @@ func secureAddr(str string) (*orm.Inet, error) {
|
||||
}
|
||||
return ip, nil
|
||||
}
|
||||
|
||||
func whitelistKey(userID int32) string {
|
||||
return fmt.Sprintf("platform:whitelist:add:%d", userID)
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/hibiken/asynq"
|
||||
"gorm.io/gen"
|
||||
"gorm.io/gen/field"
|
||||
)
|
||||
|
||||
@@ -87,30 +86,20 @@ func (s *channelBaiyinProvider) CreateChannels(source netip.Addr, resourceId int
|
||||
}
|
||||
|
||||
// 获取可用节点
|
||||
edgesResp, err := g.Cloud.CloudEdges(&g.CloudEdgesReq{
|
||||
Province: filter.Prov,
|
||||
City: filter.City,
|
||||
Isp: u.X(filter.Isp.String()),
|
||||
Limit: &count,
|
||||
NoRepeat: u.P(true),
|
||||
NoDayRepeat: u.P(true),
|
||||
ActiveTime: u.P(3600),
|
||||
IpUnchangedTime: u.P(3600),
|
||||
Sort: u.P("ip_unchanged_time_asc"),
|
||||
})
|
||||
secret := strings.Split(u.Z(proxy.Secret), ":")
|
||||
if len(secret) != 2 {
|
||||
return nil, core.NewServErr(fmt.Sprintf("代理 %s 密钥格式错误", proxy.IP.String()), nil)
|
||||
}
|
||||
gateway := g.NewGateway(proxy.IP.String(), secret[0], secret[1])
|
||||
edges, err := getAvailableEdges(gateway, filter, count)
|
||||
if err != nil {
|
||||
fmt.Printf("获取可用节点失败: %v\n", err)
|
||||
return nil, core.NewBizErr("获取可用节点失败", err)
|
||||
return nil, err
|
||||
}
|
||||
if edgesResp.Total != count && len(edgesResp.Edges) != count {
|
||||
return nil, core.NewBizErr("地区可用节点数量不足")
|
||||
}
|
||||
edges := edgesResp.Edges
|
||||
|
||||
// 准备通道数据
|
||||
channels := make([]*m.Channel, count)
|
||||
chanConfigs := make([]*g.PortConfigsReq, count)
|
||||
edgeConfigs := make([]string, count)
|
||||
edgeConfigs := make([]string, 0, count)
|
||||
for i := range count {
|
||||
ch := chans[i]
|
||||
edge := edges[i]
|
||||
@@ -152,7 +141,9 @@ func (s *channelBaiyinProvider) CreateChannels(source netip.Addr, resourceId int
|
||||
}
|
||||
|
||||
// 连接配置数据
|
||||
edgeConfigs[i] = edge.EdgeID
|
||||
if edge.Type == EdgeInfoCloud {
|
||||
edgeConfigs = append(edgeConfigs, edge.EdgeID)
|
||||
}
|
||||
}
|
||||
|
||||
// 提交异步任务关闭通道
|
||||
@@ -166,15 +157,13 @@ func (s *channelBaiyinProvider) CreateChannels(source netip.Addr, resourceId int
|
||||
|
||||
// 保存数据
|
||||
err = q.Q.Transaction(func(q *q.Query) error {
|
||||
var rs gen.ResultInfo
|
||||
|
||||
// 根据套餐类型和模式更新使用记录
|
||||
isShortType := resource.Type == m.ResourceTypeShort
|
||||
isLongType := resource.Type == m.ResourceTypeLong
|
||||
|
||||
switch {
|
||||
case isShortType:
|
||||
rs, err = q.ResourceShort.
|
||||
_, err = q.ResourceShort.
|
||||
Where(
|
||||
q.ResourceShort.ID.Eq(*resource.ShortId),
|
||||
q.ResourceShort.Used.Eq(resource.Used),
|
||||
@@ -187,7 +176,7 @@ func (s *channelBaiyinProvider) CreateChannels(source netip.Addr, resourceId int
|
||||
)
|
||||
|
||||
case isLongType:
|
||||
rs, err = q.ResourceLong.
|
||||
_, err = q.ResourceLong.
|
||||
Where(
|
||||
q.ResourceLong.ID.Eq(*resource.LongId),
|
||||
q.ResourceLong.Used.Eq(resource.Used),
|
||||
@@ -205,9 +194,6 @@ func (s *channelBaiyinProvider) CreateChannels(source netip.Addr, resourceId int
|
||||
if err != nil {
|
||||
return core.NewServErr("更新套餐使用记录失败", err)
|
||||
}
|
||||
if rs.RowsAffected == 0 {
|
||||
return core.NewServErr("套餐使用记录不存在")
|
||||
}
|
||||
|
||||
// 保存通道
|
||||
err = q.Channel.
|
||||
@@ -240,11 +226,6 @@ func (s *channelBaiyinProvider) CreateChannels(source netip.Addr, resourceId int
|
||||
}
|
||||
|
||||
// 提交配置
|
||||
secret := strings.Split(u.Z(proxy.Secret), ":")
|
||||
if len(secret) != 2 {
|
||||
return nil, core.NewServErr(fmt.Sprintf("代理 %s 密钥格式错误", proxy.IP.String()), nil)
|
||||
}
|
||||
gateway := g.NewGateway(proxy.IP.String(), secret[0], secret[1])
|
||||
if env.RunMode == env.RunModeProd {
|
||||
|
||||
// 连接节点到网关
|
||||
@@ -259,6 +240,7 @@ func (s *channelBaiyinProvider) CreateChannels(source netip.Addr, resourceId int
|
||||
// 启用网关代理通道
|
||||
err = gateway.GatewayPortConfigs(chanConfigs)
|
||||
if err != nil {
|
||||
slog.Warn("提交代理端口配置失败", "error", err.Error())
|
||||
return nil, core.NewServErr(fmt.Sprintf("配置代理 %s 端口失败", proxy.IP.String()), err)
|
||||
}
|
||||
} else {
|
||||
@@ -340,3 +322,70 @@ func (s *channelBaiyinProvider) RemoveChannels(batch string) error {
|
||||
slog.Debug("清除代理端口配置", "duration", time.Since(start).String())
|
||||
return nil
|
||||
}
|
||||
|
||||
func getAvailableEdges(gateway g.GatewayClient, filter *EdgeFilter, count int) ([]EdgeInfo, error) {
|
||||
edges := make([]EdgeInfo, 0, count)
|
||||
|
||||
// 先查本地
|
||||
localEdgesResp, err := gateway.GatewayEdge(&g.GatewayEdgeReq{
|
||||
Province: filter.Prov,
|
||||
City: filter.City,
|
||||
Isp: u.X(filter.Isp.String()),
|
||||
Limit: &count,
|
||||
Assigned: u.P(false),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, core.NewBizErr("获取可用节点失败", err)
|
||||
}
|
||||
|
||||
for id, _ := range localEdgesResp {
|
||||
edges = append(edges, EdgeInfo{
|
||||
Type: EdgeInfoLocal,
|
||||
EdgeID: id,
|
||||
})
|
||||
}
|
||||
if len(edges) >= count {
|
||||
return edges, nil
|
||||
}
|
||||
|
||||
// 再查云端无重复
|
||||
remaining := count - len(edges)
|
||||
cloudEdgesResp, err := g.Cloud.CloudEdges(&g.CloudEdgesReq{
|
||||
Province: filter.Prov,
|
||||
City: filter.City,
|
||||
Isp: u.X(filter.Isp.String()),
|
||||
Limit: &remaining,
|
||||
NoRepeat: u.P(true),
|
||||
ActiveTime: u.P(3600),
|
||||
IpUnchangedTime: u.P(3600),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, core.NewBizErr("获取可用节点失败", err)
|
||||
}
|
||||
|
||||
for _, edge := range cloudEdgesResp.Edges {
|
||||
edges = append(edges, EdgeInfo{
|
||||
Type: EdgeInfoCloud,
|
||||
EdgeID: edge.EdgeID,
|
||||
})
|
||||
}
|
||||
if len(edges) >= count {
|
||||
return edges, nil
|
||||
}
|
||||
|
||||
// 不能和已有的重复,如果有重复则再次查询云端补足,二次提取还有重复则放弃
|
||||
|
||||
return nil, core.NewBizErr("地区可用节点数量不足")
|
||||
}
|
||||
|
||||
type EdgeInfo struct {
|
||||
Type EdgeInfoType
|
||||
EdgeID string
|
||||
}
|
||||
|
||||
type EdgeInfoType string
|
||||
|
||||
const (
|
||||
EdgeInfoLocal EdgeInfoType = "local"
|
||||
EdgeInfoCloud EdgeInfoType = "cloud"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user