feat:pay callback

#287
This commit is contained in:
samwaf
2025-05-03 15:17:32 +08:00
parent c3f91b57d9
commit b6cbb653eb
6 changed files with 260 additions and 6 deletions

70
wafbot/callback_ip.go Normal file
View File

@@ -0,0 +1,70 @@
package wafbot
import "SamWaf/utils"
// CallBackIpResult 检测结果
type CallBackIpResult struct {
IsCallBack bool //是否是正常回调
CallBackName string //回调名称
}
func CheckCallBackIp(ip string) CallBackIpResult {
result := WeixinPayBackIP(ip)
if result.IsCallBack == true {
return result
}
result = AlipayPayBackIP(ip)
if result.IsCallBack == true {
return result
}
return CallBackIpResult{IsCallBack: false, CallBackName: ""}
}
func WeixinPayBackIP(ip string) CallBackIpResult {
ips := []string{
"175.24.214.208",
"175.24.211.24",
"175.24.213.135", "109.244.180.23", "114.132.203.119", "43.139.43.69",
}
for _, v := range ips {
if ip == v {
return CallBackIpResult{IsCallBack: true, CallBackName: "微信支付回调"}
}
}
ipRanges := []string{
"101.226.103.0/25",
"140.207.54.0/25",
"121.51.58.128/25",
"183.3.234.0/25",
"58.251.80.0/25",
"121.51.30.128/25",
"203.205.219.128/25",
}
isInRanges := utils.CheckIPInRanges(ip, ipRanges)
if isInRanges == true {
return CallBackIpResult{IsCallBack: true, CallBackName: "微信支付回调"}
}
return CallBackIpResult{IsCallBack: false, CallBackName: ""}
}
func AlipayPayBackIP(ip string) CallBackIpResult {
ipRanges := []string{
"103.47.4.0/22",
"103.52.196.0/22",
"110.75.128.0/19",
"110.75.224.0/19",
"110.76.0.0/19",
"110.76.48.0/20",
"119.42.224.0/19",
"203.209.224.0/19",
"43.227.188.0/22",
"45.113.40.0/22",
"2400:B200::/32",
}
isInRanges := utils.CheckIPInRanges(ip, ipRanges)
if isInRanges == true {
return CallBackIpResult{IsCallBack: true, CallBackName: "支付宝回调"}
}
return CallBackIpResult{IsCallBack: false, CallBackName: ""}
}

139
wafbot/callback_ip_test.go Normal file
View File

@@ -0,0 +1,139 @@
package wafbot
import (
"testing"
)
func TestCheckCallBackIp(t *testing.T) {
tests := []struct {
name string
ip string
expected CallBackIpResult
}{
{
name: "微信支付回调IP-直接匹配",
ip: "175.24.214.208",
expected: CallBackIpResult{
IsCallBack: true,
CallBackName: "微信支付回调",
},
},
{
name: "微信支付回调IP-范围匹配",
ip: "101.226.103.10",
expected: CallBackIpResult{
IsCallBack: true,
CallBackName: "微信支付回调",
},
},
{
name: "支付宝回调IP",
ip: "110.75.130.1",
expected: CallBackIpResult{
IsCallBack: true,
CallBackName: "支付宝回调",
},
},
{
name: "非回调IP",
ip: "8.8.8.8",
expected: CallBackIpResult{
IsCallBack: false,
CallBackName: "",
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := CheckCallBackIp(tt.ip)
if result.IsCallBack != tt.expected.IsCallBack || result.CallBackName != tt.expected.CallBackName {
t.Errorf("CheckCallBackIp() = %v, want %v", result, tt.expected)
}
})
}
}
func TestWeixinPayBackIP(t *testing.T) {
tests := []struct {
name string
ip string
expected CallBackIpResult
}{
{
name: "微信支付回调IP-直接匹配",
ip: "175.24.214.208",
expected: CallBackIpResult{
IsCallBack: true,
CallBackName: "微信支付回调",
},
},
{
name: "微信支付回调IP-范围匹配",
ip: "101.226.103.10",
expected: CallBackIpResult{
IsCallBack: true,
CallBackName: "微信支付回调",
},
},
{
name: "非微信支付回调IP",
ip: "8.8.8.8",
expected: CallBackIpResult{
IsCallBack: false,
CallBackName: "",
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := WeixinPayBackIP(tt.ip)
if result.IsCallBack != tt.expected.IsCallBack || result.CallBackName != tt.expected.CallBackName {
t.Errorf("WeixinPayBackIP() = %v, want %v", result, tt.expected)
}
})
}
}
func TestAlipayPayBackIP(t *testing.T) {
tests := []struct {
name string
ip string
expected CallBackIpResult
}{
{
name: "支付宝回调IP",
ip: "110.75.130.1",
expected: CallBackIpResult{
IsCallBack: true,
CallBackName: "支付宝回调",
},
},
{
name: "支付宝回调IP-IPv6",
ip: "2400:B200::1",
expected: CallBackIpResult{
IsCallBack: true,
CallBackName: "支付宝回调",
},
},
{
name: "非支付宝回调IP",
ip: "8.8.8.8",
expected: CallBackIpResult{
IsCallBack: false,
CallBackName: "",
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := AlipayPayBackIP(tt.ip)
if result.IsCallBack != tt.expected.IsCallBack || result.CallBackName != tt.expected.CallBackName {
t.Errorf("AlipayPayBackIP() = %v, want %v", result, tt.expected)
}
})
}
}

