From acd6eae41db3f653bd648fd327198fc4c984da0e Mon Sep 17 00:00:00 2001 From: samwaf Date: Mon, 19 Jun 2023 16:27:30 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9A=82=E5=AD=98windows=E5=8D=95=E7=8B=AC?= =?UTF-8?q?=E5=86=99=E7=9A=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build-releases-upx.bat | 5 + build-releases.bat | 2 +- build_docker_release_linux.bat | 2 +- main.go | 90 +++++++++------- utils/common.go | 17 ++++ wafenginecore/localdb.go | 5 +- wafenginecore/wafengine.go | 10 +- wafsystem/wafsystem_linux.go | 181 +++++++++++++++++++++++++++++++++ wafsystem/wafsystem_win.go | 171 +++++++++++++++++++++++++++++++ 编译说明.md | 4 +- 10 files changed, 444 insertions(+), 43 deletions(-) create mode 100644 build-releases-upx.bat create mode 100644 wafsystem/wafsystem_linux.go create mode 100644 wafsystem/wafsystem_win.go diff --git a/build-releases-upx.bat b/build-releases-upx.bat new file mode 100644 index 0000000..b13c6fa --- /dev/null +++ b/build-releases-upx.bat @@ -0,0 +1,5 @@ +SET CGO_ENABLED=1 +SET GOOS=windows +SET GOARCH=amd64 +SET GIN_MODE=release +go build -ldflags="-X SamWaf/global.GWAF_RELEASE=true -X SamWaf/global.GWAF_RELEASE_VERSION_NAME=20230619 -X SamWaf/global.GWAF_RELEASE_VERSION=101 -s -w" -o %cd%/release/SamWaf64.exe main.go && %cd%/upx/win64/upx -9 %cd%/release/SamWaf64.exe diff --git a/build-releases.bat b/build-releases.bat index 8efcd44..6a21a2a 100644 --- a/build-releases.bat +++ b/build-releases.bat @@ -2,4 +2,4 @@ SET CGO_ENABLED=1 SET GOOS=windows SET GOARCH=amd64 SET GIN_MODE=release -go build -ldflags="-X SamWaf/global.GWAF_RELEASE=true -X SamWaf/global.GWAF_RELEASE_VERSION_NAME=20230604 -X SamWaf/global.GWAF_RELEASE_VERSION=100 -s -w" -o %cd%/release/SamWaf64.exe main.go && %cd%/upx/win64/upx -9 %cd%/release/SamWaf64.exe +go build -ldflags="-X SamWaf/global.GWAF_RELEASE=true -X SamWaf/global.GWAF_RELEASE_VERSION_NAME=20230619 -X SamWaf/global.GWAF_RELEASE_VERSION=101 -s -w" -o %cd%/release/SamWaf64.exe main.go diff --git a/build_docker_release_linux.bat b/build_docker_release_linux.bat index 2449ce9..f26310a 100644 --- a/build_docker_release_linux.bat +++ b/build_docker_release_linux.bat @@ -1 +1 @@ -docker run --rm -v "$PWD":/media/sf_SamWaf -w /media/sf_SamWaf -e CGO_ENABLED=1 -e GOPROXY=https://goproxy.cn,direct golang:1.19 go build -v -ldflags="-X SamWaf/global.GWAF_RELEASE=true -X SamWaf/global.GWAF_RELEASE_VERSION_NAME=20230609 -X SamWaf/global.GWAF_RELEASE_VERSION=100 -s -w -extldflags "-static"" -o /media/sf_SamWaf/release/SamWafLinux64 main.go \ No newline at end of file +docker run --rm -v "$PWD":/media/sf_SamWaf -w /media/sf_SamWaf -e CGO_ENABLED=1 -e GOPROXY=https://goproxy.cn,direct golang:1.19 go build -v -ldflags="-X SamWaf/global.GWAF_RELEASE=true -X SamWaf/global.GWAF_RELEASE_VERSION_NAME=20230619 -X SamWaf/global.GWAF_RELEASE_VERSION=101 -s -w -extldflags "-static"" -o /media/sf_SamWaf/release/SamWafLinux64 main.go \ No newline at end of file diff --git a/main.go b/main.go index f374a15..58a9e5f 100644 --- a/main.go +++ b/main.go @@ -10,15 +10,16 @@ import ( "SamWaf/utils" "SamWaf/utils/zlog" "SamWaf/wafenginecore" + "SamWaf/wafsystem" "SamWaf/waftask" "SamWaf/xdaemon" "crypto/tls" + "fmt" dlp "github.com/bytedance/godlp" "github.com/go-co-op/gocron" Wssocket "github.com/gorilla/websocket" "go.uber.org/zap" "golang.org/x/time/rate" - "log" "net/http" "os" "os/exec" @@ -30,6 +31,58 @@ import ( func main() { + fmt.Println(utils.GetCurrentDir()) + // if received any kind of command, do it + if len(os.Args) > 1 { + serviceName := "SamWafService" + + serviceManager := wafsystem.NewWafServiceManager(serviceName) + command := os.Args[1] + switch command { + case "-d": + logFile := utils.GetCurrentDir() + "/logs/daemon.log" + fmt.Println(logFile) + //启动一个子进程后主程序退出 + xdaemon.Background(logFile, true) + break + case "-c": + println("关闭") + if runtime.GOOS == "windows" { + c := exec.Command("taskkill.exe", "/f", "/im", "SamWaf.exe") + c.Start() + } else { + println("SamWaf -d") + } + break + + case "-install": + serviceManager.Install() + return + break + case "-uninstall": + serviceManager.Uninstall() + return + break + case "-stop": + serviceManager.Stop() + return + break + case "-start": + serviceManager.StartService() + return + break + case "-help": + if runtime.GOOS == "windows" { + println("SamWaf.exe -d 是后台运行, -install 是以服务安装 ,-uninstall 卸载服务 ,-stop 暂停服务") + } else { + println("SamWaf -d 是后台运行 , -install 是以服务安装 ,-uninstall 卸载服务 ,-stop 暂停服务") + } + break + default: + println(command) + } + } + rversion := "初始化系统 版本号:" + global.GWAF_RELEASE_VERSION_NAME + "(" + global.GWAF_RELEASE_VERSION + ")" if global.GWAF_RELEASE == "false" { rversion = rversion + " 调试版本" @@ -46,40 +99,7 @@ func main() { global.GWAF_LAST_UPDATE_TIME = time.Now() - pwd, err := os.Getwd() - syscall.Setenv("ZONEINFO", pwd+"//data//zoneinfo") - if err != nil { - log.Fatal(err) - } - // if received any kind of command, do it - if len(os.Args) > 1 { - command := os.Args[1] - switch command { - case "-d": - logFile := "./logs/daemon.log" - //启动一个子进程后主程序退出 - xdaemon.Background(logFile, true) - break - case "-c": - println("关闭") - if runtime.GOOS == "windows" { - c := exec.Command("taskkill.exe", "/f", "/im", "SamWaf.exe") - c.Start() - } else { - println("SamWaf -d") - } - break - case "-help": - if runtime.GOOS == "windows" { - println("SamWaf.exe -d 是后台运行 -c 是强制关闭 -help 是帮助说明") - } else { - println("SamWaf -d 是后台运行 -c 是强制关闭 -help 是帮助说明") - } - break - default: - println(command) - } - } + syscall.Setenv("ZONEINFO", utils.GetCurrentDir()+"//data//zoneinfo") //守护程序开始 //xdaemon.DaemonProcess("GoTest.exe","./logs/damon.log") diff --git a/utils/common.go b/utils/common.go index 4be0a26..0abc1b1 100644 --- a/utils/common.go +++ b/utils/common.go @@ -7,11 +7,28 @@ import ( "fmt" "github.com/lionsoul2014/ip2region/binding/golang/xdb" "net" + "os" + "path/filepath" "strconv" "strings" "time" ) +func GetCurrentDir() string { + /* pwd, err := os.Getwd() + if err != nil { + fmt.Errorf("currentPath") + } + return pwd*/ + exePath, err := os.Executable() + if err != nil { + fmt.Println("Failed to get executable path:", err) + return "" + } + + exeDir := filepath.Dir(exePath) + return exeDir +} func GetServerByHosts(hosts model.Hosts) string { if hosts.Ssl == 1 { return "https" diff --git a/wafenginecore/localdb.go b/wafenginecore/localdb.go index 3b3ad38..ad12898 100644 --- a/wafenginecore/localdb.go +++ b/wafenginecore/localdb.go @@ -4,6 +4,7 @@ import ( "SamWaf/global" "SamWaf/innerbean" "SamWaf/model" + "SamWaf/utils" "SamWaf/utils/zlog" "gorm.io/driver/sqlite" "gorm.io/gorm" @@ -11,7 +12,7 @@ import ( func InitDb() { if global.GWAF_LOCAL_DB == nil { - db, err := gorm.Open(sqlite.Open("data/local.db"), &gorm.Config{}) + db, err := gorm.Open(sqlite.Open(utils.GetCurrentDir()+"/data/local.db"), &gorm.Config{}) if err != nil { panic("failed to connect database") } @@ -48,7 +49,7 @@ func InitDb() { } if global.GWAF_LOCAL_LOG_DB == nil { - logDB, err := gorm.Open(sqlite.Open("data/local_log.db"), &gorm.Config{}) + logDB, err := gorm.Open(sqlite.Open(utils.GetCurrentDir()+"/data/local_log.db"), &gorm.Config{}) if err != nil { panic("failed to connect database") } diff --git a/wafenginecore/wafengine.go b/wafenginecore/wafengine.go index a2f0fd8..e712bc9 100644 --- a/wafenginecore/wafengine.go +++ b/wafenginecore/wafengine.go @@ -424,7 +424,7 @@ func (waf *WafEngine) Start_WAF() { global.GWAF_LOCAL_DB.Where("tenant_id = ? and user_code=? ", global.GWAF_TENANT_ID, global.GWAF_USER_CODE).Where("user_code = ?", global.GWAF_USER_CODE).Find(&hosts) //初始化步骤[加载ip数据库] - var dbPath = "data/ip2region.xdb" + var dbPath = utils.GetCurrentDir() + "/data/ip2region.xdb" // 1、从 dbPath 加载整个 xdb 到内存 cBuff, err := xdb.LoadContentFromFile(dbPath) if err != nil { @@ -543,6 +543,12 @@ func (waf *WafEngine) Start_WAF() { if (innruntime.ServerType) == "https" { + defer func() { + e := recover() + if e != nil { // 捕获该协程的panic 111111 + zlog.Warn("https recover ", e) + } + }() svr := &http.Server{ Addr: ":" + strconv.Itoa(innruntime.Port), Handler: waf, @@ -584,7 +590,7 @@ func (waf *WafEngine) Start_WAF() { defer func() { e := recover() if e != nil { // 捕获该协程的panic 111111 - zlog.Warn("recover ", e) + zlog.Warn("http recover ", e) } }() svr := &http.Server{ diff --git a/wafsystem/wafsystem_linux.go b/wafsystem/wafsystem_linux.go new file mode 100644 index 0000000..af7ba2d --- /dev/null +++ b/wafsystem/wafsystem_linux.go @@ -0,0 +1,181 @@ +//go:build linux +// +build linux + +package wafsystem + +import ( + "fmt" + "os" + "os/exec" +) + +// WafServiceManager 封装了 Linux 平台的服务管理方法 +type WafServiceManager struct { + serviceName string +} + +// NewWafServiceManager 创建一个新的 WafServiceManager 实例 +func NewWafServiceManager(serviceName string) *WafServiceManager { + return &WafServiceManager{ + serviceName: serviceName, + } +} + +// Install 安装服务 +func (sm *WafServiceManager) Install() { + if sm.serviceExists() { + fmt.Println("Service", sm.serviceName, "already exists.") + } else { + fmt.Println("Service", sm.serviceName, "does not exist.") + sm.installServiceLinux() + } +} + +// Uninstall 卸载服务 +func (sm *WafServiceManager) Uninstall() { + sm.uninstallServiceLinux() +} + +// Pause 暂停服务 +func (sm *WafServiceManager) Pause() { + fmt.Println("Pause service functionality is not available on Linux.") +} + +// serviceExists 检查服务是否存在 +func (sm *WafServiceManager) serviceExists() bool { + cmd := exec.Command("systemctl", "is-active", sm.serviceName) + err := cmd.Run() + if err == nil { + return true + } + return false +} + +// installServiceLinux 安装服务(Linux) +func (sm *WafServiceManager) installServiceLinux() { + executablePath, err := os.Executable() + if err != nil { + fmt.Println("Failed to get executable path:", err) + return + } + + serviceContent := fmt.Sprintf(`[Unit] +Description=SamWaf is a Web Application Firewall (WAF). +After=network.target + +[Service] +ExecStart=%s +WorkingDirectory=%s +Restart=always +User=%s + +[Install] +WantedBy=default.target`, executablePath, executablePath, os.Getenv("USER")) + + // 创建服务文件 + err = ioutil.WriteFile(fmt.Sprintf("/etc/systemd/system/%s.service", sm.serviceName), []byte(serviceContent), 0644) + if err != nil { + fmt.Println("Failed to create service file:", err) + return + } + + // 重新加载 systemd 配置 + cmd := exec.Command("systemctl", "daemon-reload") + err = cmd.Run() + if err != nil { + fmt.Println("Failed to reload systemd configuration:", err) + return + } + + // 启动服务 + cmd = exec.Command("systemctl", "start", sm.serviceName) + err = cmd.Run() + if err != nil { + fmt.Println("Failed to start service:", err) + return + } + + // 设置服务自动启动 + cmd = exec.Command("systemctl", "enable", sm.serviceName) + err = cmd.Run() + if err != nil { + fmt.Println("Failed to enable service auto-start:", err) + return + } + + fmt.Println("Successfully installed and started the service", sm.serviceName) +} + +// uninstallServiceLinux 卸载服务(Linux) +func (sm *WafServiceManager) uninstallServiceLinux() { + cmd := exec.Command("systemctl", "stop", sm.serviceName) + err := cmd.Run() + if err != nil { + fmt.Println("Failed to stop service:", err) + return + } + + cmd = exec.Command("systemctl", "disable", sm.serviceName) + err = cmd.Run() + if err != nil { + fmt.Println("Failed to disable service auto-start:", err) + return + } + + serviceFile := fmt.Sprintf("/etc/systemd/system/%s.service", sm.serviceName) + err = os.Remove(serviceFile) + if err != nil { + fmt.Println("Failed to delete service file:", err) + return + } + + cmd = exec.Command("systemctl", "daemon-reload") + err = cmd.Run() + if err != nil { + fmt.Println("Failed to reload systemd configuration:", err) + return + } + + fmt.Println("Successfully uninstalled the service", sm.serviceName) +} +func (sm *WafServiceManager) IsServiceRunning() (bool, error) { + cmd := exec.Command("systemctl", "is-active", sm.serviceName) + + output, err := cmd.Output() + if err != nil { + if exitErr, ok := err.(*exec.ExitError); ok { + if exitErr.ExitCode() == 3 { + // Service is not running + return false, nil + } + } + return false, fmt.Errorf("failed to query service status: %w", err) + } + + status := string(output) + status = strings.ToLower(strings.TrimSpace(status)) + + return status == "active", nil +} + +func (sm *WafServiceManager) StartService() error { + cmd := exec.Command("systemctl", "start", sm.serviceName) + + err := cmd.Run() + if err != nil { + return fmt.Errorf("failed to start service: %w", err) + } + + return nil +} + +func (sm *WafServiceManager) StopService() error { + cmd := exec.Command("systemctl", "stop", sm.serviceName) + + err := cmd.Run() + if err != nil { + return fmt.Errorf("failed to stop service: %w", err) + } + + return nil +} diff --git a/wafsystem/wafsystem_win.go b/wafsystem/wafsystem_win.go new file mode 100644 index 0000000..0764bfa --- /dev/null +++ b/wafsystem/wafsystem_win.go @@ -0,0 +1,171 @@ +//go:build windows +// +build windows + +package wafsystem + +import ( + "fmt" + "io/ioutil" + "os" + "os/exec" + "strings" +) + +// WafServiceManager 封装了 Windows 平台的服务管理方法 +type WafServiceManager struct { + serviceName string + runAsAdmin bool +} + +// NewWafServiceManager 创建一个新的 WafServiceManager 实例 +func NewWafServiceManager(serviceName string) *WafServiceManager { + return &WafServiceManager{ + serviceName: serviceName, + } +} + +// Install 安装服务 +func (sm *WafServiceManager) Install() { + if sm.serviceExists() { + fmt.Println("Service", sm.serviceName, "already exists.") + } else { + fmt.Println("Service", sm.serviceName, "does not exist.") + sm.installServiceWindows() + } +} + +// Uninstall 卸载服务 +func (sm *WafServiceManager) Uninstall() { + sm.uninstallServiceWindows() +} + +// Pause 暂停服务 +func (sm *WafServiceManager) Stop() { + sm.stopServiceWindows() +} + +// serviceExists 检查服务是否存在 +func (sm *WafServiceManager) serviceExists() bool { + cmd := exec.Command("sc", "query", sm.serviceName) + output, err := cmd.Output() + if err == nil && strings.Contains(string(output), "SERVICE_NAME: "+sm.serviceName) { + return true + } + return false +} + +// installServiceWindows 安装服务(Windows) +func (sm *WafServiceManager) installServiceWindows() { + executablePath, err := os.Executable() + if err != nil { + fmt.Println("Failed to get executable path:", err) + return + } + + serviceContent := fmt.Sprintf(`[Unit] +Description=SamWaf is a Web Application Firewall (WAF) + +[Service] +ExecStart=%s + +[Install] +WantedBy=multi-user.target`, executablePath) + + // 创建服务配置文件 + err = ioutil.WriteFile(fmt.Sprintf("%s.service", sm.serviceName), []byte(serviceContent), 0644) + if err != nil { + fmt.Println("Failed to create service configuration file:", err) + return + } + + // 创建服务 + cmd := exec.Command("sc", "create", sm.serviceName, "binPath= \""+executablePath+" -d\"") + err = cmd.Run() + if err != nil { + fmt.Println("Failed to create service:", err) + return + } + isRunning, err := sm.IsServiceRunning() + if err != nil { + fmt.Println("Error:", err) + os.Exit(1) + } + + if !isRunning { + fmt.Println("Service is not running.") + sm.StartService() + } + + // 设置服务自动启动 + cmd = exec.Command("sc", "config", sm.serviceName, "start=auto") + err = cmd.Run() + if err != nil { + fmt.Println("Failed to set service auto-start:", err) + return + } + + fmt.Println("Successfully installed and started the service", sm.serviceName) +} + +// uninstallServiceWindows 卸载服务(Windows) +func (sm *WafServiceManager) uninstallServiceWindows() { + isRunning, err := sm.IsServiceRunning() + if err != nil { + fmt.Println("Error:", err) + os.Exit(1) + } + + if isRunning { + fmt.Println("Service is already running.") + sm.stopServiceWindows() + } + + cmd := exec.Command("sc", "delete", sm.serviceName) + err = cmd.Run() + if err != nil { + fmt.Println("Failed to delete service:", err) + return + } + + fmt.Println("Successfully uninstalled the service", sm.serviceName) +} + +// stopServiceWindows 暂停服务(Windows) +func (sm *WafServiceManager) stopServiceWindows() { + cmd := exec.Command("sc", "stop", sm.serviceName) + err := cmd.Run() + if err != nil { + fmt.Println("Failed to stop service:", err) + return + } + + fmt.Println("Successfully paused the service", sm.serviceName) +} +func (sm *WafServiceManager) IsServiceRunning() (bool, error) { + cmd := exec.Command("sc", "query", sm.serviceName) + + output, err := cmd.Output() + if err != nil { + if exitErr, ok := err.(*exec.ExitError); ok { + if exitErr.ExitCode() == 1 { + // Service is not running + return false, nil + } + } + return false, fmt.Errorf("failed to query service status: %w", err) + } + + status := string(output) + status = strings.ToLower(strings.TrimSpace(status)) + + return status == "running", nil +} +func (sm *WafServiceManager) StartService() error { + cmd := exec.Command("sc", "start", sm.serviceName) + err := cmd.Run() + if err != nil { + return fmt.Errorf("failed to start service: %w", err) + } + + return nil +} diff --git a/编译说明.md b/编译说明.md index c2aaf79..de9e705 100644 --- a/编译说明.md +++ b/编译说明.md @@ -8,11 +8,11 @@ go-bindata-assetfs.exe -o=vue/vue.go -pkg=vue vue/dist/... # linux //生成普通发行版(未upx压缩的) -docker run --rm -v "$PWD":/media/sf_SamWaf -w /media/sf_SamWaf -e CGO_ENABLED=1 -e GOPROXY=https://goproxy.cn,direct golang:1.19 go build -v -ldflags="-X SamWaf/global.GWAF_RELEASE=true -X SamWaf/global.GWAF_RELEASE_VERSION_NAME=20230604 -X SamWaf/global.GWAF_RELEASE_VERSION=100 -s -w -extldflags "-static"" -o /media/sf_SamWaf/release/SamWafLinux64 main.go +docker run --rm -v "$PWD":/media/sf_SamWaf -w /media/sf_SamWaf -e CGO_ENABLED=1 -e GOPROXY=https://goproxy.cn,direct golang:1.19 go build -v -ldflags="-X SamWaf/global.GWAF_RELEASE=true -X SamWaf/global.GWAF_RELEASE_VERSION_NAME=20230619 -X SamWaf/global.GWAF_RELEASE_VERSION=101 -s -w -extldflags "-static"" -o /media/sf_SamWaf/release/SamWafLinux64 main.go //可调试的centos -docker run --rm -v "$PWD":/media/sf_SamWaf -w /media/sf_SamWaf -e CGO_ENABLED=1 -e GOPROXY=https://goproxy.cn,direct golang:1.19 go build -v -ldflags="-X SamWaf/global.GWAF_RELEASE=true -X SamWaf/global.GWAF_RELEASE_VERSION_NAME=20230604 -X SamWaf/global.GWAF_RELEASE_VERSION=100 -s -w -extldflags "-static"" -o /media/sf_SamWaf/release/SamWafLinux64 main.go +docker run --rm -v "$PWD":/media/sf_SamWaf -w /media/sf_SamWaf -e CGO_ENABLED=1 -e GOPROXY=https://goproxy.cn,direct golang:1.19 go build -v -ldflags="-X SamWaf/global.GWAF_RELEASE=true -X SamWaf/global.GWAF_RELEASE_VERSION_NAME=20230619 -X SamWaf/global.GWAF_RELEASE_VERSION=101 -s -w -extldflags "-static"" -o /media/sf_SamWaf/release/SamWafLinux64 main.go //可调试的local ubuntu docker run --rm -v "$PWD":/home/ubuntu/samwaf -w /home/ubuntu/samwaf -e CGO_ENABLED=1 -e GOPROXY=https://goproxy.cn,direct golang:1.19 go build -v -ldflags="-extldflags "-static"" -o /home/ubuntu/samwaf/release/SamWafLinux64.exe main.go