del: 删除获取防火墙相关代码

This commit is contained in:
TsMask
2023-10-26 18:23:29 +08:00
parent 0643bc3df8
commit 1bb322a5a8
9 changed files with 0 additions and 1006 deletions

View File

@@ -1,88 +0,0 @@
package firewall
import (
"net/http"
"ems.agt/features/firewall/model"
"ems.agt/features/firewall/service"
"ems.agt/lib/core/utils/ctx"
"ems.agt/lib/core/vo/result"
"ems.agt/lib/services"
"ems.agt/restagent/config"
)
// 防火墙管理接口添加到路由
func Routers() []services.RouterItem {
// 实例化控制层 FirewallApi 结构体
var apis = &FirewallApi{
firewallService: *service.NewServiceFirewall,
}
rs := [...]services.RouterItem{
{
Method: "GET",
Pattern: "/base",
Handler: apis.BaseInfo,
Middleware: nil, //midware.Authorize(nil),
},
{
Method: "POST",
Pattern: "/rule",
Handler: apis.Rule,
Middleware: nil, //midware.Authorize(nil),
},
// 添加更多的 Router 对象...
}
// 生成两组前缀路由
rsPrefix := []services.RouterItem{}
for _, v := range rs {
path := "/firewallManage/{apiVersion}" + v.Pattern
// 固定前缀
v.Pattern = config.DefaultUriPrefix + path
rsPrefix = append(rsPrefix, v)
// 可配置
v.Pattern = config.UriPrefix + path
rsPrefix = append(rsPrefix, v)
}
return rsPrefix
}
// 防火墙管理
//
// PATH /firewallManage
type FirewallApi struct {
firewallService service.ServiceFirewall
}
// 获取防火墙基础信息
//
// GET /base
func (s *FirewallApi) BaseInfo(w http.ResponseWriter, r *http.Request) {
data, err := s.firewallService.LoadBaseInfo()
if err != nil {
ctx.JSON(w, 200, result.ErrMsg(err.Error()))
return
}
ctx.JSON(w, 200, result.OkData(data))
}
// 获取防火墙规则列表分页
//
// GET /rule
func (s *FirewallApi) Rule(w http.ResponseWriter, r *http.Request) {
var body model.RuleQuerys
err := ctx.ShouldBindJSON(r, &body)
if err != nil || body.Type == "" {
ctx.JSON(w, 400, result.CodeMsg(400, "parameter error"))
return
}
data, err := s.firewallService.RulePage(body)
if err != nil {
ctx.JSON(w, 400, result.ErrMsg(err.Error()))
return
}
ctx.JSON(w, 200, result.OkData(data))
}

View File

@@ -1,13 +0,0 @@
package model
type Firewall struct {
ID int64 `json:"id" xorm:"id"`
CreatedAt int64 `json:"createdAt" xorm:"created_at"`
UpdatedAt int64 `json:"updatedAt" xorm:"updated_at"`
Type string `json:"type" xorm:"type"`
Port string `json:"port" xorm:"port"`
Protocol string `json:"protocol" xorm:"protocol"`
Address string `json:"address" xorm:"address"`
Strategy string `json:"strategy" xorm:"strategy"`
Description string `json:"description" xorm:"description"`
}

View File

@@ -1,64 +0,0 @@
package model
type FirewallBaseInfo struct {
Name string `json:"name"`
Status string `json:"status"`
Version string `json:"version"`
PingStatus string `json:"pingStatus"`
}
type RuleQuerys struct {
PageNum int `json:"pageNum" validate:"required,number"`
PageSize int `json:"pageSize" validate:"required,number"`
Info string `json:"info"`
Status string `json:"status"`
Strategy string `json:"strategy"`
Type string `json:"type" validate:"required"`
}
type FirewallOperation struct {
Operation string `json:"operation" validate:"required,oneof=start stop disablePing enablePing"`
}
type PortRuleOperate struct {
Operation string `json:"operation" validate:"required,oneof=add remove"`
Address string `json:"address"`
Port string `json:"port" validate:"required"`
Protocol string `json:"protocol" validate:"required,oneof=tcp udp tcp/udp"`
Strategy string `json:"strategy" validate:"required,oneof=accept drop"`
Description string `json:"description"`
}
type UpdateFirewallDescription struct {
Type string `json:"type"`
Address string `json:"address"`
Port string `json:"port"`
Protocol string `json:"protocol"`
Strategy string `json:"strategy" validate:"required,oneof=accept drop"`
Description string `json:"description"`
}
type AddrRuleOperate struct {
Operation string `json:"operation" validate:"required,oneof=add remove"`
Address string `json:"address" validate:"required"`
Strategy string `json:"strategy" validate:"required,oneof=accept drop"`
Description string `json:"description"`
}
type PortRuleUpdate struct {
OldRule PortRuleOperate `json:"oldRule"`
NewRule PortRuleOperate `json:"newRule"`
}
type AddrRuleUpdate struct {
OldRule AddrRuleOperate `json:"oldRule"`
NewRule AddrRuleOperate `json:"newRule"`
}
type BatchRuleOperate struct {
Type string `json:"type" validate:"required"`
Rules []PortRuleOperate `json:"rules"`
}

