github.com/TeaOSLab/EdgeNode@v1.3.8/internal/iplibrary/action_firewalld.go (about) 1 package iplibrary 2 3 import ( 4 "errors" 5 "fmt" 6 "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" 7 "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs" 8 executils "github.com/TeaOSLab/EdgeNode/internal/utils/exec" 9 "runtime" 10 "time" 11 ) 12 13 // FirewalldAction Firewalld动作管理 14 // 常用命令: 15 // - 查询列表: firewall-cmd --list-all 16 // - 添加IP:firewall-cmd --add-rich-rule="rule family='ipv4' source address='192.168.2.32' reject" --timeout=30s 17 // - 删除IP:firewall-cmd --remove-rich-rule="rule family='ipv4' source address='192.168.2.32' reject" --timeout=30s 18 type FirewalldAction struct { 19 BaseAction 20 21 config *firewallconfigs.FirewallActionFirewalldConfig 22 23 firewalldNotFound bool 24 } 25 26 func NewFirewalldAction() *FirewalldAction { 27 return &FirewalldAction{} 28 } 29 30 func (this *FirewalldAction) Init(config *firewallconfigs.FirewallActionConfig) error { 31 this.config = &firewallconfigs.FirewallActionFirewalldConfig{} 32 err := this.convertParams(config.Params, this.config) 33 if err != nil { 34 return err 35 } 36 return nil 37 } 38 39 func (this *FirewalldAction) AddItem(listType IPListType, item *pb.IPItem) error { 40 return this.runAction("addItem", listType, item) 41 } 42 43 func (this *FirewalldAction) DeleteItem(listType IPListType, item *pb.IPItem) error { 44 return this.runAction("deleteItem", listType, item) 45 } 46 47 func (this *FirewalldAction) runAction(action string, listType IPListType, item *pb.IPItem) error { 48 if item.Type == "all" { 49 return nil 50 } 51 52 if len(item.IpTo) == 0 { 53 return this.runActionSingleIP(action, listType, item) 54 } 55 cidrList, err := iPv4RangeToCIDRRange(item.IpFrom, item.IpTo) 56 if err != nil { 57 // 不合法的范围不予处理即可 58 return nil 59 } 60 if len(cidrList) == 0 { 61 return nil 62 } 63 for _, cidr := range cidrList { 64 item.IpFrom = cidr 65 item.IpTo = "" 66 err := this.runActionSingleIP(action, listType, item) 67 if err != nil { 68 return err 69 } 70 } 71 return nil 72 } 73 74 func (this *FirewalldAction) runActionSingleIP(action string, listType IPListType, item *pb.IPItem) error { 75 timestamp := time.Now().Unix() 76 77 if item.ExpiredAt > 0 && timestamp > item.ExpiredAt { 78 return nil 79 } 80 81 path := this.config.Path 82 var err error 83 if len(path) == 0 { 84 path, err = executils.LookPath("firewall-cmd") 85 if err != nil { 86 if this.firewalldNotFound { 87 return nil 88 } 89 this.firewalldNotFound = true 90 return err 91 } 92 } 93 if len(path) == 0 { 94 return errors.New("can not find 'firewall-cmd'") 95 } 96 97 opt := "" 98 switch action { 99 case "addItem": 100 opt = "--add-rich-rule" 101 case "deleteItem": 102 opt = "--remove-rich-rule" 103 default: 104 return errors.New("invalid action '" + action + "'") 105 } 106 opt += "=rule family='" 107 switch item.Type { 108 case "ipv4": 109 opt += "ipv4" 110 case "ipv6": 111 opt += "ipv6" 112 default: 113 // 我们忽略不能识别的Family 114 return nil 115 } 116 117 opt += "' source address='" 118 if len(item.IpFrom) == 0 { 119 return errors.New("invalid ip from") 120 } 121 opt += item.IpFrom + "' " 122 123 switch listType { 124 case IPListTypeWhite: 125 opt += " accept" 126 case IPListTypeBlack: 127 opt += " reject" 128 default: 129 // 我们忽略不能识别的列表类型 130 return nil 131 } 132 133 args := []string{opt} 134 if action == "addItem" { 135 if item.ExpiredAt > timestamp { 136 args = append(args, "--timeout="+fmt.Sprintf("%d", item.ExpiredAt-timestamp)+"s") 137 } else { 138 // TODO 思考是否需要permanent,不然--reload之后会丢失 139 } 140 } 141 142 if runtime.GOOS == "darwin" { 143 // MAC OS直接返回 144 return nil 145 } 146 cmd := executils.NewTimeoutCmd(30*time.Second, path, args...) 147 cmd.WithStderr() 148 err = cmd.Run() 149 if err != nil { 150 return fmt.Errorf("%w, output: %s", err, cmd.Stderr()) 151 } 152 return nil 153 }