feat(proxy): 新增混合模式和中继直连模式支持

添加 RelayModeMixed、RelayModeAllDirect 和 RelayModeRandomDirect 三种中继模式
修复 README.md 中的拼写错误
更新 JWT 密钥和日志模式配置
优化流量日志查询排序
统一邮件验证码主题格式
This commit is contained in:
shanshanzhong 2025-09-01 02:22:16 -07:00
parent b16ac2cb9b
commit 602ecc31bc
6 changed files with 165 additions and 11 deletions

View File

@ -100,7 +100,7 @@ proxy services. Built with Go, it emphasizes performance, security, and scalabil
```
4. **Pull from Docker Hub** (after CI/CD publishes):
```bash
```bashw
docker pull yourusername/ppanel-server:latest
docker run --rm -p 8080:8080 yourusername/ppanel-server:latest
```

View File

@ -2,11 +2,11 @@ Host: 0.0.0.0
Port: 8080
Debug: false
JwtAuth:
AccessSecret: 1234567890
AccessSecret: e4bbdb8ca57179374c0e8a7a85038da21341aee4bdff98c0e612751d7c362cac
AccessExpire: 604800
Logger:
ServiceName: PPanel
Mode: console
Mode: file
Encoding: plain
TimeFormat: '2025-01-01 00:00:00.000'
Path: logs

View File