View File

@@ -1,133 +0,0 @@
package repo
import (
"strings"
"ems.agt/features/firewall/model"
"ems.agt/lib/core/datasource"
"ems.agt/lib/log"
)
// 实例化数据层 RepoFirewall 结构体
var NewRepoFirewall = &RepoFirewall{
selectSql: `select
id, created_at, updated_at, type, port, protocol, address, strategy, description
from monitor_firewall`,
resultMap: map[string]string{
"id": "ID",
"created_at": "CreatedAt",
"updated_at": "UpdatedAt",
"type": "Type",
"port": "Port",
"protocol": "Protocol",
"address": "Address",
"strategy": "Strategy",
"description": "Description",
},
}
// RepoFirewall 防火墙 数据层处理
type RepoFirewall struct {
// 查询视图对象SQL
selectSql string
// 结果字段与实体映射
resultMap map[string]string
}
// convertResultRows 将结果记录转实体结果组
func (r *RepoFirewall) convertResultRows(rows []map[string]any) []model.Firewall {
arr := make([]model.Firewall, 0)
for _, row := range rows {
UdmUser := model.Firewall{}
for key, value := range row {
if keyMapper, ok := r.resultMap[key]; ok {
datasource.SetFieldValue(&UdmUser, keyMapper, value)
}
}
arr = append(arr, UdmUser)
}
return arr
}
// List 根据实体查询
func (r *RepoFirewall) List(f model.Firewall) []model.Firewall {
// 查询条件拼接
var conditions []string
var params []any
if f.Type != "" {
conditions = append(conditions, "type = ?")
params = append(params, f.Type)
}
if f.Protocol != "" {
conditions = append(conditions, "protocol = ?")
params = append(params, f.Protocol)
}
// 构建查询条件语句
whereSql := ""
if len(conditions) > 0 {
whereSql += " where " + strings.Join(conditions, " and ")
}
// 查询数据
querySql := r.selectSql + whereSql
results, err := datasource.RawDB("", querySql, params)
if err != nil {
log.Errorf("query err => %v", err)
}
// 转换实体
return r.convertResultRows(results)
}
// Insert 新增实体
func (r *RepoFirewall) Insert(f model.Firewall) int64 {
results, err := datasource.DefaultDB().Table("monitor_firewall").Insert(f)
if err != nil {
return results
}
return results
}
// Update 修改更新
func (r *RepoFirewall) Update(f model.Firewall) int64 {
// 查询先
var fd model.Firewall
if f.Type == "port" {
has, err := datasource.DefaultDB().Table("monitor_firewall").Where("type = ? AND port = ? AND protocol = ? AND address = ? AND strategy = ?", "port", f.Port, f.Protocol, f.Address, f.Strategy).Get(&fd)
if !has || err != nil {
return 0
}
} else {
has, err := datasource.DefaultDB().Table("monitor_firewall").Where("type = ? AND address = ? AND strategy = ?", "address", f.Address, f.Strategy).Get(&fd)
if !has || err != nil {
return 0
}
}
f.ID = fd.ID
results, err := datasource.DefaultDB().Table("monitor_firewall").Where("id = ?", f.ID).Update(f)
if err != nil {
return 0
}
return results
}
// Delete 删除实体
func (r *RepoFirewall) Delete(id int64) int64 {
results, err := datasource.DefaultDB().Table("u_sub_user").Where("id = ?", id).Delete()
if err != nil {
return results
}
return results
}
// DeleteFirewallRecord 删除实体
func (r *RepoFirewall) DeleteFirewallRecord(fType, port, protocol, address, strategy string) int64 {
results, err := datasource.DefaultDB().Table("u_sub_user").Where("type = ? AND port = ? AND protocol = ? AND address = ? AND strategy = ?", fType, port, protocol, address, strategy).Delete()
if err != nil {
return results
}
return results
}

