331 lines
10 KiB
Go
331 lines
10 KiB
Go
package server
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
|
|
"github.com/perfect-panel/server/internal/model/node"
|
|
"github.com/perfect-panel/server/internal/model/server"
|
|
"github.com/perfect-panel/server/internal/svc"
|
|
"github.com/perfect-panel/server/internal/types"
|
|
"github.com/perfect-panel/server/pkg/logger"
|
|
)
|
|
|
|
type MigrateServerNodeLogic struct {
|
|
logger.Logger
|
|
ctx context.Context
|
|
svcCtx *svc.ServiceContext
|
|
}
|
|
|
|
// NewMigrateServerNodeLogic Migrate server and node data to new database
|
|
func NewMigrateServerNodeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *MigrateServerNodeLogic {
|
|
return &MigrateServerNodeLogic{
|
|
Logger: logger.WithContext(ctx),
|
|
ctx: ctx,
|
|
svcCtx: svcCtx,
|
|
}
|
|
}
|
|
|
|
func (l *MigrateServerNodeLogic) MigrateServerNode() (resp *types.MigrateServerNodeResponse, err error) {
|
|
tx := l.svcCtx.DB.WithContext(l.ctx).Begin()
|
|
var oldServers []*server.Server
|
|
var newServers []*node.Server
|
|
var newNodes []*node.Node
|
|
|
|
err = tx.Model(&server.Server{}).Find(&oldServers).Error
|
|
if err != nil {
|
|
l.Errorw("[MigrateServerNode] Query Old Server List Error: ", logger.Field("error", err.Error()))
|
|
return &types.MigrateServerNodeResponse{
|
|
Succee: 0,
|
|
Fail: 0,
|
|
Message: fmt.Sprintf("Query Old Server List Error: %s", err.Error()),
|
|
}, nil
|
|
}
|
|
for _, oldServer := range oldServers {
|
|
data, err := l.adapterServer(oldServer)
|
|
if err != nil {
|
|
l.Errorw("[MigrateServerNode] Adapter Server Error: ", logger.Field("error", err.Error()))
|
|
if resp == nil {
|
|
resp = &types.MigrateServerNodeResponse{}
|
|
}
|
|
resp.Fail++
|
|
if resp.Message == "" {
|
|
resp.Message = fmt.Sprintf("Adapter Server Error: %s", err.Error())
|
|
} else {
|
|
resp.Message = fmt.Sprintf("%s; Adapter Server Error: %s", resp.Message, err.Error())
|
|
}
|
|
continue
|
|
}
|
|
newServers = append(newServers, data)
|
|
|
|
newNode, err := l.adapterNode(oldServer)
|
|
if err != nil {
|
|
l.Errorw("[MigrateServerNode] Adapter Node Error: ", logger.Field("error", err.Error()))
|
|
if resp == nil {
|
|
resp = &types.MigrateServerNodeResponse{}
|
|
}
|
|
resp.Fail++
|
|
if resp.Message == "" {
|
|
resp.Message = fmt.Sprintf("Adapter Node Error: %s", err.Error())
|
|
} else {
|
|
resp.Message = fmt.Sprintf("%s; Adapter Node Error: %s", resp.Message, err.Error())
|
|
}
|
|
continue
|
|
}
|
|
for _, item := range newNode {
|
|
if item.Port == 0 {
|
|
protocols, _ := data.UnmarshalProtocols()
|
|
if len(protocols) > 0 {
|
|
item.Port = protocols[0].Port
|
|
}
|
|
}
|
|
newNodes = append(newNodes, item)
|
|
}
|
|
}
|
|
|
|
if len(newServers) > 0 {
|
|
err = tx.Model(&node.Server{}).CreateInBatches(newServers, 20).Error
|
|
if err != nil {
|
|
tx.Rollback()
|
|
l.Errorw("[MigrateServerNode] Insert New Server List Error: ", logger.Field("error", err.Error()))
|
|
return &types.MigrateServerNodeResponse{
|
|
Succee: 0,
|
|
Fail: uint64(len(newServers)),
|
|
Message: fmt.Sprintf("Insert New Server List Error: %s", err.Error()),
|
|
}, nil
|
|
}
|
|
}
|
|
if len(newNodes) > 0 {
|
|
err = tx.Model(&node.Node{}).CreateInBatches(newNodes, 20).Error
|
|
if err != nil {
|
|
tx.Rollback()
|
|
l.Errorw("[MigrateServerNode] Insert New Node List Error: ", logger.Field("error", err.Error()))
|
|
return &types.MigrateServerNodeResponse{
|
|
Succee: uint64(len(newServers)),
|
|
Fail: uint64(len(newNodes)),
|
|
Message: fmt.Sprintf("Insert New Node List Error: %s", err.Error()),
|
|
}, nil
|
|
}
|
|
}
|
|
tx.Commit()
|
|
|
|
return &types.MigrateServerNodeResponse{
|
|
Succee: uint64(len(newServers)),
|
|
Fail: 0,
|
|
Message: fmt.Sprintf("Migrate Success: %d servers and %d nodes", len(newServers), len(newNodes)),
|
|
}, nil
|
|
}
|
|
|
|
func (l *MigrateServerNodeLogic) adapterServer(info *server.Server) (*node.Server, error) {
|
|
result := &node.Server{
|
|
Name: info.Name,
|
|
Country: info.Country,
|
|
City: info.City,
|
|
Ratio: info.TrafficRatio,
|
|
Address: info.ServerAddr,
|
|
Sort: int(info.Sort),
|
|
Protocols: "",
|
|
}
|
|
var protocols []node.Protocol
|
|
|
|
switch info.Protocol {
|
|
case ShadowSocks:
|
|
var src server.Shadowsocks
|
|
err := json.Unmarshal([]byte(info.Config), &src)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
protocols = append(protocols, node.Protocol{
|
|
Type: "shadowsocks",
|
|
Cipher: src.Method,
|
|
Port: uint16(src.Port),
|
|
ServerKey: src.ServerKey,
|
|
})
|
|
case Vmess:
|
|
var src server.Vmess
|
|
err := json.Unmarshal([]byte(info.Config), &src)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
protocol := node.Protocol{
|
|
Type: "vmess",
|
|
Port: uint16(src.Port),
|
|
Security: src.Security,
|
|
SNI: src.SecurityConfig.SNI,
|
|
AllowInsecure: src.SecurityConfig.AllowInsecure,
|
|
Fingerprint: src.SecurityConfig.Fingerprint,
|
|
RealityServerAddr: src.SecurityConfig.RealityServerAddr,
|
|
RealityServerPort: src.SecurityConfig.RealityServerPort,
|
|
RealityPrivateKey: src.SecurityConfig.RealityPrivateKey,
|
|
RealityPublicKey: src.SecurityConfig.RealityPublicKey,
|
|
RealityShortId: src.SecurityConfig.RealityShortId,
|
|
Transport: src.Transport,
|
|
Host: src.TransportConfig.Host,
|
|
Path: src.TransportConfig.Path,
|
|
ServiceName: src.TransportConfig.ServiceName,
|
|
Flow: src.Flow,
|
|
}
|
|
protocols = append(protocols, protocol)
|
|
protocols = append(protocols, protocol)
|
|
case Vless:
|
|
var src server.Vless
|
|
err := json.Unmarshal([]byte(info.Config), &src)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
protocol := node.Protocol{
|
|
Type: "vless",
|
|
Port: uint16(src.Port),
|
|
Security: src.Security,
|
|
SNI: src.SecurityConfig.SNI,
|
|
AllowInsecure: src.SecurityConfig.AllowInsecure,
|
|
Fingerprint: src.SecurityConfig.Fingerprint,
|
|
RealityServerAddr: src.SecurityConfig.RealityServerAddr,
|
|
RealityServerPort: src.SecurityConfig.RealityServerPort,
|
|
RealityPrivateKey: src.SecurityConfig.RealityPrivateKey,
|
|
RealityPublicKey: src.SecurityConfig.RealityPublicKey,
|
|
RealityShortId: src.SecurityConfig.RealityShortId,
|
|
Transport: src.Transport,
|
|
Host: src.TransportConfig.Host,
|
|
Path: src.TransportConfig.Path,
|
|
ServiceName: src.TransportConfig.ServiceName,
|
|
Flow: src.Flow,
|
|
}
|
|
protocols = append(protocols, protocol)
|
|
case Trojan:
|
|
var src server.Trojan
|
|
err := json.Unmarshal([]byte(info.Config), &src)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
protocol := node.Protocol{
|
|
Type: "trojan",
|
|
Port: uint16(src.Port),
|
|
Security: src.Security,
|
|
SNI: src.SecurityConfig.SNI,
|
|
AllowInsecure: src.SecurityConfig.AllowInsecure,
|
|
Fingerprint: src.SecurityConfig.Fingerprint,
|
|
RealityServerAddr: src.SecurityConfig.RealityServerAddr,
|
|
RealityServerPort: src.SecurityConfig.RealityServerPort,
|
|
RealityPrivateKey: src.SecurityConfig.RealityPrivateKey,
|
|
RealityPublicKey: src.SecurityConfig.RealityPublicKey,
|
|
RealityShortId: src.SecurityConfig.RealityShortId,
|
|
Transport: src.Transport,
|
|
Host: src.TransportConfig.Host,
|
|
Path: src.TransportConfig.Path,
|
|
ServiceName: src.TransportConfig.ServiceName,
|
|
Flow: src.Flow,
|
|
}
|
|
protocols = append(protocols, protocol)
|
|
case Hysteria2:
|
|
var src server.Hysteria2
|
|
err := json.Unmarshal([]byte(info.Config), &src)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
protocol := node.Protocol{
|
|
Type: "hysteria2",
|
|
Port: uint16(src.Port),
|
|
HopPorts: src.HopPorts,
|
|
HopInterval: src.HopInterval,
|
|
ObfsPassword: src.ObfsPassword,
|
|
SNI: src.SecurityConfig.SNI,
|
|
AllowInsecure: src.SecurityConfig.AllowInsecure,
|
|
Fingerprint: src.SecurityConfig.Fingerprint,
|
|
RealityServerAddr: src.SecurityConfig.RealityServerAddr,
|
|
RealityServerPort: src.SecurityConfig.RealityServerPort,
|
|
RealityPrivateKey: src.SecurityConfig.RealityPrivateKey,
|
|
RealityPublicKey: src.SecurityConfig.RealityPublicKey,
|
|
RealityShortId: src.SecurityConfig.RealityShortId,
|
|
}
|
|
protocols = append(protocols, protocol)
|
|
case Tuic:
|
|
var src server.Tuic
|
|
err := json.Unmarshal([]byte(info.Config), &src)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
protocol := node.Protocol{
|
|
Type: "tuic",
|
|
Port: uint16(src.Port),
|
|
DisableSNI: src.DisableSNI,
|
|
ReduceRtt: src.ReduceRtt,
|
|
UDPRelayMode: src.UDPRelayMode,
|
|
CongestionController: src.CongestionController,
|
|
SNI: src.SecurityConfig.SNI,
|
|
AllowInsecure: src.SecurityConfig.AllowInsecure,
|
|
Fingerprint: src.SecurityConfig.Fingerprint,
|
|
RealityServerAddr: src.SecurityConfig.RealityServerAddr,
|
|
RealityServerPort: src.SecurityConfig.RealityServerPort,
|
|
RealityPrivateKey: src.SecurityConfig.RealityPrivateKey,
|
|
RealityPublicKey: src.SecurityConfig.RealityPublicKey,
|
|
RealityShortId: src.SecurityConfig.RealityShortId,
|
|
}
|
|
protocols = append(protocols, protocol)
|
|
case AnyTLS:
|
|
var src server.AnyTLS
|
|
err := json.Unmarshal([]byte(info.Config), &src)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
protocol := node.Protocol{
|
|
Type: "anytls",
|
|
Port: uint16(src.Port),
|
|
SNI: src.SecurityConfig.SNI,
|
|
AllowInsecure: src.SecurityConfig.AllowInsecure,
|
|
Fingerprint: src.SecurityConfig.Fingerprint,
|
|
RealityServerAddr: src.SecurityConfig.RealityServerAddr,
|
|
RealityServerPort: src.SecurityConfig.RealityServerPort,
|
|
RealityPrivateKey: src.SecurityConfig.RealityPrivateKey,
|
|
RealityPublicKey: src.SecurityConfig.RealityPublicKey,
|
|
RealityShortId: src.SecurityConfig.RealityShortId,
|
|
}
|
|
protocols = append(protocols, protocol)
|
|
}
|
|
if len(protocols) > 0 {
|
|
err := result.MarshalProtocols(protocols)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
func (l *MigrateServerNodeLogic) adapterNode(info *server.Server) ([]*node.Node, error) {
|
|
var nodes []*node.Node
|
|
enable := true
|
|
switch info.RelayMode {
|
|
case server.RelayModeNone:
|
|
nodes = append(nodes, &node.Node{
|
|
Name: info.Name,
|
|
Tags: "",
|
|
Port: 0,
|
|
Address: info.ServerAddr,
|
|
ServerId: info.Id,
|
|
Protocol: info.Protocol,
|
|
Enabled: &enable,
|
|
})
|
|
default:
|
|
var relays []server.NodeRelay
|
|
err := json.Unmarshal([]byte(info.RelayNode), &relays)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, relay := range relays {
|
|
nodes = append(nodes, &node.Node{
|
|
Name: relay.Prefix + info.Name,
|
|
Tags: "",
|
|
Port: uint16(relay.Port),
|
|
Address: relay.Host,
|
|
ServerId: info.Id,
|
|
Protocol: info.Protocol,
|
|
Enabled: &enable,
|
|
})
|
|
}
|
|
}
|
|
|
|
return nodes, nil
|
|
}
|