mirror of
https://github.com/TeaOSLab/EdgeNode.git
synced 2025-11-14 15:40:24 +08:00
自动使用本地防火墙/增加edge-node [ip.drop|ip.reject|ip.remove]等命令
This commit is contained in:
@@ -8,7 +8,10 @@ import (
|
|||||||
"github.com/TeaOSLab/EdgeNode/internal/nodes"
|
"github.com/TeaOSLab/EdgeNode/internal/nodes"
|
||||||
_ "github.com/iwind/TeaGo/bootstrap"
|
_ "github.com/iwind/TeaGo/bootstrap"
|
||||||
"github.com/iwind/TeaGo/logs"
|
"github.com/iwind/TeaGo/logs"
|
||||||
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
"github.com/iwind/TeaGo/types"
|
||||||
"github.com/iwind/gosock/pkg/gosock"
|
"github.com/iwind/gosock/pkg/gosock"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
_ "net/http/pprof"
|
_ "net/http/pprof"
|
||||||
"os"
|
"os"
|
||||||
@@ -126,6 +129,113 @@ func main() {
|
|||||||
fmt.Println("ok")
|
fmt.Println("ok")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
app.On("ip.drop", func() {
|
||||||
|
var args = os.Args[2:]
|
||||||
|
if len(args) == 0 {
|
||||||
|
fmt.Println("Usage: edge-node ip.drop IP [--timeout=SECONDS]")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var ip = args[0]
|
||||||
|
if len(net.ParseIP(ip)) == 0 {
|
||||||
|
fmt.Println("IP '" + ip + "' is invalid")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var timeoutSeconds = 0
|
||||||
|
var options = app.ParseOptions(args[1:])
|
||||||
|
timeout, ok := options["timeout"]
|
||||||
|
if ok {
|
||||||
|
timeoutSeconds = types.Int(timeout[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("drop ip '" + ip + "' for '" + types.String(timeoutSeconds) + "' seconds")
|
||||||
|
var sock = gosock.NewTmpSock(teaconst.ProcessName)
|
||||||
|
reply, err := sock.Send(&gosock.Command{
|
||||||
|
Code: "dropIP",
|
||||||
|
Params: map[string]interface{}{
|
||||||
|
"ip": ip,
|
||||||
|
"timeoutSeconds": timeoutSeconds,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("[ERROR]" + err.Error())
|
||||||
|
} else {
|
||||||
|
var errString = maps.NewMap(reply.Params).GetString("error")
|
||||||
|
if len(errString) > 0 {
|
||||||
|
fmt.Println("[ERROR]" + errString)
|
||||||
|
} else {
|
||||||
|
fmt.Println("ok")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
app.On("ip.reject", func() {
|
||||||
|
var args = os.Args[2:]
|
||||||
|
if len(args) == 0 {
|
||||||
|
fmt.Println("Usage: edge-node ip.reject IP [--timeout=SECONDS]")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var ip = args[0]
|
||||||
|
if len(net.ParseIP(ip)) == 0 {
|
||||||
|
fmt.Println("IP '" + ip + "' is invalid")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var timeoutSeconds = 0
|
||||||
|
var options = app.ParseOptions(args[1:])
|
||||||
|
timeout, ok := options["timeout"]
|
||||||
|
if ok {
|
||||||
|
timeoutSeconds = types.Int(timeout[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("reject ip '" + ip + "' for '" + types.String(timeoutSeconds) + "' seconds")
|
||||||
|
|
||||||
|
var sock = gosock.NewTmpSock(teaconst.ProcessName)
|
||||||
|
reply, err := sock.Send(&gosock.Command{
|
||||||
|
Code: "rejectIP",
|
||||||
|
Params: map[string]interface{}{
|
||||||
|
"ip": ip,
|
||||||
|
"timeoutSeconds": timeoutSeconds,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("[ERROR]" + err.Error())
|
||||||
|
} else {
|
||||||
|
var errString = maps.NewMap(reply.Params).GetString("error")
|
||||||
|
if len(errString) > 0 {
|
||||||
|
fmt.Println("[ERROR]" + errString)
|
||||||
|
} else {
|
||||||
|
fmt.Println("ok")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
app.On("ip.remove", func() {
|
||||||
|
var args = os.Args[2:]
|
||||||
|
if len(args) == 0 {
|
||||||
|
fmt.Println("Usage: edge-node ip.remove IP")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var ip = args[0]
|
||||||
|
if len(net.ParseIP(ip)) == 0 {
|
||||||
|
fmt.Println("IP '" + ip + "' is invalid")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var sock = gosock.NewTmpSock(teaconst.ProcessName)
|
||||||
|
reply, err := sock.Send(&gosock.Command{
|
||||||
|
Code: "removeIP",
|
||||||
|
Params: map[string]interface{}{
|
||||||
|
"ip": ip,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("[ERROR]" + err.Error())
|
||||||
|
} else {
|
||||||
|
var errString = maps.NewMap(reply.Params).GetString("error")
|
||||||
|
if len(errString) > 0 {
|
||||||
|
fmt.Println("[ERROR]" + errString)
|
||||||
|
} else {
|
||||||
|
fmt.Println("ok")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
app.Run(func() {
|
app.Run(func() {
|
||||||
node := nodes.NewNode()
|
node := nodes.NewNode()
|
||||||
node.Start()
|
node.Start()
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
"os/exec"
|
"os/exec"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -245,3 +246,19 @@ func (this *AppCmd) getPID() int {
|
|||||||
}
|
}
|
||||||
return maps.NewMap(reply.Params).GetInt("pid")
|
return maps.NewMap(reply.Params).GetInt("pid")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParseOptions 分析参数中的选项
|
||||||
|
func (this *AppCmd) ParseOptions(args []string) map[string][]string {
|
||||||
|
var result = map[string][]string{}
|
||||||
|
for _, arg := range args {
|
||||||
|
var pieces = strings.SplitN(arg, "=", 2)
|
||||||
|
var key = strings.TrimLeft(pieces[0], "- ")
|
||||||
|
key = strings.TrimSpace(key)
|
||||||
|
var value = ""
|
||||||
|
if len(pieces) == 2 {
|
||||||
|
value = strings.TrimSpace(pieces[1])
|
||||||
|
}
|
||||||
|
result[key] = append(result[key], value)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|||||||
42
internal/firewalls/firewall.go
Normal file
42
internal/firewalls/firewall.go
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||||
|
|
||||||
|
package firewalls
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeNode/internal/events"
|
||||||
|
"github.com/TeaOSLab/EdgeNode/internal/remotelogs"
|
||||||
|
)
|
||||||
|
|
||||||
|
var currentFirewall FirewallInterface
|
||||||
|
|
||||||
|
// 初始化
|
||||||
|
func init() {
|
||||||
|
events.On(events.EventLoaded, func() {
|
||||||
|
var firewall = Firewall()
|
||||||
|
if firewall.Name() == "mock" {
|
||||||
|
remotelogs.Warn("FIREWALL", "'firewalld' on this system should be enabled to block attackers more effectively")
|
||||||
|
} else {
|
||||||
|
remotelogs.Println("FIREWALL", "found local firewall '"+firewall.Name()+"'")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Firewall 查找当前系统中最适合的防火墙
|
||||||
|
func Firewall() FirewallInterface {
|
||||||
|
if currentFirewall != nil {
|
||||||
|
return currentFirewall
|
||||||
|
}
|
||||||
|
|
||||||
|
// firewalld
|
||||||
|
{
|
||||||
|
var firewalld = NewFirewalld()
|
||||||
|
if firewalld.IsReady() {
|
||||||
|
currentFirewall = firewalld
|
||||||
|
return currentFirewall
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 至少返回一个
|
||||||
|
currentFirewall = NewMockFirewall()
|
||||||
|
return currentFirewall
|
||||||
|
}
|
||||||
135
internal/firewalls/firewall_firewalld.go
Normal file
135
internal/firewalls/firewall_firewalld.go
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||||
|
|
||||||
|
package firewalls
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeNode/internal/goman"
|
||||||
|
"github.com/TeaOSLab/EdgeNode/internal/remotelogs"
|
||||||
|
"github.com/iwind/TeaGo/types"
|
||||||
|
"os/exec"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Firewalld struct {
|
||||||
|
isReady bool
|
||||||
|
exe string
|
||||||
|
cmdQueue chan *exec.Cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFirewalld() *Firewalld {
|
||||||
|
var firewalld = &Firewalld{
|
||||||
|
cmdQueue: make(chan *exec.Cmd, 2048),
|
||||||
|
}
|
||||||
|
|
||||||
|
path, err := exec.LookPath("firewall-cmd")
|
||||||
|
if err == nil && len(path) > 0 {
|
||||||
|
var cmd = exec.Command(path, "-V")
|
||||||
|
err := cmd.Run()
|
||||||
|
if err == nil {
|
||||||
|
firewalld.exe = path
|
||||||
|
firewalld.isReady = true
|
||||||
|
firewalld.init()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return firewalld
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Firewalld) init() {
|
||||||
|
goman.New(func() {
|
||||||
|
for cmd := range this.cmdQueue {
|
||||||
|
err := cmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
if strings.HasPrefix(err.Error(), "Warning:") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
remotelogs.Warn("FIREWALL", "run command failed '"+cmd.String()+"': "+err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name 名称
|
||||||
|
func (this *Firewalld) Name() string {
|
||||||
|
return "firewalld"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Firewalld) IsReady() bool {
|
||||||
|
return this.isReady
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Firewalld) AllowPort(port int, protocol string) error {
|
||||||
|
if !this.isReady {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var cmd = exec.Command(this.exe, "--add-port="+types.String(port)+"/"+protocol)
|
||||||
|
this.pushCmd(cmd)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Firewalld) RemovePort(port int, protocol string) error {
|
||||||
|
if !this.isReady {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var cmd = exec.Command(this.exe, "--remove-port="+types.String(port)+"/"+protocol)
|
||||||
|
this.pushCmd(cmd)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Firewalld) RejectSourceIP(ip string, timeoutSeconds int) error {
|
||||||
|
if !this.isReady {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var family = "ipv4"
|
||||||
|
if strings.Contains(ip, ":") {
|
||||||
|
family = "ipv6"
|
||||||
|
}
|
||||||
|
var args = []string{"--add-rich-rule=rule family='" + family + "' source address='" + ip + "' reject"}
|
||||||
|
if timeoutSeconds > 0 {
|
||||||
|
args = append(args, "--timeout="+types.String(timeoutSeconds)+"s")
|
||||||
|
}
|
||||||
|
var cmd = exec.Command(this.exe, args...)
|
||||||
|
this.pushCmd(cmd)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Firewalld) DropSourceIP(ip string, timeoutSeconds int) error {
|
||||||
|
if !this.isReady {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var family = "ipv4"
|
||||||
|
if strings.Contains(ip, ":") {
|
||||||
|
family = "ipv6"
|
||||||
|
}
|
||||||
|
var args = []string{"--add-rich-rule=rule family='" + family + "' source address='" + ip + "' drop"}
|
||||||
|
if timeoutSeconds > 0 {
|
||||||
|
args = append(args, "--timeout="+types.String(timeoutSeconds)+"s")
|
||||||
|
}
|
||||||
|
var cmd = exec.Command(this.exe, args...)
|
||||||
|
this.pushCmd(cmd)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Firewalld) RemoveSourceIP(ip string) error {
|
||||||
|
if !this.isReady {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var family = "ipv4"
|
||||||
|
if strings.Contains(ip, ":") {
|
||||||
|
family = "ipv6"
|
||||||
|
}
|
||||||
|
for _, action := range []string{"reject", "drop"} {
|
||||||
|
var args = []string{"--remove-rich-rule=rule family='" + family + "' source address='" + ip + "' " + action}
|
||||||
|
var cmd = exec.Command(this.exe, args...)
|
||||||
|
this.pushCmd(cmd)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Firewalld) pushCmd(cmd *exec.Cmd) {
|
||||||
|
select {
|
||||||
|
case this.cmdQueue <- cmd:
|
||||||
|
default:
|
||||||
|
// we discard the command
|
||||||
|
}
|
||||||
|
}
|
||||||
27
internal/firewalls/firewall_interface.go
Normal file
27
internal/firewalls/firewall_interface.go
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||||
|
|
||||||
|
package firewalls
|
||||||
|
|
||||||
|
// FirewallInterface 防火墙接口
|
||||||
|
type FirewallInterface interface {
|
||||||
|
// Name 名称
|
||||||
|
Name() string
|
||||||
|
|
||||||
|
// IsReady 是否已准备被调用
|
||||||
|
IsReady() bool
|
||||||
|
|
||||||
|
// AllowPort 允许端口
|
||||||
|
AllowPort(port int, protocol string) error
|
||||||
|
|
||||||
|
// RemovePort 删除端口
|
||||||
|
RemovePort(port int, protocol string) error
|
||||||
|
|
||||||
|
// RejectSourceIP 拒绝某个源IP连接
|
||||||
|
RejectSourceIP(ip string, timeoutSeconds int) error
|
||||||
|
|
||||||
|
// DropSourceIP 丢弃某个源IP数据
|
||||||
|
DropSourceIP(ip string, timeoutSeconds int) error
|
||||||
|
|
||||||
|
// RemoveSourceIP 删除某个源IP
|
||||||
|
RemoveSourceIP(ip string) error
|
||||||
|
}
|
||||||
55
internal/firewalls/firewall_mock.go
Normal file
55
internal/firewalls/firewall_mock.go
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
|
||||||
|
|
||||||
|
package firewalls
|
||||||
|
|
||||||
|
// MockFirewall 模拟防火墙
|
||||||
|
type MockFirewall struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMockFirewall() *MockFirewall {
|
||||||
|
return &MockFirewall{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name 名称
|
||||||
|
func (this *MockFirewall) Name() string {
|
||||||
|
return "mock"
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsReady 是否已准备被调用
|
||||||
|
func (this *MockFirewall) IsReady() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// AllowPort 允许端口
|
||||||
|
func (this *MockFirewall) AllowPort(port int, protocol string) error {
|
||||||
|
_ = port
|
||||||
|
_ = protocol
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemovePort 删除端口
|
||||||
|
func (this *MockFirewall) RemovePort(port int, protocol string) error {
|
||||||
|
_ = port
|
||||||
|
_ = protocol
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RejectSourceIP 拒绝某个源IP连接
|
||||||
|
func (this *MockFirewall) RejectSourceIP(ip string, timeoutSeconds int) error {
|
||||||
|
_ = ip
|
||||||
|
_ = timeoutSeconds
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DropSourceIP 丢弃某个源IP数据
|
||||||
|
func (this *MockFirewall) DropSourceIP(ip string, timeoutSeconds int) error {
|
||||||
|
_ = ip
|
||||||
|
_ = timeoutSeconds
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveSourceIP 删除某个源IP
|
||||||
|
func (this *MockFirewall) RemoveSourceIP(ip string) error {
|
||||||
|
_ = ip
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -197,7 +197,7 @@ func (this *IPListManager) processItems(items []*pb.IPItem, shouldExecute bool)
|
|||||||
list.Delete(item.Id)
|
list.Delete(item.Id)
|
||||||
|
|
||||||
// 从WAF名单中删除
|
// 从WAF名单中删除
|
||||||
waf.SharedIPBlackList.RemoveIP(item.IpFrom, item.ServerId)
|
waf.SharedIPBlackList.RemoveIP(item.IpFrom, item.ServerId, shouldExecute)
|
||||||
|
|
||||||
// 操作事件
|
// 操作事件
|
||||||
if shouldExecute {
|
if shouldExecute {
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
"github.com/TeaOSLab/EdgeNode/internal/configs"
|
"github.com/TeaOSLab/EdgeNode/internal/configs"
|
||||||
teaconst "github.com/TeaOSLab/EdgeNode/internal/const"
|
teaconst "github.com/TeaOSLab/EdgeNode/internal/const"
|
||||||
"github.com/TeaOSLab/EdgeNode/internal/events"
|
"github.com/TeaOSLab/EdgeNode/internal/events"
|
||||||
|
"github.com/TeaOSLab/EdgeNode/internal/firewalls"
|
||||||
"github.com/TeaOSLab/EdgeNode/internal/goman"
|
"github.com/TeaOSLab/EdgeNode/internal/goman"
|
||||||
"github.com/TeaOSLab/EdgeNode/internal/iplibrary"
|
"github.com/TeaOSLab/EdgeNode/internal/iplibrary"
|
||||||
"github.com/TeaOSLab/EdgeNode/internal/metrics"
|
"github.com/TeaOSLab/EdgeNode/internal/metrics"
|
||||||
@@ -636,6 +637,47 @@ func (this *Node) listenSock() error {
|
|||||||
"limiter": sharedConnectionsLimiter.Len(),
|
"limiter": sharedConnectionsLimiter.Len(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
case "dropIP":
|
||||||
|
var m = maps.NewMap(cmd.Params)
|
||||||
|
var ip = m.GetString("ip")
|
||||||
|
var timeSeconds = m.GetInt("timeoutSeconds")
|
||||||
|
err := firewalls.Firewall().DropSourceIP(ip, timeSeconds)
|
||||||
|
if err != nil {
|
||||||
|
_ = cmd.Reply(&gosock.Command{
|
||||||
|
Params: map[string]interface{}{
|
||||||
|
"error": err.Error(),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
_ = cmd.ReplyOk()
|
||||||
|
}
|
||||||
|
case "rejectIP":
|
||||||
|
var m = maps.NewMap(cmd.Params)
|
||||||
|
var ip = m.GetString("ip")
|
||||||
|
var timeSeconds = m.GetInt("timeoutSeconds")
|
||||||
|
err := firewalls.Firewall().RejectSourceIP(ip, timeSeconds)
|
||||||
|
if err != nil {
|
||||||
|
_ = cmd.Reply(&gosock.Command{
|
||||||
|
Params: map[string]interface{}{
|
||||||
|
"error": err.Error(),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
_ = cmd.ReplyOk()
|
||||||
|
}
|
||||||
|
case "removeIP":
|
||||||
|
var m = maps.NewMap(cmd.Params)
|
||||||
|
var ip = m.GetString("ip")
|
||||||
|
err := firewalls.Firewall().RemoveSourceIP(ip)
|
||||||
|
if err != nil {
|
||||||
|
_ = cmd.Reply(&gosock.Command{
|
||||||
|
Params: map[string]interface{}{
|
||||||
|
"error": err.Error(),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
_ = cmd.ReplyOk()
|
||||||
|
}
|
||||||
case "gc":
|
case "gc":
|
||||||
runtime.GC()
|
runtime.GC()
|
||||||
debug.FreeOSMemory()
|
debug.FreeOSMemory()
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ func (this *WAFManager) convertWAF(policy *firewallconfigs.HTTPFirewallPolicy) (
|
|||||||
IsOn: policy.IsOn,
|
IsOn: policy.IsOn,
|
||||||
Name: policy.Name,
|
Name: policy.Name,
|
||||||
Mode: policy.Mode,
|
Mode: policy.Mode,
|
||||||
|
UseLocalFirewall: policy.UseLocalFirewall,
|
||||||
}
|
}
|
||||||
|
|
||||||
// inbound
|
// inbound
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ func (this *BlockAction) Perform(waf *WAF, group *RuleGroup, set *RuleSet, reque
|
|||||||
timeout = 60 // 默认封锁60秒
|
timeout = 60 // 默认封锁60秒
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedIPBlackList.RecordIP(IPTypeAll, this.Scope, request.WAFServerId(), request.WAFRemoteIP(), time.Now().Unix()+int64(timeout), waf.Id, group.Id, set.Id)
|
SharedIPBlackList.RecordIP(IPTypeAll, this.Scope, request.WAFServerId(), request.WAFRemoteIP(), time.Now().Unix()+int64(timeout), waf.Id, waf.UseLocalFirewall, group.Id, set.Id)
|
||||||
|
|
||||||
if writer != nil {
|
if writer != nil {
|
||||||
// close the connection
|
// close the connection
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ func (this *Post307Action) Perform(waf *WAF, group *RuleGroup, set *RuleSet, req
|
|||||||
life = 600 // 默认10分钟
|
life = 600 // 默认10分钟
|
||||||
}
|
}
|
||||||
var setId = m.GetString("setId")
|
var setId = m.GetString("setId")
|
||||||
SharedIPWhiteList.RecordIP("set:"+setId, this.Scope, request.WAFServerId(), request.WAFRemoteIP(), time.Now().Unix()+life, m.GetInt64("policyId"), m.GetInt64("groupId"), m.GetInt64("setId"))
|
SharedIPWhiteList.RecordIP("set:"+setId, this.Scope, request.WAFServerId(), request.WAFRemoteIP(), time.Now().Unix()+life, m.GetInt64("policyId"), false, m.GetInt64("groupId"), m.GetInt64("setId"))
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ func (this *CaptchaValidator) validate(actionConfig *CaptchaAction, policyId int
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 加入到白名单
|
// 加入到白名单
|
||||||
SharedIPWhiteList.RecordIP("set:"+strconv.FormatInt(setId, 10), actionConfig.Scope, request.WAFServerId(), request.WAFRemoteIP(), time.Now().Unix()+int64(life), policyId, groupId, setId)
|
SharedIPWhiteList.RecordIP("set:"+strconv.FormatInt(setId, 10), actionConfig.Scope, request.WAFServerId(), request.WAFRemoteIP(), time.Now().Unix()+int64(life), policyId, false, groupId, setId)
|
||||||
|
|
||||||
http.Redirect(writer, request.WAFRaw(), originURL, http.StatusSeeOther)
|
http.Redirect(writer, request.WAFRaw(), originURL, http.StatusSeeOther)
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ func (this *Get302Validator) Run(request requests.Request, writer http.ResponseW
|
|||||||
life = 600 // 默认10分钟
|
life = 600 // 默认10分钟
|
||||||
}
|
}
|
||||||
setId := m.GetString("setId")
|
setId := m.GetString("setId")
|
||||||
SharedIPWhiteList.RecordIP("set:"+setId, m.GetString("scope"), request.WAFServerId(), request.WAFRemoteIP(), time.Now().Unix()+life, m.GetInt64("policyId"), m.GetInt64("groupId"), m.GetInt64("setId"))
|
SharedIPWhiteList.RecordIP("set:"+setId, m.GetString("scope"), request.WAFServerId(), request.WAFRemoteIP(), time.Now().Unix()+life, m.GetInt64("policyId"), false, m.GetInt64("groupId"), m.GetInt64("setId"))
|
||||||
|
|
||||||
// 返回原始URL
|
// 返回原始URL
|
||||||
var url = m.GetString("url")
|
var url = m.GetString("url")
|
||||||
|
|||||||
@@ -4,10 +4,12 @@ package waf
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
||||||
|
"github.com/TeaOSLab/EdgeNode/internal/firewalls"
|
||||||
"github.com/TeaOSLab/EdgeNode/internal/utils/expires"
|
"github.com/TeaOSLab/EdgeNode/internal/utils/expires"
|
||||||
"github.com/iwind/TeaGo/types"
|
"github.com/iwind/TeaGo/types"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var SharedIPWhiteList = NewIPList(IPListTypeAllow)
|
var SharedIPWhiteList = NewIPList(IPListTypeAllow)
|
||||||
@@ -71,10 +73,19 @@ func (this *IPList) Add(ipType string, scope firewallconfigs.FirewallScope, serv
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RecordIP 记录IP
|
// RecordIP 记录IP
|
||||||
func (this *IPList) RecordIP(ipType string, scope firewallconfigs.FirewallScope, serverId int64, ip string, expiresAt int64, policyId int64, groupId int64, setId int64) {
|
func (this *IPList) RecordIP(ipType string,
|
||||||
|
scope firewallconfigs.FirewallScope,
|
||||||
|
serverId int64,
|
||||||
|
ip string,
|
||||||
|
expiresAt int64,
|
||||||
|
policyId int64,
|
||||||
|
useLocalFirewall bool,
|
||||||
|
groupId int64,
|
||||||
|
setId int64) {
|
||||||
this.Add(ipType, scope, serverId, ip, expiresAt)
|
this.Add(ipType, scope, serverId, ip, expiresAt)
|
||||||
|
|
||||||
if this.listType == IPListTypeDeny {
|
if this.listType == IPListTypeDeny {
|
||||||
|
// 加入队列等待上传
|
||||||
select {
|
select {
|
||||||
case recordIPTaskChan <- &recordIPTask{
|
case recordIPTaskChan <- &recordIPTask{
|
||||||
ip: ip,
|
ip: ip,
|
||||||
@@ -90,6 +101,18 @@ func (this *IPList) RecordIP(ipType string, scope firewallconfigs.FirewallScope,
|
|||||||
default:
|
default:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 使用本地防火墙
|
||||||
|
if useLocalFirewall {
|
||||||
|
var seconds = expiresAt - time.Now().Unix()
|
||||||
|
if seconds > 0 {
|
||||||
|
// 最大3600,防止误封时间过长
|
||||||
|
if seconds > 3600 {
|
||||||
|
seconds = 3600
|
||||||
|
}
|
||||||
|
_ = firewalls.Firewall().DropSourceIP(ip, int(seconds))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,13 +134,18 @@ func (this *IPList) Contains(ipType string, scope firewallconfigs.FirewallScope,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RemoveIP 删除IP
|
// RemoveIP 删除IP
|
||||||
func (this *IPList) RemoveIP(ip string, serverId int64) {
|
func (this *IPList) RemoveIP(ip string, serverId int64, shouldExecute bool) {
|
||||||
this.locker.Lock()
|
this.locker.Lock()
|
||||||
delete(this.ipMap, "*@"+ip+"@"+IPTypeAll)
|
delete(this.ipMap, "*@"+ip+"@"+IPTypeAll)
|
||||||
if serverId > 0 {
|
if serverId > 0 {
|
||||||
delete(this.ipMap, types.String(serverId)+"@"+ip+"@"+IPTypeAll)
|
delete(this.ipMap, types.String(serverId)+"@"+ip+"@"+IPTypeAll)
|
||||||
}
|
}
|
||||||
this.locker.Unlock()
|
this.locker.Unlock()
|
||||||
|
|
||||||
|
// 从本地防火墙中删除
|
||||||
|
if shouldExecute {
|
||||||
|
_ = firewalls.Firewall().RemoveSourceIP(ip)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *IPList) remove(id int64) {
|
func (this *IPList) remove(id int64) {
|
||||||
|
|||||||
@@ -43,9 +43,9 @@ func Test_Template2(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
waf := Template()
|
waf := Template()
|
||||||
err = waf.Init()
|
var errs = waf.Init()
|
||||||
if err != nil {
|
if len(errs) > 0 {
|
||||||
t.Fatal(err)
|
t.Fatal(errs[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ type WAF struct {
|
|||||||
Outbound []*RuleGroup `yaml:"outbound" json:"outbound"`
|
Outbound []*RuleGroup `yaml:"outbound" json:"outbound"`
|
||||||
CreatedVersion string `yaml:"createdVersion" json:"createdVersion"`
|
CreatedVersion string `yaml:"createdVersion" json:"createdVersion"`
|
||||||
Mode firewallconfigs.FirewallMode `yaml:"mode" json:"mode"`
|
Mode firewallconfigs.FirewallMode `yaml:"mode" json:"mode"`
|
||||||
|
UseLocalFirewall bool `yaml:"useLocalFirewall" json:"useLocalFirewall"`
|
||||||
|
|
||||||
DefaultBlockAction *BlockAction
|
DefaultBlockAction *BlockAction
|
||||||
|
|
||||||
|
|||||||
@@ -33,9 +33,9 @@ func TestWAF_MatchRequest(t *testing.T) {
|
|||||||
|
|
||||||
waf := NewWAF()
|
waf := NewWAF()
|
||||||
waf.AddRuleGroup(group)
|
waf.AddRuleGroup(group)
|
||||||
err := waf.Init()
|
errs := waf.Init()
|
||||||
if err != nil {
|
if len(errs) > 0 {
|
||||||
t.Fatal(err)
|
t.Fatal(errs[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
req, err := http.NewRequest(http.MethodGet, "http://teaos.cn/hello?name=lu&age=20", nil)
|
req, err := http.NewRequest(http.MethodGet, "http://teaos.cn/hello?name=lu&age=20", nil)
|
||||||
|
|||||||
Reference in New Issue
Block a user