View File

@@ -1,207 +0,0 @@
package service
import (
"fmt"
"os"
"strconv"
"strings"
"ems.agt/features/firewall/model"
"ems.agt/features/firewall/repo"
"ems.agt/lib/core/cmd"
"ems.agt/lib/core/utils/firewall"
fireClient "ems.agt/lib/core/utils/firewall/client"
"ems.agt/lib/core/utils/scan"
)
// 实例化服务层 ServiceFirewall 结构体
var NewServiceFirewall = &ServiceFirewall{
repoFirewall: *repo.NewRepoFirewall,
}
// ServiceFirewall 防火墙 服务层处理
type ServiceFirewall struct {
repoFirewall repo.RepoFirewall
}
// LoadBaseInfo 获取防火墙基础信息
func (s *ServiceFirewall) LoadBaseInfo() (model.FirewallBaseInfo, error) {
var baseInfo model.FirewallBaseInfo
baseInfo.PingStatus = s.pingStatus()
baseInfo.Status = "not running"
baseInfo.Version = "-"
baseInfo.Name = "-"
client, err := firewall.NewFirewallClient()
if err != nil {
if err.Error() == "no such type" {
return baseInfo, nil
}
return baseInfo, err
}
baseInfo.Name = client.Name()
baseInfo.Status, err = client.Status()
if err != nil {
return baseInfo, err
}
if baseInfo.Status == "not running" {
return baseInfo, err
}
baseInfo.Version, err = client.Version()
if err != nil {
return baseInfo, err
}
return baseInfo, nil
}
// LoadBaseInfo 获取防火墙基础信息
func (s *ServiceFirewall) RulePage(querys model.RuleQuerys) (map[string]any, error) {
var (
datas []fireClient.FireInfo
backDatas []fireClient.FireInfo
)
data := map[string]any{
"total": 0,
"rows": backDatas,
}
client, err := firewall.NewFirewallClient()
if err != nil {
return data, err
}
if querys.Type == "port" {
ports, err := client.ListPort()
if err != nil {
return data, err
}
if len(querys.Info) != 0 {
for _, port := range ports {
if strings.Contains(port.Port, querys.Info) {
datas = append(datas, port)
}
}
} else {
datas = ports
}
} else {
addrs, err := client.ListAddress()
if err != nil {
return data, err
}
if len(querys.Info) != 0 {
for _, addr := range addrs {
if strings.Contains(addr.Address, querys.Info) {
datas = append(datas, addr)
}
}
} else {
datas = addrs
}
}
var datasFilterStatus []fireClient.FireInfo
if len(querys.Status) != 0 {
for _, data := range datas {
portItem, _ := strconv.Atoi(data.Port)
if querys.Status == "free" && !scan.ScanPortWithProto(portItem, data.Protocol) {
datasFilterStatus = append(datasFilterStatus, data)
}
if querys.Status == "used" && scan.ScanPortWithProto(portItem, data.Protocol) {
datasFilterStatus = append(datasFilterStatus, data)
}
}
} else {
datasFilterStatus = datas
}
var datasFilterStrategy []fireClient.FireInfo
if len(querys.Strategy) != 0 {
for _, data := range datasFilterStatus {
if querys.Strategy == data.Strategy {
datasFilterStrategy = append(datasFilterStrategy, data)
}
}
} else {
datasFilterStrategy = datasFilterStatus
}
total, start, end := len(datasFilterStrategy), (querys.PageNum-1)*querys.PageSize, querys.PageNum*querys.PageSize
if start > total {
backDatas = make([]fireClient.FireInfo, 0)
} else {
if end >= total {
end = total
}
backDatas = datasFilterStrategy[start:end]
}
datasFromDB := s.repoFirewall.List(model.Firewall{})
for i := 0; i < len(backDatas); i++ {
for _, des := range datasFromDB {
if querys.Type != des.Type {
continue
}
if backDatas[i].Port == des.Port && querys.Type == "port" &&
backDatas[i].Protocol == des.Protocol &&
backDatas[i].Strategy == des.Strategy &&
backDatas[i].Address == des.Address {
backDatas[i].Description = des.Description
break
}
if querys.Type == "address" && backDatas[i].Strategy == des.Strategy && backDatas[i].Address == des.Address {
backDatas[i].Description = des.Description
break
}
}
}
if querys.Type == "port" {
for i := 0; i < len(backDatas); i++ {
port, _ := strconv.Atoi(backDatas[i].Port)
backDatas[i].IsUsed = scan.ScanPort(port)
if backDatas[i].Protocol == "udp" {
backDatas[i].IsUsed = scan.ScanUDPPort(port)
continue
}
}
}
go s.cleanUnUsedData(client)
return data, nil
}
func (s *ServiceFirewall) pingStatus() string {
if _, err := os.Stat("/etc/sysctl.conf"); err != nil {
return "None"
}
sudo := cmd.SudoHandleCmd()
command := fmt.Sprintf("%s cat /etc/sysctl.conf | grep net/ipv4/icmp_echo_ignore_all= ", sudo)
stdout, _ := cmd.Exec(command)
if stdout == "net/ipv4/icmp_echo_ignore_all=1\n" {
return "Enable"
}
return "Disable"
}
func (s *ServiceFirewall) cleanUnUsedData(client firewall.FirewallClient) {
list, _ := client.ListPort()
addressList, _ := client.ListAddress()
list = append(list, addressList...)
if len(list) == 0 {
return
}
records := s.repoFirewall.List(model.Firewall{})
if len(records) == 0 {
return
}
for _, item := range list {
for i := 0; i < len(records); i++ {
if records[i].Port == item.Port && records[i].Protocol == item.Protocol && records[i].Strategy == item.Strategy && records[i].Address == item.Address {
records = append(records[:i], records[i+1:]...)
}
}
}
for _, record := range records {
_ = s.repoFirewall.Delete(record.ID)
}
}

