Enhance Proxy and Configuration Management

- Implemented comprehensive VMESS proxy installation with dynamic configuration
- Added support for Xray installation and configuration generation
- Introduced hostname normalization with city, architecture, and IP-based naming
- Updated proxy commands to include VMESS and VLESS subcommands
- Improved configuration management with NormalizeConfig method
- Enhanced logging and error handling for proxy-related operations
This commit is contained in:
zeaslity
2025-02-28 23:58:38 +08:00
parent 5c39bd7594
commit db3d259a0a
8 changed files with 376 additions and 29 deletions

View File

@@ -1,7 +1,17 @@
package cmd
import (
"agent-wdd/cmd/xray"
"agent-wdd/config"
"agent-wdd/log"
"agent-wdd/op"
"agent-wdd/utils"
"bytes"
"encoding/json"
"fmt"
"os"
"text/template"
"github.com/spf13/cobra"
)
@@ -16,23 +26,256 @@ func addProxySubcommands(cmd *cobra.Command) {
Use: "install",
Short: "安装Xray",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("Installing Xray...")
log.Info("Installing Xray...")
installXray()
},
},
// 其他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,
&cobra.Command{
Use: "vmess",
Short: "设置VMESS代理",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("Setting up VMESS proxy...")
},
},
vmessCmd,
vlessCmd,
// 其他proxy子命令...
)
}
// 其他命令结构类似,根据需求补充完整...
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(),
}
}
// 将result 打印的终端
fmt.Println("vmess client config is below: ")
fmt.Println(string(result.Bytes()))
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)
// 执行安装脚本
op.SingleLineCommandExecutor([]string{
"/bin/bash",
"/tmp/install-release.sh",
"-u root",
"install",
})
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")
}