Files
ProjectOctopus/agent-wdd/cmd/Proxy.go
zeaslity 7c92512a7e Improve Xray Proxy Management and Configuration
- Added 'remove' subcommand for Xray proxy
- Enhanced VMESS installation with V2rayNG config generation
- Updated Xray installation process with improved error handling
- Modified vmess template to separate Clash and V2rayNG configurations
- Fixed command existence check in PackageOperator
2025-03-01 00:32:53 +08:00

311 lines
7.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package cmd
import (
"agent-wdd/cmd/xray"
"agent-wdd/config"
"agent-wdd/log"
"agent-wdd/op"
"agent-wdd/utils"
"bytes"
"encoding/base64"
"encoding/json"
"fmt"
"os"
"strings"
"text/template"
"github.com/spf13/cobra"
)
// 添加proxy子命令
func addProxySubcommands(cmd *cobra.Command) {
xrayCmd := &cobra.Command{
Use: "xray",
Short: "Xray相关操作",
}
xrayCmd.AddCommand(
&cobra.Command{
Use: "install",
Short: "安装Xray",
Run: func(cmd *cobra.Command, args []string) {
log.Info("Installing Xray...")
installXray()
},
},
&cobra.Command{
Use: "remove",
Short: "移除Xray",
Run: func(cmd *cobra.Command, args []string) {
log.Info("Removing Xray...")
removeXray()
},
},
// 其他xray子命令...
)
vmessCmd := &cobra.Command{
Use: "vmess [port]",
Short: "VMESS代理安装",
Run: func(cmd *cobra.Command, args []string) {
log.Info("Setting up VMESS proxy...")
var port string
if len(args) == 0 {
log.Info("no port provided, using default port 443")
port = "443"
} else {
port = args[0]
}
// 执行info all命令 获得归一化的名字 高耦合方案 不推荐
// for _, command := range cmd.Parent().Parent().Commands() {
// if command.Name() == "info" {
// command.Run(command, []string{"all"})
// }
// }
// 2. 调用 info all 命令
if err := executeInfoAll(cmd); err != nil {
fmt.Printf("Error executing info all: %v\n", err)
}
installVmess(port)
},
}
vlessCmd := &cobra.Command{
Use: "vless [port]",
Short: "VLESS代理安装",
Run: func(cmd *cobra.Command, args []string) {
log.Info("Setting up VLESS proxy...")
// var port string
// if len(args) == 0 {
// log.Info("no port provided, using default port 443")
// port = "443"
// }
},
}
cmd.AddCommand(
xrayCmd,
vmessCmd,
vlessCmd,
// 其他proxy子命令...
)
}
// 移除Xray
func removeXray() {
}
func executeInfoAll(cmd *cobra.Command) any {
// 获取根命令
rootCmd := cmd.Root()
// 创建临时上下文
infoCmd, _, err := rootCmd.Find([]string{"info", "all"})
if err != nil {
return fmt.Errorf("command not found: %w", err)
}
// 克隆命令避免污染原始配置
clonedCmd := cloneCommand(infoCmd)
// 重置命令状态
clonedCmd.SetArgs([]string{})
clonedCmd.SilenceErrors = true
clonedCmd.SilenceUsage = true
// 执行命令
return clonedCmd.Execute()
}
// 深度克隆命令的工具函数
func cloneCommand(cmd *cobra.Command) *cobra.Command {
cloned := &cobra.Command{
Use: cmd.Use,
Run: cmd.Run,
PreRun: cmd.PreRun,
PostRun: cmd.PostRun,
}
cloned.Flags().AddFlagSet(cmd.Flags())
return cloned
}
// VmessConfig 定义模板数据模型
type VmessConfig struct {
PORT string
UUID string
}
type VmessClientConfig struct {
ServerNodeName string
ServerNodeAddress string
VmessConfig
}
// 安装VMESS代理 最简单快速的模式
func installVmess(port string) (bool, []string) {
// 检查是否安装了xray
if !op.CommandExistsByPath("xray") {
log.Error("Xray is not installed, please install xray first")
return false, []string{"Xray is not installed, please install xray first"}
}
// 构建配置
// 创建新模板并解析
tmpl, err := template.New("vmessConfig").Parse(xray.VmessServerTemplate)
if err != nil {
return false, []string{err.Error()}
}
// 准备模板数据
// 执行 xray uuid 拿到返回值
ok, resultLog := op.SingleLineCommandExecutor([]string{"xray", "uuid"})
if !ok {
return false, resultLog
}
if len(resultLog) == 0 {
return false, []string{
"xray uuid generate error ! cant not get the uuid",
}
}
uuid := resultLog[0]
vmessConfig := VmessConfig{
PORT: port,
UUID: uuid,
}
// 执行模板渲染
var result bytes.Buffer
if err := tmpl.Execute(&result, vmessConfig); err != nil {
return false, []string{
err.Error(),
}
}
// 将result写入到 /usr/local/etc/xray/config.json 中
// 直接访问底层字节切片避免拷贝
data := result.Bytes()
// 快速验证JSON格式
if !json.Valid(data) {
return false, []string{fmt.Sprintf("Invalid JSON format: %s", data)}
}
// 使用适当权限创建文件并写入O_WRONLY|O_CREATE|O_TRUNC, 0644
filename := "/usr/local/etc/xray/config.json"
if err := os.WriteFile(filename, data, 0644); err != nil {
return false, []string{err.Error()}
}
fmt.Println("xray config file is written to ", filename)
// 移除encode自动添加的换行重新缩进格式化
var prettyJSON bytes.Buffer
if err := json.Indent(&prettyJSON, bytes.TrimSpace(data), "", " "); err != nil {
fmt.Printf("JSON indent error: %v\n", err)
}
fmt.Println(prettyJSON.String())
fmt.Println()
// 重启Xray
op.SystemdRestart("xray")
ok, resultLog = op.SystemIsRunning("xray")
if !ok {
log.Error("Xray service is not running => %s Maybe the config file is not valid", resultLog)
return false, resultLog
}
result.Reset() // 清空全局buffer以备后续使用
// 输出 client的配置
configCache := config.ConfigCache
// 获取服务器节点名称
serverNodeName := configCache.Agent.OS.Hostname
vmessClientConfig := VmessClientConfig{
ServerNodeName: serverNodeName,
ServerNodeAddress: configCache.Agent.Network.Public.IPv4,
VmessConfig: vmessConfig,
}
// 执行模板渲染
clientTmpl, err := template.New("vmessClientConfig").Parse(xray.VmessClientTemplate)
if err != nil {
return false, []string{err.Error()}
}
if err := clientTmpl.Execute(&result, vmessClientConfig); err != nil {
return false, []string{
err.Error(),
}
}
lines := strings.Split(string(result.Bytes()), "\n")
// for index, line := range lines {
// fmt.Println(index, line)
// }
// 转换为字节切片并进行Base64编码
v2rayNGConfig := "vmess://" + base64.StdEncoding.EncodeToString([]byte(lines[2]))
// 将result 打印的终端
fmt.Println("Clash client config is below: ")
fmt.Println()
fmt.Println(lines[1])
fmt.Println()
fmt.Println("V2rayNG config is below: ")
fmt.Println()
fmt.Println(v2rayNGConfig)
fmt.Println()
return true, []string{"Xray Configuration file written successfully"}
}
// 安装Xray 最新版本 主机可以联网才可以
func installXray() {
installScriptUrl := "https://gitea.107421.xyz/zeaslity/Xray-install/raw/branch/main/install-release.sh"
// 下载安装脚本
ok, err := utils.DownloadFile(installScriptUrl, "/tmp/install-release.sh")
if !ok {
log.Error("Download Xray install script failed ! from %s error is %s", installScriptUrl, err)
return
}
// 添加执行权限
os.Chmod("/tmp/install-release.sh", 0777)
// 执行安装脚本
ok, resultLog := op.HardCodeCommandExecutor("/bin/bash /tmp/install-release.sh -u root install")
if !ok {
log.Error("Install Xray failed ! error is %s", resultLog)
return
}
op.SystemdUp("xray")
op.SystemdEnable("xray")
// 默认服务已经启动! 检查
ok, resultLog = op.SystemIsRunning("xray")
if !ok {
log.Error("Xray service is not running => %s", resultLog)
return
}
// 安装成功
log.Info("Xray installed successfully")
}