View File

@@ -1,34 +0,0 @@
package firewall
import (
"errors"
"os"
"ems.agt/lib/core/utils/firewall/client"
)
type FirewallClient interface {
Name() string // ufw firewalld
Start() error
Stop() error
Reload() error
Status() (string, error) // running not running
Version() (string, error)
ListPort() ([]client.FireInfo, error)
ListAddress() ([]client.FireInfo, error)
Port(port client.FireInfo, operation string) error
RichRules(rule client.FireInfo, operation string) error
PortForward(info client.Forward, operation string) error
}
func NewFirewallClient() (FirewallClient, error) {
if _, err := os.Stat("/usr/sbin/firewalld"); err == nil {
return client.NewFirewalld()
}
if _, err := os.Stat("/usr/sbin/ufw"); err == nil {
return client.NewUfw()
}
return nil, errors.New("no such type")
}

View File

@@ -1,209 +0,0 @@
package client
import (
"fmt"
"strings"
"sync"
"ems.agt/lib/core/cmd"
)
type Firewall struct{}
func NewFirewalld() (*Firewall, error) {
return &Firewall{}, nil
}
func (f *Firewall) Name() string {
return "firewalld"
}
func (f *Firewall) Status() (string, error) {
stdout, _ := cmd.Exec("firewall-cmd --state")
if stdout == "running\n" {
return "running", nil
}
return "not running", nil
}
func (f *Firewall) Version() (string, error) {
stdout, err := cmd.Exec("firewall-cmd --version")
if err != nil {
return "", fmt.Errorf("load the firewall version failed, err: %s", stdout)
}
return strings.ReplaceAll(stdout, "\n ", ""), nil
}
func (f *Firewall) Start() error {
stdout, err := cmd.Exec("systemctl start firewalld")
if err != nil {
return fmt.Errorf("enable the firewall failed, err: %s", stdout)
}
return nil
}
func (f *Firewall) Stop() error {
stdout, err := cmd.Exec("systemctl stop firewalld")
if err != nil {
return fmt.Errorf("stop the firewall failed, err: %s", stdout)
}
return nil
}
func (f *Firewall) Reload() error {
stdout, err := cmd.Exec("firewall-cmd --reload")
if err != nil {
return fmt.Errorf("reload firewall failed, err: %s", stdout)
}
return nil
}
func (f *Firewall) ListPort() ([]FireInfo, error) {
var wg sync.WaitGroup
var datas []FireInfo
wg.Add(2)
go func() {
defer wg.Done()
stdout, err := cmd.Exec("firewall-cmd --zone=public --list-ports")
if err != nil {
return
}
ports := strings.Split(strings.ReplaceAll(stdout, "\n", ""), " ")
for _, port := range ports {
if len(port) == 0 {
continue
}
var itemPort FireInfo
if strings.Contains(port, "/") {
itemPort.Port = strings.Split(port, "/")[0]
itemPort.Protocol = strings.Split(port, "/")[1]
}
itemPort.Strategy = "accept"
datas = append(datas, itemPort)
}
}()
go func() {
defer wg.Done()
stdout1, err := cmd.Exec("firewall-cmd --zone=public --list-rich-rules")
if err != nil {
return
}
rules := strings.Split(stdout1, "\n")
for _, rule := range rules {
if len(rule) == 0 {
continue
}
itemRule := f.loadInfo(rule)
if len(itemRule.Port) != 0 && itemRule.Family == "ipv4" {
datas = append(datas, itemRule)
}
}
}()
wg.Wait()
return datas, nil
}
func (f *Firewall) ListAddress() ([]FireInfo, error) {
stdout, err := cmd.Exec("firewall-cmd --zone=public --list-rich-rules")
if err != nil {
return nil, err
}
var datas []FireInfo
rules := strings.Split(stdout, "\n")
for _, rule := range rules {
if len(rule) == 0 {
continue
}
itemRule := f.loadInfo(rule)
if len(itemRule.Port) == 0 && len(itemRule.Address) != 0 {
datas = append(datas, itemRule)
}
}
return datas, nil
}
func (f *Firewall) Port(port FireInfo, operation string) error {
if cmd.CheckIllegal(operation, port.Protocol, port.Port) {
return fmt.Errorf("errCmdIllegal %v", port)
}
stdout, err := cmd.Execf("firewall-cmd --zone=public --%s-port=%s/%s --permanent", operation, port.Port, port.Protocol)
if err != nil {
return fmt.Errorf("%s port failed, err: %s", operation, stdout)
}
return nil
}
func (f *Firewall) RichRules(rule FireInfo, operation string) error {
if cmd.CheckIllegal(operation, rule.Address, rule.Protocol, rule.Port, rule.Strategy) {
return fmt.Errorf("errCmdIllegal %v", rule)
}
ruleStr := ""
if strings.Contains(rule.Address, "-") {
std, err := cmd.Execf("firewall-cmd --permanent --new-ipset=%s --type=hash:ip", rule.Address)
if err != nil {
return fmt.Errorf("add new ipset failed, err: %s", std)
}
std2, err := cmd.Execf("firewall-cmd --permanent --ipset=%s --add-entry=%s", rule.Address, rule.Address)
if err != nil {
return fmt.Errorf("add entry to ipset failed, err: %s", std2)
}
if err := f.Reload(); err != nil {
return err
}
ruleStr = fmt.Sprintf("rule source ipset=%s %s", rule.Address, rule.Strategy)
} else {
ruleStr = "rule family=ipv4 "
if len(rule.Address) != 0 {
ruleStr += fmt.Sprintf("source address=%s ", rule.Address)
}
if len(rule.Port) != 0 {
ruleStr += fmt.Sprintf("port port=%s ", rule.Port)
}
if len(rule.Protocol) != 0 {
ruleStr += fmt.Sprintf("protocol=%s ", rule.Protocol)
}
ruleStr += rule.Strategy
}
stdout, err := cmd.Execf("firewall-cmd --zone=public --%s-rich-rule '%s' --permanent", operation, ruleStr)
if err != nil {
return fmt.Errorf("%s rich rules failed, err: %s", operation, stdout)
}
return nil
}
func (f *Firewall) PortForward(info Forward, operation string) error {
ruleStr := fmt.Sprintf("firewall-cmd --%s-forward-port=port=%s:proto=%s:toport=%s --permanent", operation, info.Port, info.Protocol, info.Target)
if len(info.Address) != 0 {
ruleStr = fmt.Sprintf("firewall-cmd --%s-forward-port=port=%s:proto=%s:toaddr=%s:toport=%s --permanent", operation, info.Port, info.Protocol, info.Address, info.Target)
}
stdout, err := cmd.Exec(ruleStr)
if err != nil {
return fmt.Errorf("%s port forward failed, err: %s", operation, stdout)
}
return nil
}
func (f *Firewall) loadInfo(line string) FireInfo {
var itemRule FireInfo
ruleInfo := strings.Split(strings.ReplaceAll(line, "\"", ""), " ")
for _, item := range ruleInfo {
switch {
case strings.Contains(item, "family="):
itemRule.Family = strings.ReplaceAll(item, "family=", "")
case strings.Contains(item, "ipset="):
itemRule.Address = strings.ReplaceAll(item, "ipset=", "")
case strings.Contains(item, "address="):
itemRule.Address = strings.ReplaceAll(item, "address=", "")
case strings.Contains(item, "port="):
itemRule.Port = strings.ReplaceAll(item, "port=", "")
case strings.Contains(item, "protocol="):
itemRule.Protocol = strings.ReplaceAll(item, "protocol=", "")
case item == "accept" || item == "drop" || item == "reject":
itemRule.Strategy = item
}
}
return itemRule
}

