From 1235e36ad3b598d44a2a1ed160f8e403ec12c14b Mon Sep 17 00:00:00 2001 From: samwaf Date: Mon, 28 Oct 2024 14:20:35 +0800 Subject: [PATCH] fix:win7 win2008r2 can update --- .github/workflows/goreleaser.yml | 8 +-- api/waf_sys_info.go | 28 +++++++--- api/waf_sys_info_test.go | 94 +++++++++++++++++++++++++++----- build-releases-win7-upx.bat | 5 ++ global/global.go | 12 ++-- main.go | 8 ++- release_pub.bat | 3 +- release_pub_test.bat | 7 +-- utils/common.go | 64 +++++++++++++++++++++- 9 files changed, 187 insertions(+), 42 deletions(-) create mode 100644 build-releases-win7-upx.bat diff --git a/.github/workflows/goreleaser.yml b/.github/workflows/goreleaser.yml index 7e28b30..6651267 100644 --- a/.github/workflows/goreleaser.yml +++ b/.github/workflows/goreleaser.yml @@ -136,17 +136,17 @@ jobs: BUILDTIME: ${{ env.BUILDTIME }} CURRENT_TAG: ${{ env.CURRENT_TAG }} run: | - go build -ldflags="-X SamWaf/global.GWAF_RUNTIME_WIN7_VERSION=true -X SamWaf/global.GWAF_RELEASE=true -X SamWaf/global.GWAF_RELEASE_VERSION_NAME=${BUILDTIME} -X SamWaf/global.GWAF_RELEASE_VERSION=${CURRENT_TAG} -s -w -extldflags '-static'" -o ./release/SamWaf64Win7Win8Win2008.exe main.go + go build -ldflags="-X SamWaf/global.GWAF_RUNTIME_WIN7_VERSION=true -X SamWaf/global.GWAF_RELEASE=true -X SamWaf/global.GWAF_RELEASE_VERSION_NAME=${BUILDTIME} -X SamWaf/global.GWAF_RELEASE_VERSION=${CURRENT_TAG} -s -w -extldflags '-static'" -o ./release/SamWaf64ForWin7Win8Win2008.exe main.go - name: Archive artifacts uses: actions/upload-artifact@v4 with: - name: SamWaf64Win7Win8Win2008_Win8_Win2008 - path: release/SamWaf64Win7Win8Win2008.exe + name: SamWaf64ForWin7Win8Win2008 + path: release/SamWaf64ForWin7Win8Win2008.exe - name: Release uses: softprops/action-gh-release@v2 if: startsWith(github.ref, 'refs/tags/') with: files: | - release/SamWaf64Win7Win8Win2008.exe + release/SamWaf64ForWin7Win8Win2008.exe needs: goreleaser \ No newline at end of file diff --git a/api/waf_sys_info.go b/api/waf_sys_info.go index 35f12ee..0b71294 100644 --- a/api/waf_sys_info.go +++ b/api/waf_sys_info.go @@ -6,7 +6,9 @@ import ( "SamWaf/innerbean" "SamWaf/model" "SamWaf/model/common/response" + "SamWaf/utils" "SamWaf/wafupdate" + "fmt" "github.com/gin-gonic/gin" ) @@ -26,11 +28,17 @@ func (w *WafSysInfoApi) CheckVersionApi(c *gin.Context) { response.OkWithMessage("正在升级中...请在消息等待结果", c) return } + var remoteURL string + if global.GWAF_RUNTIME_WIN7_VERSION == "true" || utils.IsSupportedWindows7Version() { + remoteURL = fmt.Sprintf("%s%s", global.GUPDATE_VERSION_URL, "win7/") + } else { + remoteURL = fmt.Sprintf("%s%s", global.GUPDATE_VERSION_URL, "") + } var updater = &wafupdate.Updater{ CurrentVersion: global.GWAF_RELEASE_VERSION, // Manually update the const, or set it using `go build -ldflags="-X main.VERSION=" -o hello-updater src/hello-updater/main.go` - ApiURL: global.GUPDATE_VERSION_URL, // The server hosting `$CmdName/$GOOS-$ARCH.json` which contains the checksum for the binary - BinURL: global.GUPDATE_VERSION_URL, // The server hosting the zip file containing the binary application which is a fallback for the patch method - DiffURL: global.GUPDATE_VERSION_URL, // The server hosting the binary patch diff for incremental updates + ApiURL: remoteURL, // The server hosting `$CmdName/$GOOS-$ARCH.json` which contains the checksum for the binary + BinURL: remoteURL, // The server hosting the zip file containing the binary application which is a fallback for the patch method + DiffURL: remoteURL, // The server hosting the binary patch diff for incremental updates Dir: "tmp_update/", // The directory created by the app when run which stores the cktime file CmdName: "samwaf_update", // The app name which is appended to the ApiURL to look for an update //ForceCheck: true, // For this example, always check for an update unless the version is "dev" @@ -65,16 +73,18 @@ func (w *WafSysInfoApi) UpdateApi(c *gin.Context) { response.OkWithMessage("正在升级中...请在消息等待结果", c) return } - if global.GWAF_RUNTIME_WIN7_VERSION == "true" { - response.OkWithMessage("您当前使用的是Win7内核版本,请手工下载版本升级。https://github.com/samwafgo/SamWaf/releases", c) - return + var remoteURL string + if global.GWAF_RUNTIME_WIN7_VERSION == "true" || utils.IsSupportedWindows7Version() { + remoteURL = fmt.Sprintf("%s%s", global.GUPDATE_VERSION_URL, "win7/") + } else { + remoteURL = fmt.Sprintf("%s%s", global.GUPDATE_VERSION_URL, "") } global.GWAF_RUNTIME_IS_UPDATETING = true var updater = &wafupdate.Updater{ CurrentVersion: global.GWAF_RELEASE_VERSION, // Manually update the const, or set it using `go build -ldflags="-X main.VERSION=" -o hello-updater src/hello-updater/main.go` - ApiURL: global.GUPDATE_VERSION_URL, // The server hosting `$CmdName/$GOOS-$ARCH.json` which contains the checksum for the binary - BinURL: global.GUPDATE_VERSION_URL, // The server hosting the zip file containing the binary application which is a fallback for the patch method - DiffURL: global.GUPDATE_VERSION_URL, // The server hosting the binary patch diff for incremental updates + ApiURL: remoteURL, // The server hosting `$CmdName/$GOOS-$ARCH.json` which contains the checksum for the binary + BinURL: remoteURL, // The server hosting the zip file containing the binary application which is a fallback for the patch method + DiffURL: remoteURL, // The server hosting the binary patch diff for incremental updates Dir: "tmp_update/", // The directory created by the app when run which stores the cktime file CmdName: "samwaf_update", // The app name which is appended to the ApiURL to look for an update //ForceCheck: true, // For this example, always check for an update unless the version is "dev" diff --git a/api/waf_sys_info_test.go b/api/waf_sys_info_test.go index 95b5ae0..a785530 100644 --- a/api/waf_sys_info_test.go +++ b/api/waf_sys_info_test.go @@ -2,6 +2,7 @@ package api import ( "SamWaf/global" + "SamWaf/wafsec" "encoding/json" "github.com/gin-gonic/gin" "net/http" @@ -11,14 +12,15 @@ import ( // 响应体:{"message":"H ello, World!"},实际响应体:{"code":0,"data":{"need_update":false,"versi on":"555","version_name":"1.0","version_release":"false"},"msg":" 已经是最新版本"} type WafCheckVersionResponse struct { - Code int `json:"code"` - Data struct { - NeedUpdate bool `json:"need_update"` - Version string `json:"version"` - VersionName string `json:"version_name"` - VersionRelease string `json:"version_release"` - } `json:"data"` - Msg string `json:"msg"` + Code int `json:"code"` + Data json.RawMessage `json:"data"` + Msg string `json:"msg"` +} +type ComplexData struct { + NeedUpdate bool `json:"need_update"` + Version string `json:"version"` + VersionName string `json:"version_name"` + VersionRelease string `json:"version_release"` } // 测试用例 CheckVersionApi @@ -26,7 +28,11 @@ func TestCheckVersionApi(t *testing.T) { // 创建一个基于 Gin 的引擎 r := gin.Default() - global.GWAF_RELEASE_VERSION = "v1.0.0" + //解析响应体 + var response WafCheckVersionResponse + + global.GWAF_RELEASE_VERSION_NAME = "v1.3.6" + global.GUPDATE_VERSION_URL = "http://127.0.0.1:8111/" r.GET("/samwaf/sysinfo/checkversion", new(WafSysInfoApi).CheckVersionApi) // 创建一个模拟的 HTTP 请求 req, err := http.NewRequest(http.MethodGet, "/samwaf/sysinfo/checkversion", nil) @@ -39,19 +45,79 @@ func TestCheckVersionApi(t *testing.T) { // 将模拟的请求发送到测试的 API 路由 r.ServeHTTP(rec, req) + t.Logf("响应体内容: %s", rec.Body.String()) // 检查响应状态码是否为 200 if rec.Code != http.StatusOK { t.Errorf("期望的状态码:%d,实际状态码:%d", http.StatusOK, rec.Code) } + + if err := json.Unmarshal(rec.Body.Bytes(), &response); err != nil { + t.Errorf("复杂结构体解析失败:%v", err) + } + if response.Code != -1 { + t.Errorf("期望的响应体:%v,实际响应体:%v", "-1", response.Code) + } + +} + +// 测试用例 CheckVersionApi +func TestCheckVersionNeedUploadApi(t *testing.T) { + // 创建一个基于 Gin 的引擎 + r := gin.Default() + //解析响应体 var response WafCheckVersionResponse - err = json.Unmarshal(rec.Body.Bytes(), &response) + + global.GWAF_RELEASE_VERSION_NAME = "v1.0.6" + global.GUPDATE_VERSION_URL = "http://127.0.0.1:8111/" + global.GWAF_RUNTIME_WIN7_VERSION = "true" + r.GET("/samwaf/sysinfo/checkversion", new(WafSysInfoApi).CheckVersionApi) + // 创建一个模拟的 HTTP 请求 + req, err := http.NewRequest(http.MethodGet, "/samwaf/sysinfo/checkversion", nil) if err != nil { - t.Errorf("响应体解析失败:%v", err) + t.Fatalf("无法创建请求:%v", err) } - expectedNeedUpdate := false - if response.Data.NeedUpdate != expectedNeedUpdate { - t.Errorf("期望的响应体:%t,实际响应体:%t", expectedNeedUpdate, response.Data.NeedUpdate) + + // 创建一个响应记录器 + rec := httptest.NewRecorder() + + // 将模拟的请求发送到测试的 API 路由 + r.ServeHTTP(rec, req) + t.Logf("响应体内容: %s", rec.Body.String()) + + // 检查响应状态码是否为 200 + if rec.Code != http.StatusOK { + t.Errorf("期望的状态码:%d,实际状态码:%d", http.StatusOK, rec.Code) } + + if err := json.Unmarshal(rec.Body.Bytes(), &response); err != nil { + t.Errorf("复杂结构体解析失败:%v", err) + } + if response.Code < 0 { + t.Errorf("期望的响应体:%v,实际响应体:%v", "大于0", response.Code) + } + // 判断 data 是简单字符串还是复杂结构体 + var dataString string + if json.Unmarshal(response.Data, &dataString) == nil { + // data 是字符串 + decryptedData, err := wafsec.AesDecrypt(dataString, global.GWAF_COMMUNICATION_KEY) + if err != nil { + t.Errorf("失败:%v", err) + return + } + + //JSON 数据 + var complexData ComplexData + if err := json.Unmarshal(decryptedData, &complexData); err != nil { + t.Errorf("数据解析失败:%v", err) + } else { + // 继续检查复杂结构体内容 + expectedNeedUpdate := false + if complexData.NeedUpdate != expectedNeedUpdate { + t.Errorf("期望的 NeedUpdate 值:%t,实际值:%t", expectedNeedUpdate, complexData.NeedUpdate) + } + } + } + } diff --git a/build-releases-win7-upx.bat b/build-releases-win7-upx.bat new file mode 100644 index 0000000..485c539 --- /dev/null +++ b/build-releases-win7-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_RUNTIME_WIN7_VERSION=true -X SamWaf/global.GWAF_RELEASE=true -X SamWaf/global.GWAF_RELEASE_VERSION_NAME=20241011 -X SamWaf/global.GWAF_RELEASE_VERSION=v1.3.6 -s -w" -o %cd%/release/SamWaf64.exe main.go && %cd%/upx/win64/upx -9 %cd%/release/SamWaf64.exe \ No newline at end of file diff --git a/global/global.go b/global/global.go index 20045e0..baa4896 100644 --- a/global/global.go +++ b/global/global.go @@ -26,11 +26,11 @@ var ( GWAF_RUNTIME_AREA string = "" //本机当前所在区域 GWAF_RUNTIME_SERVER_TYPE bool = false //当前是是否以服务形式启动 - GWAF_RUNTIME_NEW_VERSION string = "" //最新版本号 - GWAF_RUNTIME_NEW_VERSION_DESC string = "" //最新版本描述 - GWAF_RUNTIME_WIN7_VERSION string = "false" //是否是win7内部版本 - GWAF_RUNTIME_QPS uint64 = 0 //当前qps - GWAF_RUNTIME_LOG_PROCESS uint64 = 0 //log 处理速度 + GWAF_RUNTIME_NEW_VERSION string = "" //最新版本号 + GWAF_RUNTIME_NEW_VERSION_DESC string = "" //最新版本描述 + GWAF_RUNTIME_WIN7_VERSION string = "true" //是否是win7内部版本 + GWAF_RUNTIME_QPS uint64 = 0 //当前qps + GWAF_RUNTIME_LOG_PROCESS uint64 = 0 //log 处理速度 GWAF_RUNTIME_DNS_SERVER string = "119.29.29.29" //反向查询DNS的IP @@ -58,7 +58,7 @@ var ( GWAF_CUSTOM_SERVER_NAME string // 当前服务器自定义名称 GWAF_TENANT_ID string = "SamWafCom" // 当前租户ID GWAF_RELEASE string = "false" // 当前是否为发行版 - GWAF_RELEASE_VERSION_NAME string = "1.0" // 发行版的版本号名称 + GWAF_RELEASE_VERSION_NAME string = "20241028" // 发行版的版本号名称 GWAF_RELEASE_VERSION string = "v1.0.0" // 发行版的版本号 GWAF_LAST_UPDATE_TIME time.Time // 上次时间 GWAF_NOTICE_ENABLE bool = false // 是否开启通知 diff --git a/main.go b/main.go index 2db7d9f..d9fa461 100644 --- a/main.go +++ b/main.go @@ -170,6 +170,12 @@ func (m *wafSystenService) run() { rversion = rversion + " linux" } else if runtime.GOOS == "windows" { rversion = rversion + " windows" + if utils.IsSupportedWindows7Version() { + zlog.Info("Now your system is win7 or win2008r2.") + } + if global.GWAF_RUNTIME_WIN7_VERSION == "true" && utils.IsSupportedWindows7Version() == false { + zlog.Error("Now your use is win7 or win2008r2 special version,We recommend you download normal version") + } } else { rversion = rversion + " " + runtime.GOOS } @@ -180,7 +186,7 @@ func (m *wafSystenService) run() { zlog.Info("OutIp", global.GWAF_RUNTIME_IP) if global.GWAF_RELEASE == "false" { - global.GUPDATE_VERSION_URL = "http://127.0.0.1:81/" + global.GUPDATE_VERSION_URL = "http://127.0.0.1:8111/" /*runtime.GOMAXPROCS(1) // 限制 CPU 使用数,避免过载 runtime.SetMutexProfileFraction(1) // 开启对锁调用的跟踪 runtime.SetBlockProfileRate(1) // 开启对阻塞操作的跟踪*/ diff --git a/release_pub.bat b/release_pub.bat index 54ec2cb..9c45b46 100644 --- a/release_pub.bat +++ b/release_pub.bat @@ -4,4 +4,5 @@ set currentpath=%cd% set currentversion=v1.3.6 set currentdescription=请在闲时升级,新增ssl证书夹,自定义ip库等 %currentpath%\setup\go_gen_updatefile\go_gen_updatefile.exe -desc %currentdescription% -o %currentpath%\release\web\samwaf_update -platform windows-amd64 %currentpath%\release\githubci\%currentversion%\SamWaf64.exe %currentversion% -%currentpath%\setup\go_gen_updatefile\go_gen_updatefile.exe -desc %currentdescription% -o %currentpath%\release\web\samwaf_update -platform linux-amd64 %currentpath%\release\githubci\%currentversion%\SamWafLinux64 %currentversion% \ No newline at end of file +%currentpath%\setup\go_gen_updatefile\go_gen_updatefile.exe -desc %currentdescription% -o %currentpath%\release\web\samwaf_update -platform linux-amd64 %currentpath%\release\githubci\%currentversion%\SamWafLinux64 %currentversion% +%currentpath%\setup\go_gen_updatefile\go_gen_updatefile.exe -desc %currentdescription% -o %currentpath%\release\web\win7\samwaf_update -platform windows-amd64 %currentpath%\release\githubci\%currentversion%\SamWaf64ForWin7Win8Win2008.exe %currentversion% diff --git a/release_pub_test.bat b/release_pub_test.bat index 698da06..302bd46 100644 --- a/release_pub_test.bat +++ b/release_pub_test.bat @@ -1,7 +1,6 @@ @echo on chcp 65001 -set testpath=C:\huawei\goproject\SamWafUpdate\ set currentpath=%cd% -set currentversion=v1.1.2024 -set currentdescription=测试升级 -%currentpath%\setup\go_gen_updatefile\go_gen_updatefile.exe -desc %currentdescription% -o %currentpath%\release\web\test_update -platform windows-amd64 %testpath%\SamWafUpdate.exe %currentversion% \ No newline at end of file +set currentversion=v1.3.7-beta.2 +set currentdescription=本地测试 +%currentpath%\setup\go_gen_updatefile\go_gen_updatefile.exe -desc %currentdescription% -o %currentpath%\release\web\win7\samwaf_update -platform windows-amd64 %currentpath%\release\githubci\%currentversion%\SamWaf64ForWin7Win8Win2008.exe %currentversion% diff --git a/utils/common.go b/utils/common.go index 0626638..1fe93d8 100644 --- a/utils/common.go +++ b/utils/common.go @@ -11,9 +11,12 @@ import ( "net/http" "os" "path/filepath" + "runtime" "strconv" "strings" + "syscall" "time" + "unsafe" ) func GetExternalIp() string { @@ -262,9 +265,8 @@ func IsValidIPv4(ip string) bool { return parsedIP != nil && parsedIP.To4() != nil } -/* -获取纯域名 -*/ +// 获取纯域名 + func GetPureDomain(host string) string { // 检查是否包含端口号 if strings.Contains(host, ":") { @@ -272,3 +274,59 @@ func GetPureDomain(host string) string { } return host } + +// 定义 RtlGetVersion 函数 +var modNtDll = syscall.NewLazyDLL("ntdll.dll") +var procRtlGetVersion = modNtDll.NewProc("RtlGetVersion") + +type OsVersionInfoEx struct { + DwOSVersionInfoSize uint32 + DwMajorVersion uint32 + DwMinorVersion uint32 + DwBuildNumber uint32 + DwPlatformId uint32 + SzCSDVersion [128]uint16 + WServicePackMajor uint16 + WServicePackMinor uint16 + WSuiteMask uint16 + WProductType byte + WReserved byte +} + +// 使用 RtlGetVersion 函数获取版本信息 +func getWindowsVersion() (uint32, uint32, uint32, error) { + var info OsVersionInfoEx + info.DwOSVersionInfoSize = uint32(unsafe.Sizeof(info)) + ret, _, _ := procRtlGetVersion.Call(uintptr(unsafe.Pointer(&info))) + if ret != 0 { + return 0, 0, 0, syscall.Errno(ret) + } + return info.DwMajorVersion, info.DwMinorVersion, info.DwBuildNumber, nil +} + +// 判断是否为 Windows 平台,并且是 Windows 7, Windows 8 或 Windows Server 2008 R2 +func IsSupportedWindows7Version() bool { + // 检查是否是 Windows 系统 + if runtime.GOOS != "windows" { + return false + } + + // 调用 RtlGetVersion 获取准确的操作系统版本信息 + major, minor, _, err := getWindowsVersion() + if err != nil { + return false + } + + // 判断是否为 Windows 7 或 Windows Server 2008 R2 (版本 6.1) + if major == 6 && minor == 1 { + return true + } + + // 判断是否为 Windows 8 (版本 6.2) + if major == 6 && minor == 2 { + return true + } + + // 如果都不满足,返回 false + return false +}