Files
EdgeNode/internal/iplibrary/action_firewalld.go
2022-09-15 11:14:33 +08:00

155 lines
3.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package iplibrary
import (
"errors"
"fmt"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
executils "github.com/TeaOSLab/EdgeNode/internal/utils/exec"
"os/exec"
"runtime"
"time"
)
// FirewalldAction Firewalld动作管理
// 常用命令:
// - 查询列表: firewall-cmd --list-all
// - 添加IPfirewall-cmd --add-rich-rule="rule family='ipv4' source address='192.168.2.32' reject" --timeout=30s
// - 删除IPfirewall-cmd --remove-rich-rule="rule family='ipv4' source address='192.168.2.32' reject" --timeout=30s
type FirewalldAction struct {
BaseAction
config *firewallconfigs.FirewallActionFirewalldConfig
firewalldNotFound bool
}
func NewFirewalldAction() *FirewalldAction {
return &FirewalldAction{}
}
func (this *FirewalldAction) Init(config *firewallconfigs.FirewallActionConfig) error {
this.config = &firewallconfigs.FirewallActionFirewalldConfig{}
err := this.convertParams(config.Params, this.config)
if err != nil {
return err
}
return nil
}
func (this *FirewalldAction) AddItem(listType IPListType, item *pb.IPItem) error {
return this.runAction("addItem", listType, item)
}
func (this *FirewalldAction) DeleteItem(listType IPListType, item *pb.IPItem) error {
return this.runAction("deleteItem", listType, item)
}
func (this *FirewalldAction) runAction(action string, listType IPListType, item *pb.IPItem) error {
if item.Type == "all" {
return nil
}
if len(item.IpTo) == 0 {
return this.runActionSingleIP(action, listType, item)
}
cidrList, err := iPv4RangeToCIDRRange(item.IpFrom, item.IpTo)
if err != nil {
// 不合法的范围不予处理即可
return nil
}
if len(cidrList) == 0 {
return nil
}
for _, cidr := range cidrList {
item.IpFrom = cidr
item.IpTo = ""
err := this.runActionSingleIP(action, listType, item)
if err != nil {
return err
}
}
return nil
}
func (this *FirewalldAction) runActionSingleIP(action string, listType IPListType, item *pb.IPItem) error {
timestamp := time.Now().Unix()
if item.ExpiredAt > 0 && timestamp > item.ExpiredAt {
return nil
}
path := this.config.Path
var err error
if len(path) == 0 {
path, err = exec.LookPath("firewall-cmd")
if err != nil {
if this.firewalldNotFound {
return nil
}
this.firewalldNotFound = true
return err
}
}
if len(path) == 0 {
return errors.New("can not find 'firewall-cmd'")
}
opt := ""
switch action {
case "addItem":
opt = "--add-rich-rule"
case "deleteItem":
opt = "--remove-rich-rule"
default:
return errors.New("invalid action '" + action + "'")
}
opt += "=rule family='"
switch item.Type {
case "ipv4":
opt += "ipv4"
case "ipv6":
opt += "ipv6"
default:
// 我们忽略不能识别的Family
return nil
}
opt += "' source address='"
if len(item.IpFrom) == 0 {
return errors.New("invalid ip from")
}
opt += item.IpFrom + "' "
switch listType {
case IPListTypeWhite:
opt += " accept"
case IPListTypeBlack:
opt += " reject"
default:
// 我们忽略不能识别的列表类型
return nil
}
args := []string{opt}
if action == "addItem" {
if item.ExpiredAt > timestamp {
args = append(args, "--timeout="+fmt.Sprintf("%d", item.ExpiredAt-timestamp)+"s")
} else {
// TODO 思考是否需要permanent不然--reload之后会丢失
}
}
if runtime.GOOS == "darwin" {
// MAC OS直接返回
return nil
}
cmd := executils.NewTimeoutCmd(30*time.Second, path, args...)
cmd.WithStderr()
err = cmd.Run()
if err != nil {
return errors.New(err.Error() + ", output: " + cmd.Stderr())
}
return nil
}