From 561248d5e2537cba0b449a97e12a38b7f55b76d8 Mon Sep 17 00:00:00 2001 From: civisrom <167646351+civisrom@users.noreply.github.com> Date: Tue, 4 Feb 2025 14:35:39 +0300 Subject: [PATCH] Delete xray directory --- xray/api.go | 256 ----------------------------------------- xray/client_traffic.go | 13 --- xray/config.go | 65 ----------- xray/inbound.go | 46 -------- xray/log_writer.go | 66 ----------- xray/process.go | 248 --------------------------------------- xray/traffic.go | 9 -- 7 files changed, 703 deletions(-) delete mode 100644 xray/api.go delete mode 100644 xray/client_traffic.go delete mode 100644 xray/config.go delete mode 100644 xray/inbound.go delete mode 100644 xray/log_writer.go delete mode 100644 xray/process.go delete mode 100644 xray/traffic.go diff --git a/xray/api.go b/xray/api.go deleted file mode 100644 index 727ab526..00000000 --- a/xray/api.go +++ /dev/null @@ -1,256 +0,0 @@ -package xray - -import ( - "context" - "encoding/json" - "fmt" - "regexp" - "time" - - "x-ui/logger" - "x-ui/util/common" - - "github.com/xtls/xray-core/app/proxyman/command" - statsService "github.com/xtls/xray-core/app/stats/command" - "github.com/xtls/xray-core/common/protocol" - "github.com/xtls/xray-core/common/serial" - "github.com/xtls/xray-core/infra/conf" - "github.com/xtls/xray-core/proxy/shadowsocks" - "github.com/xtls/xray-core/proxy/shadowsocks_2022" - "github.com/xtls/xray-core/proxy/trojan" - "github.com/xtls/xray-core/proxy/vless" - "github.com/xtls/xray-core/proxy/vmess" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials/insecure" -) - -type XrayAPI struct { - HandlerServiceClient *command.HandlerServiceClient - StatsServiceClient *statsService.StatsServiceClient - grpcClient *grpc.ClientConn - isConnected bool -} - -func (x *XrayAPI) Init(apiPort int) error { - if apiPort <= 0 { - return fmt.Errorf("invalid Xray API port: %d", apiPort) - } - - addr := fmt.Sprintf("127.0.0.1:%d", apiPort) - conn, err := grpc.NewClient(addr, grpc.WithTransportCredentials(insecure.NewCredentials())) - if err != nil { - return fmt.Errorf("failed to connect to Xray API: %w", err) - } - - x.grpcClient = conn - x.isConnected = true - - hsClient := command.NewHandlerServiceClient(conn) - ssClient := statsService.NewStatsServiceClient(conn) - - x.HandlerServiceClient = &hsClient - x.StatsServiceClient = &ssClient - - return nil -} - -func (x *XrayAPI) Close() { - if x.grpcClient != nil { - x.grpcClient.Close() - } - x.HandlerServiceClient = nil - x.StatsServiceClient = nil - x.isConnected = false -} - -func (x *XrayAPI) AddInbound(inbound []byte) error { - client := *x.HandlerServiceClient - - conf := new(conf.InboundDetourConfig) - err := json.Unmarshal(inbound, conf) - if err != nil { - logger.Debug("Failed to unmarshal inbound:", err) - return err - } - config, err := conf.Build() - if err != nil { - logger.Debug("Failed to build inbound Detur:", err) - return err - } - inboundConfig := command.AddInboundRequest{Inbound: config} - - _, err = client.AddInbound(context.Background(), &inboundConfig) - - return err -} - -func (x *XrayAPI) DelInbound(tag string) error { - client := *x.HandlerServiceClient - _, err := client.RemoveInbound(context.Background(), &command.RemoveInboundRequest{ - Tag: tag, - }) - return err -} - -func (x *XrayAPI) AddUser(Protocol string, inboundTag string, user map[string]interface{}) error { - var account *serial.TypedMessage - switch Protocol { - case "vmess": - account = serial.ToTypedMessage(&vmess.Account{ - Id: user["id"].(string), - }) - case "vless": - account = serial.ToTypedMessage(&vless.Account{ - Id: user["id"].(string), - Flow: user["flow"].(string), - }) - case "trojan": - account = serial.ToTypedMessage(&trojan.Account{ - Password: user["password"].(string), - }) - case "shadowsocks": - var ssCipherType shadowsocks.CipherType - switch user["cipher"].(string) { - case "aes-128-gcm": - ssCipherType = shadowsocks.CipherType_AES_128_GCM - case "aes-256-gcm": - ssCipherType = shadowsocks.CipherType_AES_256_GCM - case "chacha20-poly1305", "chacha20-ietf-poly1305": - ssCipherType = shadowsocks.CipherType_CHACHA20_POLY1305 - case "xchacha20-poly1305", "xchacha20-ietf-poly1305": - ssCipherType = shadowsocks.CipherType_XCHACHA20_POLY1305 - default: - ssCipherType = shadowsocks.CipherType_NONE - } - - if ssCipherType != shadowsocks.CipherType_NONE { - account = serial.ToTypedMessage(&shadowsocks.Account{ - Password: user["password"].(string), - CipherType: ssCipherType, - }) - } else { - account = serial.ToTypedMessage(&shadowsocks_2022.ServerConfig{ - Key: user["password"].(string), - Email: user["email"].(string), - }) - } - default: - return nil - } - - client := *x.HandlerServiceClient - - _, err := client.AlterInbound(context.Background(), &command.AlterInboundRequest{ - Tag: inboundTag, - Operation: serial.ToTypedMessage(&command.AddUserOperation{ - User: &protocol.User{ - Email: user["email"].(string), - Account: account, - }, - }), - }) - return err -} - -func (x *XrayAPI) RemoveUser(inboundTag, email string) error { - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) - defer cancel() - - op := &command.RemoveUserOperation{Email: email} - req := &command.AlterInboundRequest{ - Tag: inboundTag, - Operation: serial.ToTypedMessage(op), - } - - _, err := (*x.HandlerServiceClient).AlterInbound(ctx, req) - if err != nil { - return fmt.Errorf("failed to remove user: %w", err) - } - - return nil -} - -func (x *XrayAPI) GetTraffic(reset bool) ([]*Traffic, []*ClientTraffic, error) { - if x.grpcClient == nil { - return nil, nil, common.NewError("xray api is not initialized") - } - - trafficRegex := regexp.MustCompile(`(inbound|outbound)>>>([^>]+)>>>traffic>>>(downlink|uplink)`) - clientTrafficRegex := regexp.MustCompile(`user>>>([^>]+)>>>traffic>>>(downlink|uplink)`) - - ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) - defer cancel() - - if x.StatsServiceClient == nil { - return nil, nil, common.NewError("xray StatusServiceClient is not initialized") - } - - resp, err := (*x.StatsServiceClient).QueryStats(ctx, &statsService.QueryStatsRequest{Reset_: reset}) - if err != nil { - logger.Debug("Failed to query Xray stats:", err) - return nil, nil, err - } - - tagTrafficMap := make(map[string]*Traffic) - emailTrafficMap := make(map[string]*ClientTraffic) - - for _, stat := range resp.GetStat() { - if matches := trafficRegex.FindStringSubmatch(stat.Name); len(matches) == 4 { - processTraffic(matches, stat.Value, tagTrafficMap) - } else if matches := clientTrafficRegex.FindStringSubmatch(stat.Name); len(matches) == 3 { - processClientTraffic(matches, stat.Value, emailTrafficMap) - } - } - return mapToSlice(tagTrafficMap), mapToSlice(emailTrafficMap), nil -} - -func processTraffic(matches []string, value int64, trafficMap map[string]*Traffic) { - isInbound := matches[1] == "inbound" - tag := matches[2] - isDown := matches[3] == "downlink" - - if tag == "api" { - return - } - - traffic, ok := trafficMap[tag] - if !ok { - traffic = &Traffic{ - IsInbound: isInbound, - IsOutbound: !isInbound, - Tag: tag, - } - trafficMap[tag] = traffic - } - - if isDown { - traffic.Down = value - } else { - traffic.Up = value - } -} - -func processClientTraffic(matches []string, value int64, clientTrafficMap map[string]*ClientTraffic) { - email := matches[1] - isDown := matches[2] == "downlink" - - traffic, ok := clientTrafficMap[email] - if !ok { - traffic = &ClientTraffic{Email: email} - clientTrafficMap[email] = traffic - } - - if isDown { - traffic.Down = value - } else { - traffic.Up = value - } -} - -func mapToSlice[T any](m map[string]*T) []*T { - result := make([]*T, 0, len(m)) - for _, v := range m { - result = append(result, v) - } - return result -} diff --git a/xray/client_traffic.go b/xray/client_traffic.go deleted file mode 100644 index 0f2389a0..00000000 --- a/xray/client_traffic.go +++ /dev/null @@ -1,13 +0,0 @@ -package xray - -type ClientTraffic struct { - Id int `json:"id" form:"id" gorm:"primaryKey;autoIncrement"` - InboundId int `json:"inboundId" form:"inboundId"` - Enable bool `json:"enable" form:"enable"` - Email string `json:"email" form:"email" gorm:"unique"` - Up int64 `json:"up" form:"up"` - Down int64 `json:"down" form:"down"` - ExpiryTime int64 `json:"expiryTime" form:"expiryTime"` - Total int64 `json:"total" form:"total"` - Reset int `json:"reset" form:"reset" gorm:"default:0"` -} diff --git a/xray/config.go b/xray/config.go deleted file mode 100644 index 67ff7d95..00000000 --- a/xray/config.go +++ /dev/null @@ -1,65 +0,0 @@ -package xray - -import ( - "bytes" - - "x-ui/util/json_util" -) - -type Config struct { - LogConfig json_util.RawMessage `json:"log"` - RouterConfig json_util.RawMessage `json:"routing"` - DNSConfig json_util.RawMessage `json:"dns"` - InboundConfigs []InboundConfig `json:"inbounds"` - OutboundConfigs json_util.RawMessage `json:"outbounds"` - Transport json_util.RawMessage `json:"transport"` - Policy json_util.RawMessage `json:"policy"` - API json_util.RawMessage `json:"api"` - Stats json_util.RawMessage `json:"stats"` - Reverse json_util.RawMessage `json:"reverse"` - FakeDNS json_util.RawMessage `json:"fakedns"` - Observatory json_util.RawMessage `json:"observatory"` - BurstObservatory json_util.RawMessage `json:"burstObservatory"` -} - -func (c *Config) Equals(other *Config) bool { - if len(c.InboundConfigs) != len(other.InboundConfigs) { - return false - } - for i, inbound := range c.InboundConfigs { - if !inbound.Equals(&other.InboundConfigs[i]) { - return false - } - } - if !bytes.Equal(c.LogConfig, other.LogConfig) { - return false - } - if !bytes.Equal(c.RouterConfig, other.RouterConfig) { - return false - } - if !bytes.Equal(c.DNSConfig, other.DNSConfig) { - return false - } - if !bytes.Equal(c.OutboundConfigs, other.OutboundConfigs) { - return false - } - if !bytes.Equal(c.Transport, other.Transport) { - return false - } - if !bytes.Equal(c.Policy, other.Policy) { - return false - } - if !bytes.Equal(c.API, other.API) { - return false - } - if !bytes.Equal(c.Stats, other.Stats) { - return false - } - if !bytes.Equal(c.Reverse, other.Reverse) { - return false - } - if !bytes.Equal(c.FakeDNS, other.FakeDNS) { - return false - } - return true -} diff --git a/xray/inbound.go b/xray/inbound.go deleted file mode 100644 index c74b07ba..00000000 --- a/xray/inbound.go +++ /dev/null @@ -1,46 +0,0 @@ -package xray - -import ( - "bytes" - - "x-ui/util/json_util" -) - -type InboundConfig struct { - Listen json_util.RawMessage `json:"listen"` // listen cannot be an empty string - Port int `json:"port"` - Protocol string `json:"protocol"` - Settings json_util.RawMessage `json:"settings"` - StreamSettings json_util.RawMessage `json:"streamSettings"` - Tag string `json:"tag"` - Sniffing json_util.RawMessage `json:"sniffing"` - Allocate json_util.RawMessage `json:"allocate"` -} - -func (c *InboundConfig) Equals(other *InboundConfig) bool { - if !bytes.Equal(c.Listen, other.Listen) { - return false - } - if c.Port != other.Port { - return false - } - if c.Protocol != other.Protocol { - return false - } - if !bytes.Equal(c.Settings, other.Settings) { - return false - } - if !bytes.Equal(c.StreamSettings, other.StreamSettings) { - return false - } - if c.Tag != other.Tag { - return false - } - if !bytes.Equal(c.Sniffing, other.Sniffing) { - return false - } - if !bytes.Equal(c.Allocate, other.Allocate) { - return false - } - return true -} diff --git a/xray/log_writer.go b/xray/log_writer.go deleted file mode 100644 index cc00d541..00000000 --- a/xray/log_writer.go +++ /dev/null @@ -1,66 +0,0 @@ -package xray - -import ( - "regexp" - "strings" - - "x-ui/logger" -) - -func NewLogWriter() *LogWriter { - return &LogWriter{} -} - -type LogWriter struct { - lastLine string -} - -func (lw *LogWriter) Write(m []byte) (n int, err error) { - crashRegex := regexp.MustCompile(`(?i)(panic|exception|stack trace|fatal error)`) - - // Convert the data to a string - message := strings.TrimSpace(string(m)) - - // Check if the message contains a crash - if crashRegex.MatchString(message) { - logger.Debug("Core crash detected:\n", message) - lw.lastLine = message - err1 := writeCrachReport(m) - if err1 != nil { - logger.Error("Unable to write crash report:", err1) - } - return len(m), nil - } - - regex := regexp.MustCompile(`^(\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2}) \[([^\]]+)\] (.+)$`) - messages := strings.Split(message, "\n") - - for _, msg := range messages { - matches := regex.FindStringSubmatch(msg) - - if len(matches) > 3 { - level := matches[2] - msgBody := matches[3] - - // Map the level to the appropriate logger function - switch level { - case "Debug": - logger.Debug("XRAY: " + msgBody) - case "Info": - logger.Info("XRAY: " + msgBody) - case "Warning": - logger.Warning("XRAY: " + msgBody) - case "Error": - logger.Error("XRAY: " + msgBody) - default: - logger.Debug("XRAY: " + msg) - } - lw.lastLine = "" - } else if msg != "" { - logger.Debug("XRAY: " + msg) - lw.lastLine = msg - } - } - - return len(m), nil -} diff --git a/xray/process.go b/xray/process.go deleted file mode 100644 index b4947864..00000000 --- a/xray/process.go +++ /dev/null @@ -1,248 +0,0 @@ -package xray - -import ( - "bytes" - "encoding/json" - "errors" - "fmt" - "io/fs" - "os" - "os/exec" - "runtime" - "syscall" - "time" - - "x-ui/config" - "x-ui/logger" - "x-ui/util/common" -) - -func GetBinaryName() string { - return fmt.Sprintf("xray-%s-%s", runtime.GOOS, runtime.GOARCH) -} - -func GetBinaryPath() string { - return config.GetBinFolderPath() + "/" + GetBinaryName() -} - -func GetConfigPath() string { - return config.GetBinFolderPath() + "/config.json" -} - -func GetGeositePath() string { - return config.GetBinFolderPath() + "/geosite.dat" -} - -func GetGeoipPath() string { - return config.GetBinFolderPath() + "/geoip.dat" -} - -func GetIPLimitLogPath() string { - return config.GetLogFolder() + "/3xipl.log" -} - -func GetIPLimitBannedLogPath() string { - return config.GetLogFolder() + "/3xipl-banned.log" -} - -func GetIPLimitBannedPrevLogPath() string { - return config.GetLogFolder() + "/3xipl-banned.prev.log" -} - -func GetAccessPersistentLogPath() string { - return config.GetLogFolder() + "/3xipl-ap.log" -} - -func GetAccessPersistentPrevLogPath() string { - return config.GetLogFolder() + "/3xipl-ap.prev.log" -} - -func GetAccessLogPath() (string, error) { - config, err := os.ReadFile(GetConfigPath()) - if err != nil { - logger.Warningf("Failed to read configuration file: %s", err) - return "", err - } - - jsonConfig := map[string]interface{}{} - err = json.Unmarshal([]byte(config), &jsonConfig) - if err != nil { - logger.Warningf("Failed to parse JSON configuration: %s", err) - return "", err - } - - if jsonConfig["log"] != nil { - jsonLog := jsonConfig["log"].(map[string]interface{}) - if jsonLog["access"] != nil { - accessLogPath := jsonLog["access"].(string) - return accessLogPath, nil - } - } - return "", err -} - -func stopProcess(p *Process) { - p.Stop() -} - -type Process struct { - *process -} - -func NewProcess(xrayConfig *Config) *Process { - p := &Process{newProcess(xrayConfig)} - runtime.SetFinalizer(p, stopProcess) - return p -} - -type process struct { - cmd *exec.Cmd - - version string - apiPort int - - onlineClients []string - - config *Config - logWriter *LogWriter - exitErr error - startTime time.Time -} - -func newProcess(config *Config) *process { - return &process{ - version: "Unknown", - config: config, - logWriter: NewLogWriter(), - startTime: time.Now(), - } -} - -func (p *process) IsRunning() bool { - if p.cmd == nil || p.cmd.Process == nil { - return false - } - if p.cmd.ProcessState == nil { - return true - } - return false -} - -func (p *process) GetErr() error { - return p.exitErr -} - -func (p *process) GetResult() string { - if len(p.logWriter.lastLine) == 0 && p.exitErr != nil { - return p.exitErr.Error() - } - return p.logWriter.lastLine -} - -func (p *process) GetVersion() string { - return p.version -} - -func (p *Process) GetAPIPort() int { - return p.apiPort -} - -func (p *Process) GetConfig() *Config { - return p.config -} - -func (p *Process) GetOnlineClients() []string { - return p.onlineClients -} - -func (p *Process) SetOnlineClients(users []string) { - p.onlineClients = users -} - -func (p *Process) GetUptime() uint64 { - return uint64(time.Since(p.startTime).Seconds()) -} - -func (p *process) refreshAPIPort() { - for _, inbound := range p.config.InboundConfigs { - if inbound.Tag == "api" { - p.apiPort = inbound.Port - break - } - } -} - -func (p *process) refreshVersion() { - cmd := exec.Command(GetBinaryPath(), "-version") - data, err := cmd.Output() - if err != nil { - p.version = "Unknown" - } else { - datas := bytes.Split(data, []byte(" ")) - if len(datas) <= 1 { - p.version = "Unknown" - } else { - p.version = string(datas[1]) - } - } -} - -func (p *process) Start() (err error) { - if p.IsRunning() { - return errors.New("xray is already running") - } - - defer func() { - if err != nil { - logger.Error("Failure in running xray-core process: ", err) - p.exitErr = err - } - }() - - data, err := json.MarshalIndent(p.config, "", " ") - if err != nil { - return common.NewErrorf("Failed to generate XRAY configuration files: %v", err) - } - - err = os.MkdirAll(config.GetLogFolder(), 0o770) - if err != nil { - logger.Warningf("Failed to create log folder: %s", err) - } - - configPath := GetConfigPath() - err = os.WriteFile(configPath, data, fs.ModePerm) - if err != nil { - return common.NewErrorf("Failed to write configuration file: %v", err) - } - - cmd := exec.Command(GetBinaryPath(), "-c", configPath) - p.cmd = cmd - - cmd.Stdout = p.logWriter - cmd.Stderr = p.logWriter - - go func() { - err := cmd.Run() - if err != nil { - logger.Error("Failure in running xray-core:", err) - p.exitErr = err - } - }() - - p.refreshVersion() - p.refreshAPIPort() - - return nil -} - -func (p *process) Stop() error { - if !p.IsRunning() { - return errors.New("xray is not running") - } - return p.cmd.Process.Signal(syscall.SIGTERM) -} - -func writeCrachReport(m []byte) error { - crashReportPath := config.GetBinFolderPath() + "/core_crash_" + time.Now().Format("20060102_150405") + ".log" - return os.WriteFile(crashReportPath, m, os.ModePerm) -} diff --git a/xray/traffic.go b/xray/traffic.go deleted file mode 100644 index 7b907bae..00000000 --- a/xray/traffic.go +++ /dev/null @@ -1,9 +0,0 @@ -package xray - -type Traffic struct { - IsInbound bool - IsOutbound bool - Tag string - Up int64 - Down int64 -}