mirror of
https://github.com/wyx2685/V2bX.git
synced 2025-01-22 18:08:14 -05:00
221 lines
6.9 KiB
Go
221 lines
6.9 KiB
Go
package panel
|
|
|
|
import (
|
|
"encoding/json"
|
|
"github.com/Yuzuki616/V2bX/app/mydispatcher"
|
|
io "io/ioutil"
|
|
"log"
|
|
"sync"
|
|
|
|
"github.com/Yuzuki616/V2bX/api"
|
|
"github.com/Yuzuki616/V2bX/api/v2board"
|
|
_ "github.com/Yuzuki616/V2bX/main/distro/all"
|
|
"github.com/Yuzuki616/V2bX/service"
|
|
"github.com/Yuzuki616/V2bX/service/controller"
|
|
"github.com/imdario/mergo"
|
|
"github.com/r3labs/diff/v2"
|
|
"github.com/xtls/xray-core/app/proxyman"
|
|
"github.com/xtls/xray-core/app/stats"
|
|
"github.com/xtls/xray-core/common/serial"
|
|
"github.com/xtls/xray-core/core"
|
|
"github.com/xtls/xray-core/infra/conf"
|
|
)
|
|
|
|
// Panel Structure
|
|
type Panel struct {
|
|
access sync.Mutex
|
|
panelConfig *Config
|
|
Server *core.Instance
|
|
Service []service.Service
|
|
Running bool
|
|
}
|
|
|
|
func New(panelConfig *Config) *Panel {
|
|
p := &Panel{panelConfig: panelConfig}
|
|
return p
|
|
}
|
|
|
|
func (p *Panel) loadCore(panelConfig *Config) *core.Instance {
|
|
// Log Config
|
|
coreLogConfig := &conf.LogConfig{}
|
|
logConfig := getDefaultLogConfig()
|
|
if panelConfig.LogConfig != nil {
|
|
if _, err := diff.Merge(logConfig, panelConfig.LogConfig, logConfig); err != nil {
|
|
log.Panicf("Read Log config failed: %s", err)
|
|
}
|
|
}
|
|
coreLogConfig.LogLevel = logConfig.Level
|
|
coreLogConfig.AccessLog = logConfig.AccessPath
|
|
coreLogConfig.ErrorLog = logConfig.ErrorPath
|
|
|
|
// DNS config
|
|
coreDnsConfig := &conf.DNSConfig{}
|
|
if panelConfig.DnsConfigPath != "" {
|
|
if data, err := io.ReadFile(panelConfig.DnsConfigPath); err != nil {
|
|
log.Panicf("Failed to read DNS config file at: %s", panelConfig.DnsConfigPath)
|
|
} else {
|
|
if err = json.Unmarshal(data, coreDnsConfig); err != nil {
|
|
log.Panicf("Failed to unmarshal DNS config: %s", panelConfig.DnsConfigPath)
|
|
}
|
|
}
|
|
}
|
|
dnsConfig, err := coreDnsConfig.Build()
|
|
if err != nil {
|
|
log.Panicf("Failed to understand DNS config, Please check: https://xtls.github.io/config/dns.html for help: %s", err)
|
|
}
|
|
// Routing config
|
|
coreRouterConfig := &conf.RouterConfig{}
|
|
if panelConfig.RouteConfigPath != "" {
|
|
if data, err := io.ReadFile(panelConfig.RouteConfigPath); err != nil {
|
|
log.Panicf("Failed to read Routing config file at: %s", panelConfig.RouteConfigPath)
|
|
} else {
|
|
if err = json.Unmarshal(data, coreRouterConfig); err != nil {
|
|
log.Panicf("Failed to unmarshal Routing config: %s", panelConfig.RouteConfigPath)
|
|
}
|
|
}
|
|
}
|
|
routeConfig, err := coreRouterConfig.Build()
|
|
if err != nil {
|
|
log.Panicf("Failed to understand Routing config Please check: https://xtls.github.io/config/routing.html for help: %s", err)
|
|
}
|
|
// Custom Inbound config
|
|
var coreCustomInboundConfig []conf.InboundDetourConfig
|
|
if panelConfig.InboundConfigPath != "" {
|
|
if data, err := io.ReadFile(panelConfig.InboundConfigPath); err != nil {
|
|
log.Panicf("Failed to read Custom Inbound config file at: %s", panelConfig.OutboundConfigPath)
|
|
} else {
|
|
if err = json.Unmarshal(data, &coreCustomInboundConfig); err != nil {
|
|
log.Panicf("Failed to unmarshal Custom Inbound config: %s", panelConfig.OutboundConfigPath)
|
|
}
|
|
}
|
|
}
|
|
var inBoundConfig []*core.InboundHandlerConfig
|
|
for _, config := range coreCustomInboundConfig {
|
|
oc, err := config.Build()
|
|
if err != nil {
|
|
log.Panicf("Failed to understand Inbound config, Please check: https://xtls.github.io/config/inbound.html for help: %s", err)
|
|
}
|
|
inBoundConfig = append(inBoundConfig, oc)
|
|
}
|
|
// Custom Outbound config
|
|
var coreCustomOutboundConfig []conf.OutboundDetourConfig
|
|
if panelConfig.OutboundConfigPath != "" {
|
|
if data, err := io.ReadFile(panelConfig.OutboundConfigPath); err != nil {
|
|
log.Panicf("Failed to read Custom Outbound config file at: %s", panelConfig.OutboundConfigPath)
|
|
} else {
|
|
if err = json.Unmarshal(data, &coreCustomOutboundConfig); err != nil {
|
|
log.Panicf("Failed to unmarshal Custom Outbound config: %s", panelConfig.OutboundConfigPath)
|
|
}
|
|
}
|
|
}
|
|
var outBoundConfig []*core.OutboundHandlerConfig
|
|
for _, config := range coreCustomOutboundConfig {
|
|
oc, err := config.Build()
|
|
if err != nil {
|
|
log.Panicf("Failed to understand Outbound config, Please check: https://xtls.github.io/config/outbound.html for help: %s", err)
|
|
}
|
|
outBoundConfig = append(outBoundConfig, oc)
|
|
}
|
|
// Policy config
|
|
levelPolicyConfig := parseConnectionConfig(panelConfig.ConnetionConfig)
|
|
corePolicyConfig := &conf.PolicyConfig{}
|
|
corePolicyConfig.Levels = map[uint32]*conf.Policy{0: levelPolicyConfig}
|
|
policyConfig, _ := corePolicyConfig.Build()
|
|
// Build Core Config
|
|
config := &core.Config{
|
|
App: []*serial.TypedMessage{
|
|
serial.ToTypedMessage(coreLogConfig.Build()),
|
|
serial.ToTypedMessage(&mydispatcher.Config{}),
|
|
serial.ToTypedMessage(&stats.Config{}),
|
|
serial.ToTypedMessage(&proxyman.InboundConfig{}),
|
|
serial.ToTypedMessage(&proxyman.OutboundConfig{}),
|
|
serial.ToTypedMessage(policyConfig),
|
|
serial.ToTypedMessage(dnsConfig),
|
|
serial.ToTypedMessage(routeConfig),
|
|
},
|
|
Inbound: inBoundConfig,
|
|
Outbound: outBoundConfig,
|
|
}
|
|
server, err := core.New(config)
|
|
if err != nil {
|
|
log.Panicf("failed to create instance: %s", err)
|
|
}
|
|
log.Printf("Xray Core Version: %s", core.Version())
|
|
|
|
return server
|
|
}
|
|
|
|
// Start Start the panel
|
|
func (p *Panel) Start() {
|
|
p.access.Lock()
|
|
defer p.access.Unlock()
|
|
log.Print("Start the panel..")
|
|
// Load Core
|
|
server := p.loadCore(p.panelConfig)
|
|
if err := server.Start(); err != nil {
|
|
log.Panicf("Failed to start instance: %s", err)
|
|
}
|
|
p.Server = server
|
|
// Load Nodes config
|
|
for _, nodeConfig := range p.panelConfig.NodesConfig {
|
|
var apiClient api.API = v2board.New(nodeConfig.ApiConfig)
|
|
var controllerService service.Service
|
|
// Register controller service
|
|
controllerConfig := getDefaultControllerConfig()
|
|
if nodeConfig.ControllerConfig != nil {
|
|
if err := mergo.Merge(controllerConfig, nodeConfig.ControllerConfig, mergo.WithOverride); err != nil {
|
|
log.Panicf("Read Controller Config Failed")
|
|
}
|
|
}
|
|
controllerService = controller.New(server, apiClient, controllerConfig)
|
|
p.Service = append(p.Service, controllerService)
|
|
|
|
}
|
|
|
|
// Start all the service
|
|
for _, s := range p.Service {
|
|
err := s.Start()
|
|
if err != nil {
|
|
log.Panicf("Panel Start fialed: %s", err)
|
|
}
|
|
}
|
|
p.Running = true
|
|
return
|
|
}
|
|
|
|
// Close Close the panel
|
|
func (p *Panel) Close() {
|
|
p.access.Lock()
|
|
defer p.access.Unlock()
|
|
for _, s := range p.Service {
|
|
err := s.Close()
|
|
if err != nil {
|
|
log.Panicf("Panel Close fialed: %s", err)
|
|
}
|
|
}
|
|
p.Service = nil
|
|
p.Server.Close()
|
|
p.Running = false
|
|
return
|
|
}
|
|
|
|
func parseConnectionConfig(c *ConnetionConfig) (policy *conf.Policy) {
|
|
connetionConfig := getDefaultConnetionConfig()
|
|
if c != nil {
|
|
if _, err := diff.Merge(connetionConfig, c, connetionConfig); err != nil {
|
|
log.Panicf("Read ConnetionConfig failed: %s", err)
|
|
}
|
|
}
|
|
policy = &conf.Policy{
|
|
StatsUserUplink: true,
|
|
StatsUserDownlink: true,
|
|
Handshake: &connetionConfig.Handshake,
|
|
ConnectionIdle: &connetionConfig.ConnIdle,
|
|
UplinkOnly: &connetionConfig.UplinkOnly,
|
|
DownlinkOnly: &connetionConfig.DownlinkOnly,
|
|
BufferSize: &connetionConfig.BufferSize,
|
|
}
|
|
|
|
return
|
|
}
|