View File

@@ -0,0 +1,30 @@
package wafenginecore
import (
"SamWaf/global"
"SamWaf/innerbean"
"SamWaf/model/detection"
"SamWaf/model/wafenginmodel"
"SamWaf/wafbot"
"net/http"
"net/url"
)
func (waf *WafEngine) CheckAllowCallBackIP(r *http.Request, weblogbean *innerbean.WebLog, formValue url.Values, hostTarget *wafenginmodel.HostSafe, globalHostTarget *wafenginmodel.HostSafe) detection.Result {
result := detection.Result{
JumpGuardResult: false,
IsBlock: false,
Title: "",
Content: "",
}
clientIp := weblogbean.SRC_IP
if global.GCONFIG_RECORD_PROXY_HEADER == "" {
clientIp = weblogbean.NetSrcIp
}
backIpResult := wafbot.CheckCallBackIp(clientIp)
if backIpResult.IsCallBack {
result.JumpGuardResult = true
weblogbean.GUEST_IDENTIFICATION = backIpResult.CallBackName
}
return result
}

View File

@@ -21,10 +21,15 @@ func (waf *WafEngine) CheckAllowIP(r *http.Request, weblogbean *innerbean.WebLog
Title: "",
Content: "",
}
clientIp := weblogbean.SRC_IP
if global.GCONFIG_RECORD_PROXY_HEADER == "" {
clientIp = weblogbean.NetSrcIp
}
//ip白名单策略局部
if hostTarget.IPWhiteLists != nil {
for i := 0; i < len(hostTarget.IPWhiteLists); i++ {
if utils.CheckIPInCIDR(weblogbean.SRC_IP, hostTarget.IPWhiteLists[i].Ip) {
if utils.CheckIPInCIDR(clientIp, hostTarget.IPWhiteLists[i].Ip) {
result.JumpGuardResult = true
break
}
@@ -33,7 +38,7 @@ func (waf *WafEngine) CheckAllowIP(r *http.Request, weblogbean *innerbean.WebLog
//ip白名单策略全局
if waf.HostTarget[global.GWAF_GLOBAL_HOST_NAME].Host.GUARD_STATUS == 1 && waf.HostTarget[global.GWAF_GLOBAL_HOST_NAME].IPWhiteLists != nil {
for i := 0; i < len(waf.HostTarget[global.GWAF_GLOBAL_HOST_NAME].IPWhiteLists); i++ {
if utils.CheckIPInCIDR(weblogbean.SRC_IP, waf.HostTarget[global.GWAF_GLOBAL_HOST_NAME].IPWhiteLists[i].Ip) {
if utils.CheckIPInCIDR(clientIp, waf.HostTarget[global.GWAF_GLOBAL_HOST_NAME].IPWhiteLists[i].Ip) {
result.JumpGuardResult = true
break
}

View File

@@ -15,7 +15,7 @@ import (
检测允许的URL
返回是否满足条件
*/
func (waf *WafEngine) CheckAllowURL(r *http.Request, weblogbean innerbean.WebLog, formValue url.Values, hostTarget *wafenginmodel.HostSafe, globalHostTarget *wafenginmodel.HostSafe) detection.Result {
func (waf *WafEngine) CheckAllowURL(r *http.Request, weblogbean *innerbean.WebLog, formValue url.Values, hostTarget *wafenginmodel.HostSafe, globalHostTarget *wafenginmodel.HostSafe) detection.Result {
result := detection.Result{
JumpGuardResult: false,
IsBlock: false,

View File

@@ -268,10 +268,20 @@ func (waf *WafEngine) ServeHTTP(w http.ResponseWriter, r *http.Request) {
return false
}
globalHostSafe := waf.HostTarget[waf.HostCode[global.GWAF_GLOBAL_HOST_CODE]]
detectionWhiteResult := waf.CheckAllowIP(r, &weblogbean, formValues, hostTarget, globalHostSafe)
if detectionWhiteResult.JumpGuardResult == false {
detectionWhiteResult = waf.CheckAllowURL(r, weblogbean, formValues, hostTarget, globalHostSafe)
// 检测白名单开始
detectionWhiteResult := detection.Result{JumpGuardResult: false}
checkFunctions := []func(*http.Request, *innerbean.WebLog, url.Values, *wafenginmodel.HostSafe, *wafenginmodel.HostSafe) detection.Result{
waf.CheckAllowIP,
waf.CheckAllowURL,
waf.CheckAllowCallBackIP,
}
for _, checkFunc := range checkFunctions {
detectionWhiteResult = checkFunc(r, &weblogbean, formValues, hostTarget, globalHostSafe)
if detectionWhiteResult.JumpGuardResult == true {
break
}
}
//检测白名单结束
if detectionWhiteResult.JumpGuardResult == false {
if handleBlock(waf.CheckDenyIP) {