From b1bfd04895ecbf570c0f7f0ec67335c12ef5384f Mon Sep 17 00:00:00 2001 From: Senis John Date: Sat, 14 Oct 2023 10:50:50 +0800 Subject: [PATCH] Refactor main to use Cobra command line framework and package restructure Reorganized the Go package structure, moving the main package to 'cmd'. Upgraded the flag library to Cobra for better management of CLI commands. This included moving the X25519 key generation from a flag to its own standalone Cobra command, which improves user interaction and code modularity. This structural change will benefit future additions and code maintainability. --- .github/workflows/release.yml | 16 ++--- .gitignore | 38 ++++++----- Dockerfile | 2 +- {main => cmd}/distro/all/all.go | 0 main/main.go => cmd/root.go | 63 ++++++++---------- cmd/version.go | 27 ++++++++ cmd/x25519.go | 48 +++++++++++++ common/common.go | 34 ---------- go.mod | 2 + go.sum | 2 + main.go | 13 ++++ panel/panel.go | 2 +- {main => release/config}/config.yml.example | 12 ++-- {main => release/config}/custom_inbound.json | 0 {main => release/config}/custom_outbound.json | 0 {main => release/config}/dns.json | 0 {main => release/config}/geoip.dat | Bin {main => release/config}/geosite.dat | 0 {main => release/config}/route.json | 0 {main => release/config}/rulelist | 0 service/controller/controller_test.go | 2 +- 21 files changed, 158 insertions(+), 103 deletions(-) rename {main => cmd}/distro/all/all.go (100%) rename main/main.go => cmd/root.go (63%) create mode 100644 cmd/version.go create mode 100644 cmd/x25519.go create mode 100644 main.go rename {main => release/config}/config.yml.example (96%) rename {main => release/config}/custom_inbound.json (100%) rename {main => release/config}/custom_outbound.json (100%) rename {main => release/config}/dns.json (100%) rename {main => release/config}/geoip.dat (100%) rename {main => release/config}/geosite.dat (100%) rename {main => release/config}/route.json (100%) rename {main => release/config}/rulelist (100%) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a520163..8b9fa02 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -122,12 +122,12 @@ jobs: - name: Build XrayR run: | mkdir -p build_assets - go build -v -o build_assets/XrayR -trimpath -ldflags "-s -w -buildid=" ./main + go build -v -o build_assets/XrayR -trimpath -ldflags "-s -w -buildid=" - name: Build Mips softfloat XrayR if: matrix.goarch == 'mips' || matrix.goarch == 'mipsle' run: | - GOMIPS=softfloat go build -v -o build_assets/XrayR_softfloat -trimpath -ldflags "-s -w -buildid=" ./main + GOMIPS=softfloat go build -v -o build_assets/XrayR_softfloat -trimpath -ldflags "-s -w -buildid=" - name: Rename Windows XrayR if: matrix.goos == 'windows' run: | @@ -143,12 +143,12 @@ jobs: command: | cp ${GITHUB_WORKSPACE}/README.md ./build_assets/README.md cp ${GITHUB_WORKSPACE}/LICENSE ./build_assets/LICENSE - cp ${GITHUB_WORKSPACE}/main/dns.json ./build_assets/dns.json - cp ${GITHUB_WORKSPACE}/main/route.json ./build_assets/route.json - cp ${GITHUB_WORKSPACE}/main/custom_outbound.json ./build_assets/custom_outbound.json - cp ${GITHUB_WORKSPACE}/main/custom_inbound.json ./build_assets/custom_inbound.json - cp ${GITHUB_WORKSPACE}/main/rulelist ./build_assets/rulelist - cp ${GITHUB_WORKSPACE}/main/config.yml.example ./build_assets/config.yml + cp ${GITHUB_WORKSPACE}/release/config/dns.json ./build_assets/dns.json + cp ${GITHUB_WORKSPACE}/release/config/route.json ./build_assets/route.json + cp ${GITHUB_WORKSPACE}/release/config/custom_outbound.json ./build_assets/custom_outbound.json + cp ${GITHUB_WORKSPACE}/release/config/custom_inbound.json ./build_assets/custom_inbound.json + cp ${GITHUB_WORKSPACE}/release/config/rulelist ./build_assets/rulelist + cp ${GITHUB_WORKSPACE}/release/config/config.yml.example ./build_assets/config.yml LIST=('geoip geoip geoip' 'domain-list-community dlc geosite') for i in "${LIST[@]}" do diff --git a/.gitignore b/.gitignore index 7e035eb..0aada64 100644 --- a/.gitignore +++ b/.gitignore @@ -1,18 +1,20 @@ -main/main -main/XrayR -main/XrayR* -main/mytest -main/access.logo -main/error.log -api/chooseparser.go.bak -common/Inboundbuilder/.lego/ -common/legocmd/.lego/ -.vscode/launch.json -main/.lego -main/cert -main/config.yml -./vscode -.idea/* -.DS_Store -*.bak -go.work* \ No newline at end of file +.idea +*.iml +out +gen +*.exe +*.exe~ +*.dll +*.so +*.dylib +*.test +*.out +go.work +main +XrayR +XrayR* +access.log +error.log +.lego +cert +config.yml \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index c2ccdb8..380a69b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,7 +4,7 @@ WORKDIR /app COPY . . ENV CGO_ENABLED=0 RUN go mod download -RUN go build -v -o XrayR -trimpath -ldflags "-s -w -buildid=" ./main +RUN go build -v -o XrayR -trimpath -ldflags "-s -w -buildid=" # Release FROM alpine diff --git a/main/distro/all/all.go b/cmd/distro/all/all.go similarity index 100% rename from main/distro/all/all.go rename to cmd/distro/all/all.go diff --git a/main/main.go b/cmd/root.go similarity index 63% rename from main/main.go rename to cmd/root.go index 03fb3e4..259cb5f 100644 --- a/main/main.go +++ b/cmd/root.go @@ -1,7 +1,6 @@ -package main +package cmd import ( - "flag" "fmt" "log" "os" @@ -13,37 +12,37 @@ import ( "time" "github.com/fsnotify/fsnotify" + "github.com/spf13/cobra" "github.com/spf13/viper" - "github.com/XrayR-project/XrayR/common" "github.com/XrayR-project/XrayR/panel" ) var ( - configFile = flag.String("config", "", "Config file for XrayR.") - printVersion = flag.Bool("version", false, "show version") - x25519 = flag.Bool("x25519", false, "Generate key pair for x25519 key exchange") + cfgFile string + rootCmd = &cobra.Command{ + Use: "XrayR", + Run: func(cmd *cobra.Command, args []string) { + if err := run(); err != nil { + log.Fatal(err) + } + }, + } ) -var ( - version = "0.9.1" - codename = "XrayR" - intro = "A Xray backend that supports many panels" -) - -func showVersion() { - fmt.Printf("%s %s (%s) \n", codename, version, intro) +func init() { + rootCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", "", "Config file for XrayR.") } func getConfig() *viper.Viper { config := viper.New() // Set custom path and name - if *configFile != "" { - configName := path.Base(*configFile) - configFileExt := path.Ext(*configFile) + if cfgFile != "" { + configName := path.Base(cfgFile) + configFileExt := path.Ext(cfgFile) configNameOnly := strings.TrimSuffix(configName, configFileExt) - configPath := path.Dir(*configFile) + configPath := path.Dir(cfgFile) config.SetConfigName(configNameOnly) config.SetConfigType(strings.TrimPrefix(configFileExt, ".")) config.AddConfigPath(configPath) @@ -67,21 +66,13 @@ func getConfig() *viper.Viper { return config } -func main() { - flag.Parse() +func run() error { showVersion() - if *printVersion { - return - } - if *x25519 { - common.X25519() - return - } config := getConfig() panelConfig := &panel.Config{} if err := config.Unmarshal(panelConfig); err != nil { - log.Panicf("Parse config file %v failed: %s \n", configFile, err) + return fmt.Errorf("Parse config file %v failed: %s \n", cfgFile, err) } p := panel.New(panelConfig) lastTime := time.Now() @@ -94,7 +85,7 @@ func main() { // Delete old instance and trigger GC runtime.GC() if err := config.Unmarshal(panelConfig); err != nil { - log.Panicf("Parse config file %v failed: %s \n", configFile, err) + log.Panicf("Parse config file %v failed: %s \n", cfgFile, err) } p.Start() lastTime = time.Now() @@ -106,9 +97,13 @@ func main() { // Explicitly triggering GC to remove garbage from config loading. runtime.GC() // Running backend - { - osSignals := make(chan os.Signal, 1) - signal.Notify(osSignals, os.Interrupt, os.Kill, syscall.SIGTERM) - <-osSignals - } + osSignals := make(chan os.Signal, 1) + signal.Notify(osSignals, os.Interrupt, os.Kill, syscall.SIGTERM) + <-osSignals + + return nil +} + +func Execute() error { + return rootCmd.Execute() } diff --git a/cmd/version.go b/cmd/version.go new file mode 100644 index 0000000..294e9b2 --- /dev/null +++ b/cmd/version.go @@ -0,0 +1,27 @@ +package cmd + +import ( + "fmt" + + "github.com/spf13/cobra" +) + +var ( + version = "0.9.1" + codename = "XrayR" + intro = "A Xray backend that supports many panels" +) + +func init() { + rootCmd.AddCommand(&cobra.Command{ + Use: "version", + Short: "Print current version of XrayR", + Run: func(cmd *cobra.Command, args []string) { + showVersion() + }, + }) +} + +func showVersion() { + fmt.Printf("%s %s (%s) \n", codename, version, intro) +} diff --git a/cmd/x25519.go b/cmd/x25519.go new file mode 100644 index 0000000..fb121e8 --- /dev/null +++ b/cmd/x25519.go @@ -0,0 +1,48 @@ +package cmd + +import ( + "crypto/rand" + "encoding/base64" + "fmt" + + "github.com/spf13/cobra" + "golang.org/x/crypto/curve25519" +) + +func init() { + rootCmd.AddCommand(&cobra.Command{ + Use: "x25519", + Short: "Generate key pair for x25519 key exchange", + Run: func(cmd *cobra.Command, args []string) { + if err := x25519(); err != nil { + fmt.Println(err) + } + }, + }) +} + +func x25519() error { + var publicKey []byte + privateKey := make([]byte, curve25519.ScalarSize) + if _, err := rand.Read(privateKey); err != nil { + return err + } + + // Modify random bytes using algorithm described at: + // https://cr.yp.to/ecdh.html. + privateKey[0] &= 248 + privateKey[31] &= 127 + privateKey[31] |= 64 + + publicKey, err := curve25519.X25519(privateKey, curve25519.Basepoint) + if err != nil { + return err + } + + output := fmt.Sprintf("Private key: %v\nPublic key: %v", + base64.RawURLEncoding.EncodeToString(privateKey), + base64.RawURLEncoding.EncodeToString(publicKey)) + fmt.Println(output) + + return nil +} diff --git a/common/common.go b/common/common.go index b7a8d38..a7d06d5 100644 --- a/common/common.go +++ b/common/common.go @@ -1,36 +1,2 @@ // Package common contains common utilities that are shared among other packages. package common - -import ( - "crypto/rand" - "encoding/base64" - "fmt" - - "golang.org/x/crypto/curve25519" -) - -func X25519() { - var publicKey []byte - privateKey := make([]byte, curve25519.ScalarSize) - if _, err := rand.Read(privateKey); err != nil { - fmt.Println(err) - return - } - - // Modify random bytes using algorithm described at: - // https://cr.yp.to/ecdh.html. - privateKey[0] &= 248 - privateKey[31] &= 127 - privateKey[31] |= 64 - - publicKey, err := curve25519.X25519(privateKey, curve25519.Basepoint) - if err != nil { - fmt.Println(err) - return - } - - output := fmt.Sprintf("Private key: %v\nPublic key: %v", - base64.RawURLEncoding.EncodeToString(privateKey), - base64.RawURLEncoding.EncodeToString(publicKey)) - fmt.Println(output) -} diff --git a/go.mod b/go.mod index f8e47d6..561ccd2 100644 --- a/go.mod +++ b/go.mod @@ -21,6 +21,7 @@ require ( github.com/sagernet/sing v0.2.13 github.com/sagernet/sing-shadowsocks v0.2.5 github.com/shirou/gopsutil/v3 v3.23.9 + github.com/spf13/cobra v1.1.1 github.com/spf13/viper v1.17.0 github.com/stretchr/testify v1.8.4 github.com/xtls/xray-core v1.8.4 @@ -112,6 +113,7 @@ require ( github.com/hashicorp/go-retryablehttp v0.7.4 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df // indirect + github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/infobloxopen/infoblox-go-client v1.1.1 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/json-iterator/go v1.1.12 // indirect diff --git a/go.sum b/go.sum index 0faca5e..55fd346 100644 --- a/go.sum +++ b/go.sum @@ -468,6 +468,7 @@ github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1: github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df h1:MZf03xP9WdakyXhOWuAD5uPK3wHh96wCsqe3hCMKh8E= github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df/go.mod h1:QMZY7/J/KSQEhKWFeDesPjMj+wCHReeknARU3wqlyN4= +github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/infobloxopen/infoblox-go-client v1.1.1 h1:728A6LbLjptj/7kZjHyIxQnm768PWHfGFm0HH8FnbtU= github.com/infobloxopen/infoblox-go-client v1.1.1/go.mod h1:BXiw7S2b9qJoM8MS40vfgCNB2NLHGusk1DtO16BD9zI= @@ -834,6 +835,7 @@ github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA= github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48= +github.com/spf13/cobra v1.1.1 h1:KfztREH0tPxJJ+geloSLaAkaPkr4ki2Er5quFV1TDo4= github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= diff --git a/main.go b/main.go new file mode 100644 index 0000000..0045a9f --- /dev/null +++ b/main.go @@ -0,0 +1,13 @@ +package main + +import ( + "log" + + "github.com/XrayR-project/XrayR/cmd" +) + +func main() { + if err := cmd.Execute(); err != nil { + log.Fatal(err) + } +} diff --git a/panel/panel.go b/panel/panel.go index d4a0ef7..c789a7f 100644 --- a/panel/panel.go +++ b/panel/panel.go @@ -23,7 +23,7 @@ import ( "github.com/XrayR-project/XrayR/api/proxypanel" "github.com/XrayR-project/XrayR/api/sspanel" "github.com/XrayR-project/XrayR/api/v2raysocks" - _ "github.com/XrayR-project/XrayR/main/distro/all" + _ "github.com/XrayR-project/XrayR/cmd/distro/all" "github.com/XrayR-project/XrayR/service" "github.com/XrayR-project/XrayR/service/controller" ) diff --git a/main/config.yml.example b/release/config/config.yml.example similarity index 96% rename from main/config.yml.example rename to release/config/config.yml.example index d424d10..f6eae73 100644 --- a/main/config.yml.example +++ b/release/config/config.yml.example @@ -56,11 +56,11 @@ Nodes: EnableREALITY: false # Enable REALITY REALITYConfigs: Show: true # Show REALITY debug - Dest: www.smzdm.com:443 # Required, Same as fallback + Dest: www.amazon.com:443 # Required, Same as fallback ProxyProtocolVer: 0 # Send PROXY protocol version, 0 for disable ServerNames: # Required, list of available serverNames for the client, * wildcard is not supported at the moment. - - www.smzdm.com - PrivateKey: YOUR_PRIVATE_KEY # Required, execute './XrayR -x25519' to generate. + - www.amazon.com + PrivateKey: YOUR_PRIVATE_KEY # Required, execute './XrayR x25519' to generate. MinClientVer: # Optional, minimum version of Xray client, format is x.y.z. MaxClientVer: # Optional, maximum version of Xray client, format is x.y.z. MaxTimeDiff: 0 # Optional, maximum allowed time difference, unit is in milliseconds. @@ -119,11 +119,11 @@ Nodes: # EnableREALITY: true # Enable REALITY # REALITYConfigs: # Show: true # Show REALITY debug -# Dest: www.smzdm.com:443 # Required, Same as fallback +# Dest: www.amazon.com:443 # Required, Same as fallback # ProxyProtocolVer: 0 # Send PROXY protocol version, 0 for disable # ServerNames: # Required, list of available serverNames for the client, * wildcard is not supported at the moment. -# - www.smzdm.com -# PrivateKey: YOUR_PRIVATE_KEY # Required, execute './xray x25519' to generate. +# - www.amazon.com +# PrivateKey: YOUR_PRIVATE_KEY # Required, execute './XrayR x25519' to generate. # MinClientVer: # Optional, minimum version of Xray client, format is x.y.z. # MaxClientVer: # Optional, maximum version of Xray client, format is x.y.z. # MaxTimeDiff: 0 # Optional, maximum allowed time difference, unit is in milliseconds. diff --git a/main/custom_inbound.json b/release/config/custom_inbound.json similarity index 100% rename from main/custom_inbound.json rename to release/config/custom_inbound.json diff --git a/main/custom_outbound.json b/release/config/custom_outbound.json similarity index 100% rename from main/custom_outbound.json rename to release/config/custom_outbound.json diff --git a/main/dns.json b/release/config/dns.json similarity index 100% rename from main/dns.json rename to release/config/dns.json diff --git a/main/geoip.dat b/release/config/geoip.dat similarity index 100% rename from main/geoip.dat rename to release/config/geoip.dat diff --git a/main/geosite.dat b/release/config/geosite.dat similarity index 100% rename from main/geosite.dat rename to release/config/geosite.dat diff --git a/main/route.json b/release/config/route.json similarity index 100% rename from main/route.json rename to release/config/route.json diff --git a/main/rulelist b/release/config/rulelist similarity index 100% rename from main/rulelist rename to release/config/rulelist diff --git a/service/controller/controller_test.go b/service/controller/controller_test.go index f290f10..008171d 100644 --- a/service/controller/controller_test.go +++ b/service/controller/controller_test.go @@ -13,8 +13,8 @@ import ( "github.com/XrayR-project/XrayR/api" "github.com/XrayR-project/XrayR/api/sspanel" + _ "github.com/XrayR-project/XrayR/cmd/distro/all" "github.com/XrayR-project/XrayR/common/mylego" - _ "github.com/XrayR-project/XrayR/main/distro/all" . "github.com/XrayR-project/XrayR/service/controller" )