View File

@@ -1,20 +0,0 @@
package client
type FireInfo struct {
Family string `json:"family"` // ipv4 ipv6
Address string `json:"address"` // Anywhere
Port string `json:"port"`
Protocol string `json:"protocol"` // tcp udp tcp/udp
Strategy string `json:"strategy"` // accept drop
APPName string `json:"appName"`
IsUsed bool `json:"isUsed"`
Description string `json:"description"`
}
type Forward struct {
Protocol string `json:"protocol"`
Address string `json:"address"`
Port string `json:"port"`
Target string `json:"target"`
}

View File

@@ -1,238 +0,0 @@
package client
import (
"fmt"
"strings"
"ems.agt/lib/core/cmd"
)
type Ufw struct {
CmdStr string
}
func NewUfw() (*Ufw, error) {
var ufw Ufw
if cmd.HasNoPasswordSudo() {
ufw.CmdStr = "sudo ufw"
} else {
ufw.CmdStr = "ufw"
}
return &ufw, nil
}
func (f *Ufw) Name() string {
return "ufw"
}
func (f *Ufw) Status() (string, error) {
stdout, _ := cmd.Execf("%s status | grep Status", f.CmdStr)
if stdout == "Status: active\n" {
return "running", nil
}
stdout1, _ := cmd.Execf("%s status | grep 状态", f.CmdStr)
if stdout1 == "状态: 激活\n" {
return "running", nil
}
return "not running", nil
}
func (f *Ufw) Version() (string, error) {
stdout, err := cmd.Execf("%s version | grep ufw", f.CmdStr)
if err != nil {
return "", fmt.Errorf("load the firewall status failed, err: %s", stdout)
}
info := strings.ReplaceAll(stdout, "\n", "")
return strings.ReplaceAll(info, "ufw ", ""), nil
}
func (f *Ufw) Start() error {
stdout, err := cmd.Execf("echo y | %s enable", f.CmdStr)
if err != nil {
return fmt.Errorf("enable the firewall failed, err: %s", stdout)
}
return nil
}
func (f *Ufw) Stop() error {
stdout, err := cmd.Execf("%s disable", f.CmdStr)
if err != nil {
return fmt.Errorf("stop the firewall failed, err: %s", stdout)
}
return nil
}
func (f *Ufw) Reload() error {
return nil
}
func (f *Ufw) ListPort() ([]FireInfo, error) {
stdout, err := cmd.Execf("%s status verbose", f.CmdStr)
if err != nil {
return nil, err
}
portInfos := strings.Split(stdout, "\n")
var datas []FireInfo
isStart := false
for _, line := range portInfos {
if strings.HasPrefix(line, "-") {
isStart = true
continue
}
if !isStart {
continue
}
itemFire := f.loadInfo(line, "port")
if len(itemFire.Port) != 0 && itemFire.Port != "Anywhere" && !strings.Contains(itemFire.Port, ".") {
itemFire.Port = strings.ReplaceAll(itemFire.Port, ":", "-")
datas = append(datas, itemFire)
}
}
return datas, nil
}
func (f *Ufw) ListAddress() ([]FireInfo, error) {
stdout, err := cmd.Execf("%s status verbose", f.CmdStr)
if err != nil {
return nil, err
}
portInfos := strings.Split(stdout, "\n")
var datas []FireInfo
isStart := false
for _, line := range portInfos {
if strings.HasPrefix(line, "-") {
isStart = true
continue
}
if !isStart {
continue
}
if !strings.Contains(line, " IN") {
continue
}
itemFire := f.loadInfo(line, "address")
if strings.Contains(itemFire.Port, ".") {
itemFire.Address += ("-" + itemFire.Port)
itemFire.Port = ""
}
if len(itemFire.Port) == 0 && len(itemFire.Address) != 0 {
datas = append(datas, itemFire)
}
}
return datas, nil
}
func (f *Ufw) Port(port FireInfo, operation string) error {
switch port.Strategy {
case "accept":
port.Strategy = "allow"
case "drop":
port.Strategy = "deny"
default:
return fmt.Errorf("unsupport strategy %s", port.Strategy)
}
if cmd.CheckIllegal(port.Protocol, port.Port) {
return fmt.Errorf("errCmdIllegal %v", port)
}
command := fmt.Sprintf("%s %s %s", f.CmdStr, port.Strategy, port.Port)
if operation == "remove" {
command = fmt.Sprintf("%s delete %s %s", f.CmdStr, port.Strategy, port.Port)
}
if len(port.Protocol) != 0 {
command += fmt.Sprintf("/%s", port.Protocol)
}
stdout, err := cmd.Exec(command)
if err != nil {
return fmt.Errorf("%s port failed, err: %s", operation, stdout)
}
return nil
}
func (f *Ufw) RichRules(rule FireInfo, operation string) error {
switch rule.Strategy {
case "accept":
rule.Strategy = "allow"
case "drop":
rule.Strategy = "deny"
default:
return fmt.Errorf("unsupport strategy %s", rule.Strategy)
}
if cmd.CheckIllegal(operation, rule.Protocol, rule.Address, rule.Port) {
return fmt.Errorf("errCmdIllegal %v", rule)
}
ruleStr := fmt.Sprintf("%s %s ", f.CmdStr, rule.Strategy)
if operation == "remove" {
ruleStr = fmt.Sprintf("%s delete %s ", f.CmdStr, rule.Strategy)
}
if len(rule.Protocol) != 0 {
ruleStr += fmt.Sprintf("proto %s ", rule.Protocol)
}
if strings.Contains(rule.Address, "-") {
ruleStr += fmt.Sprintf("from %s to %s ", strings.Split(rule.Address, "-")[0], strings.Split(rule.Address, "-")[1])
} else {
ruleStr += fmt.Sprintf("from %s ", rule.Address)
}
if len(rule.Port) != 0 {
ruleStr += fmt.Sprintf("to any port %s ", rule.Port)
}
stdout, err := cmd.Exec(ruleStr)
if err != nil {
return fmt.Errorf("%s rich rules failed, err: %s", operation, stdout)
}
return nil
}
func (f *Ufw) PortForward(info Forward, operation string) error {
ruleStr := fmt.Sprintf("firewall-cmd --%s-forward-port=port=%s:proto=%s:toport=%s --permanent", operation, info.Port, info.Protocol, info.Target)
if len(info.Address) != 0 {
ruleStr = fmt.Sprintf("firewall-cmd --%s-forward-port=port=%s:proto=%s:toaddr=%s:toport=%s --permanent", operation, info.Port, info.Protocol, info.Address, info.Target)
}
stdout, err := cmd.Exec(ruleStr)
if err != nil {
return fmt.Errorf("%s port forward failed, err: %s", operation, stdout)
}
if err := f.Reload(); err != nil {
return err
}
return nil
}
func (f *Ufw) loadInfo(line string, fireType string) FireInfo {
fields := strings.Fields(line)
var itemInfo FireInfo
if len(fields) < 4 {
return itemInfo
}
if fields[1] == "(v6)" {
return itemInfo
}
if fields[0] == "Anywhere" && fireType != "port" {
itemInfo.Strategy = "drop"
if fields[1] == "ALLOW" {
itemInfo.Strategy = "accept"
}
itemInfo.Address = fields[3]
return itemInfo
}
if strings.Contains(fields[0], "/") {
itemInfo.Port = strings.Split(fields[0], "/")[0]
itemInfo.Protocol = strings.Split(fields[0], "/")[1]
} else {
itemInfo.Port = fields[0]
itemInfo.Protocol = "tcp/udp"
}
itemInfo.Family = "ipv4"
if fields[1] == "ALLOW" {
itemInfo.Strategy = "accept"
} else {
itemInfo.Strategy = "drop"
}
itemInfo.Address = fields[3]
return itemInfo
}