mirror of
https://github.com/TeaOSLab/EdgeNode.git
synced 2025-12-15 07:06:36 +08:00
实现WAF
This commit is contained in:
94
internal/waf/action_block.go
Normal file
94
internal/waf/action_block.go
Normal file
@@ -0,0 +1,94 @@
|
||||
package waf
|
||||
|
||||
import (
|
||||
teaconst "github.com/TeaOSLab/EdgeNode/internal/const"
|
||||
"github.com/TeaOSLab/EdgeNode/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeNode/internal/waf/requests"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/logs"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"time"
|
||||
)
|
||||
|
||||
// url client configure
|
||||
var urlPrefixReg = regexp.MustCompile("^(?i)(http|https)://")
|
||||
var httpClient = utils.SharedHttpClient(5 * time.Second)
|
||||
|
||||
type BlockAction struct {
|
||||
StatusCode int `yaml:"statusCode" json:"statusCode"`
|
||||
Body string `yaml:"body" json:"body"` // supports HTML
|
||||
URL string `yaml:"url" json:"url"`
|
||||
}
|
||||
|
||||
func (this *BlockAction) Perform(waf *WAF, request *requests.Request, writer http.ResponseWriter) (allow bool) {
|
||||
if writer != nil {
|
||||
// if status code eq 444, we close the connection
|
||||
if this.StatusCode == 444 {
|
||||
hijack, ok := writer.(http.Hijacker)
|
||||
if ok {
|
||||
conn, _, _ := hijack.Hijack()
|
||||
if conn != nil {
|
||||
_ = conn.Close()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// output response
|
||||
if this.StatusCode > 0 {
|
||||
writer.WriteHeader(this.StatusCode)
|
||||
} else {
|
||||
writer.WriteHeader(http.StatusForbidden)
|
||||
}
|
||||
if len(this.URL) > 0 {
|
||||
if urlPrefixReg.MatchString(this.URL) {
|
||||
req, err := http.NewRequest(http.MethodGet, this.URL, nil)
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
return false
|
||||
}
|
||||
resp, err := httpClient.Do(req)
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
return false
|
||||
}
|
||||
defer func() {
|
||||
_ = resp.Body.Close()
|
||||
}()
|
||||
|
||||
for k, v := range resp.Header {
|
||||
for _, v1 := range v {
|
||||
writer.Header().Add(k, v1)
|
||||
}
|
||||
}
|
||||
|
||||
buf := make([]byte, 1024)
|
||||
_, _ = io.CopyBuffer(writer, resp.Body, buf)
|
||||
} else {
|
||||
path := this.URL
|
||||
if !filepath.IsAbs(this.URL) {
|
||||
path = Tea.Root + string(os.PathSeparator) + path
|
||||
}
|
||||
|
||||
data, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
logs.Error(err)
|
||||
return false
|
||||
}
|
||||
_, _ = writer.Write(data)
|
||||
}
|
||||
return false
|
||||
}
|
||||
if len(this.Body) > 0 {
|
||||
_, _ = writer.Write([]byte(this.Body))
|
||||
} else {
|
||||
_, _ = writer.Write([]byte("The request is blocked by " + teaconst.ProductName))
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
Reference in New Issue
Block a user