Archived
自动使用本地防火墙/增加edge-node [ip.drop|ip.reject|ip.remove]等命令
This commit is contained in:
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user