@ -89,7 +89,7 @@ func (l *SendEmailCodeLogic) SendEmailCode(req *types.SendCodeRequest) (resp *ty
// Generate verification code
code := random.Key(6, 0)
taskPayload.Email = req.Email
taskPayload.Subject = "Verification code"
taskPayload.Subject = "Verification Code"
content, err := l.initTemplate(req.Type, code)
if err != nil {
l.Logger.Error("[SendEmailCode]: InitTemplate Error", logger.Field("error", err.Error()))

View File

@ -9,12 +9,15 @@ import (
)
const (
RelayModeNone = "none"
RelayModeAll = "all"
RelayModeRandom = "random"
RuleGroupTypeReject = "reject"
RuleGroupTypeDefault = "default"
RuleGroupTypeDirect = "direct"
RelayModeNone = "none"
RelayModeAll = "all"
RelayModeRandom = "random"
RelayModeMixed = "mixed"
RelayModeAllDirect = "all_direct"
RelayModeRandomDirect = "random_direct"
RuleGroupTypeReject = "reject"
RuleGroupTypeDefault = "default"
RuleGroupTypeDirect = "direct"
)
type ServerFilter struct {

View File

@ -118,6 +118,6 @@ func (m *customTrafficModel) TopUsersTrafficByMonthly(ctx context.Context, date
func (m *customTrafficModel) QueryTrafficLogPageList(ctx context.Context, userId, subscribeId int64, page, size int) ([]*TrafficLog, int64, error) {
var list []*TrafficLog
var total int64
err := m.Conn.WithContext(ctx).Model(&TrafficLog{}).Where("user_id = ? and subscribe_id= ?", userId, subscribeId).Count(&total).Limit(size).Offset((page - 1) * size).Find(&list).Error
err := m.Conn.WithContext(ctx).Model(&TrafficLog{}).Where("user_id = ? and subscribe_id= ?", userId, subscribeId).Count(&total).Order("timestamp DESC").Limit(size).Offset((page - 1) * size).Find(&list).Error
return list, total, err
}

View File

@ -213,6 +213,157 @@ func adapterProxies(servers []*server.Server) ([]proxy.Proxy, []string, map[stri
}
}
proxies = append(proxies, *n)
case server.RelayModeMixed:
// 生成直连节点
n := addNode(node, node.ServerAddr, 0)
if n != nil {
directName := "直连-" + node.Name
n.Name = directName
if node.Tags != "" {
t := tool.RemoveDuplicateElements(strings.Split(node.Tags, ",")...)
for _, tag := range t {
if tag != "" {
if _, ok := tags[tag]; !ok {
tags[tag] = []string{}
}
tags[tag] = append(tags[tag], n.Name)
}
}
}
proxies = append(proxies, *n)
}
// 生成一个随机中继节点类似random模式但和直连共存
var relays []server.NodeRelay
if err := json.Unmarshal([]byte(node.RelayNode), &relays); err != nil {
logger.Errorw("Unmarshal RelayNode", logger.Field("error", err.Error()), logger.Field("node", node.Name), logger.Field("relayNode", node.RelayNode))
continue
}
if len(relays) > 0 {
randNum := random.RandomInRange(0, len(relays)-1)
relay := relays[randNum]
n := addNode(node, relay.Host, relay.Port)
if n == nil {
continue
}
relayName := "中继-" + node.Name
if relay.Prefix != "" {
relayName = relay.Prefix + node.Name
}
n.Name = relayName
if node.Tags != "" {
t := tool.RemoveDuplicateElements(strings.Split(node.Tags, ",")...)
for _, tag := range t {
if tag != "" {
if _, ok := tags[tag]; !ok {
tags[tag] = []string{}
}
tags[tag] = append(tags[tag], n.Name)
}
}
}
proxies = append(proxies, *n)
}
case server.RelayModeAllDirect:
// 生成直连节点
n := addNode(node, node.ServerAddr, 0)
if n != nil {
directName := "直连-" + node.Name
n.Name = directName
if node.Tags != "" {
t := tool.RemoveDuplicateElements(strings.Split(node.Tags, ",")...)
for _, tag := range t {
if tag != "" {
if _, ok := tags[tag]; !ok {
tags[tag] = []string{}
}
tags[tag] = append(tags[tag], n.Name)
}
}
}
proxies = append(proxies, *n)
}
// 生成所有中继节点
var relays []server.NodeRelay
if err := json.Unmarshal([]byte(node.RelayNode), &relays); err != nil {
logger.Errorw("Unmarshal RelayNode", logger.Field("error", err.Error()), logger.Field("node", node.Name), logger.Field("relayNode", node.RelayNode))
continue
}
for _, relay := range relays {
n := addNode(node, relay.Host, relay.Port)
if n == nil {
continue
}
relayName := "中继-" + node.Name
if relay.Prefix != "" {
relayName = relay.Prefix + node.Name
}
n.Name = relayName
if node.Tags != "" {
t := tool.RemoveDuplicateElements(strings.Split(node.Tags, ",")...)
for _, tag := range t {
if tag != "" {
if _, ok := tags[tag]; !ok {
tags[tag] = []string{}
}
tags[tag] = append(tags[tag], n.Name)
}
}
}
proxies = append(proxies, *n)
}
case server.RelayModeRandomDirect:
// 生成直连节点
n := addNode(node, node.ServerAddr, 0)
if n != nil {
directName := "直连-" + node.Name
n.Name = directName
if node.Tags != "" {
t := tool.RemoveDuplicateElements(strings.Split(node.Tags, ",")...)
for _, tag := range t {
if tag != "" {
if _, ok := tags[tag]; !ok {
tags[tag] = []string{}
}
tags[tag] = append(tags[tag], n.Name)
}
}
}
proxies = append(proxies, *n)
}
// 随机选择一个中继节点
var relays []server.NodeRelay
if err := json.Unmarshal([]byte(node.RelayNode), &relays); err != nil {
logger.Errorw("Unmarshal RelayNode", logger.Field("error", err.Error()), logger.Field("node", node.Name), logger.Field("relayNode", node.RelayNode))
continue
}
if len(relays) > 0 {
randNum := random.RandomInRange(0, len(relays)-1)
relay := relays[randNum]
n := addNode(node, relay.Host, relay.Port)
if n == nil {
continue
}
relayName := "中继-" + node.Name
if relay.Prefix != "" {
relayName = relay.Prefix + node.Name
}
n.Name = relayName
if node.Tags != "" {
t := tool.RemoveDuplicateElements(strings.Split(node.Tags, ",")...)
for _, tag := range t {
if tag != "" {
if _, ok := tags[tag]; !ok {
tags[tag] = []string{}
}
tags[tag] = append(tags[tag], n.Name)
}
}
}
proxies = append(proxies, *n)
}
default:
logger.Info("Not Relay Mode", logger.Field("node", node.Name), logger.Field("relayMode", node.RelayMode))
n := addNode(node, node.ServerAddr, 0)