Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions backend/app/api/v1/firewall.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,31 @@ func (b *BaseApi) BatchOperateRule(c *gin.Context) {
helper.SuccessWithData(c, nil)
}

// @Tags Firewall
// @Summary Update rule description
// @Description 更新防火墙描述
// @Accept json
// @Param request body dto.UpdateFirewallDescription true "request"
// @Success 200
// @Security ApiKeyAuth
// @Router /hosts/firewall/update/description [post]
func (b *BaseApi) UpdateFirewallDescription(c *gin.Context) {
var req dto.UpdateFirewallDescription
if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := global.VALID.Struct(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := firewallService.UpdateDescription(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, nil)
}

// @Tags Firewall
// @Summary Create group
// @Description 更新端口防火墙规则
Expand Down
13 changes: 13 additions & 0 deletions backend/app/dto/firewall.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,25 @@ type PortRuleOperate struct {
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 {
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 {
Expand Down
11 changes: 11 additions & 0 deletions backend/app/model/firewall.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package model

type Firewall struct {
BaseModel

Port string `gorm:"type:varchar(64);not null" json:"port"`
Protocol string `gorm:"type:varchar(64);not null" json:"protocol"`
Address string `gorm:"type:varchar(64);not null" json:"address"`
Strategy string `gorm:"type:varchar(64);not null" json:"strategy"`
Description string `gorm:"type:varchar(64);not null" json:"description"`
}
44 changes: 44 additions & 0 deletions backend/app/repo/host.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ type IHostRepo interface {
Create(host *model.Host) error
Update(id uint, vars map[string]interface{}) error
Delete(opts ...DBOption) error

GetFirewallRecord(opts ...DBOption) (model.Firewall, error)
ListFirewallRecord() ([]model.Firewall, error)
SaveFirewallRecord(firewall *model.Firewall) error
DeleteFirewallRecordByID(id uint) error
DeleteFirewallRecord(port, protocol, address, strategy string) error
}

func NewIHostRepo() IHostRepo {
Expand Down Expand Up @@ -106,3 +112,41 @@ func (h *HostRepo) Delete(opts ...DBOption) error {
}
return db.Delete(&model.Host{}).Error
}

func (h *HostRepo) GetFirewallRecord(opts ...DBOption) (model.Firewall, error) {
var firewall model.Firewall
db := global.DB
for _, opt := range opts {
db = opt(db)
}
err := db.First(&firewall).Error
return firewall, err
}

func (h *HostRepo) ListFirewallRecord() ([]model.Firewall, error) {
var datas []model.Firewall
if err := global.DB.Find(&datas).Error; err != nil {
return datas, nil
}
return datas, nil
}

func (h *HostRepo) SaveFirewallRecord(firewall *model.Firewall) error {
if firewall.ID != 0 {
return global.DB.Save(firewall).Error
}
var data model.Firewall
_ = global.DB.Where("port = ? AND protocol = ? AND address = ? AND strategy = ?", firewall.Port, firewall.Protocol, firewall.Address, firewall.Strategy).First(&data)
if data.ID != 0 {
firewall.ID = data.ID
}
return global.DB.Save(firewall).Error
}

func (h *HostRepo) DeleteFirewallRecordByID(id uint) error {
return global.DB.Where("id = ?", id).Delete(&model.Firewall{}).Error
}

func (h *HostRepo) DeleteFirewallRecord(port, protocol, address, strategy string) error {
return global.DB.Where("port = ? AND protocol = ? AND address = ? AND strategy = ?", port, protocol, address, strategy).Delete(&model.Firewall{}).Error
}
140 changes: 104 additions & 36 deletions backend/app/service/firewall.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ import (
"strings"

"github.com/1Panel-dev/1Panel/backend/app/dto"
"github.com/1Panel-dev/1Panel/backend/app/model"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
"github.com/1Panel-dev/1Panel/backend/utils/common"
"github.com/1Panel-dev/1Panel/backend/utils/firewall"
fireClient "github.com/1Panel-dev/1Panel/backend/utils/firewall/client"
"github.com/jinzhu/copier"
"github.com/pkg/errors"
)

const confPath = "/etc/sysctl.conf"
Expand All @@ -27,6 +29,7 @@ type IFirewallService interface {
OperateAddressRule(req dto.AddrRuleOperate, reload bool) error
UpdatePortRule(req dto.PortRuleUpdate) error
UpdateAddrRule(req dto.AddrRuleUpdate) error
UpdateDescription(req dto.UpdateFirewallDescription) error
BatchOperateRule(req dto.BatchRuleOperate) error
}

Expand Down Expand Up @@ -67,6 +70,7 @@ func (u *FirewallService) SearchWithPage(req dto.RuleSearch) (int64, interface{}
datas []fireClient.FireInfo
backDatas []fireClient.FireInfo
)

client, err := firewall.NewFirewallClient()
if err != nil {
return 0, nil, err
Expand Down Expand Up @@ -110,6 +114,16 @@ func (u *FirewallService) SearchWithPage(req dto.RuleSearch) (int64, interface{}
backDatas = datas[start:end]
}

datasFromDB, _ := hostRepo.ListFirewallRecord()
for i := 0; i < len(backDatas); i++ {
for _, des := range datasFromDB {
if backDatas[i].Port == des.Port && backDatas[i].Protocol == des.Protocol && backDatas[i].Strategy == des.Strategy && backDatas[i].Address == des.Address {
backDatas[i].Description = des.Description
break
}
}
}

if req.Type == "port" {
apps := u.loadPortByApp()
for i := 0; i < len(backDatas); i++ {
Expand All @@ -127,6 +141,7 @@ func (u *FirewallService) SearchWithPage(req dto.RuleSearch) (int64, interface{}
}
}
}
go u.cleanUnUsedData(client)

return int64(total), backDatas, nil
}
Expand Down Expand Up @@ -166,59 +181,55 @@ func (u *FirewallService) OperatePortRule(req dto.PortRuleOperate, reload bool)
if err != nil {
return err
}
protos := strings.Split(req.Protocol, "/")
if client.Name() == "ufw" {
req.Port = strings.ReplaceAll(req.Port, "-", ":")
if req.Operation == "remove" && req.Protocol == "tcp/udp" {
req.Protocol = ""
return u.operatePort(client, req)
if len(req.Address) == 0 {
req.Address = "Anywhere"
}
}
if req.Protocol == "tcp/udp" {
if client.Name() == "firewalld" && strings.Contains(req.Port, ",") {
ports := strings.Split(req.Port, ",")
for _, port := range ports {
if len(port) == 0 {
continue
}
req.Port = port
req.Protocol = "tcp"
if err := u.operatePort(client, req); err != nil {
return err
}
req.Protocol = "udp"
if strings.Contains(req.Port, ",") || strings.Contains(req.Port, "-") {
for _, proto := range protos {
req.Port = strings.ReplaceAll(req.Port, "-", ":")
req.Protocol = proto
if err := u.operatePort(client, req); err != nil {
return err
}
_ = u.addPortRecord(req)
}
} else {
req.Protocol = "tcp"
if err := u.operatePort(client, req); err != nil {
return err
}
req.Protocol = "udp"
return nil
}
if req.Protocol == "tcp/udp" {
req.Protocol = ""
}
if err := u.operatePort(client, req); err != nil {
return err
}
_ = u.addPortRecord(req)
return nil
}

for _, proto := range protos {
if strings.Contains(req.Port, "-") {
req.Protocol = proto
if err := u.operatePort(client, req); err != nil {
return err
}
}
} else {
if strings.Contains(req.Port, ",") {
_ = u.addPortRecord(req)
} else {
ports := strings.Split(req.Port, ",")
for _, port := range ports {
if len(port) == 0 {
continue
}
req.Port = port
req.Protocol = proto
if err := u.operatePort(client, req); err != nil {
return err
}
}
} else {
if err := u.operatePort(client, req); err != nil {
return err
_ = u.addPortRecord(req)
}
}
}
if reload {
return client.Reload()
}
return nil
return client.Reload()
}

func (u *FirewallService) OperateAddressRule(req dto.AddrRuleOperate, reload bool) error {
Expand All @@ -241,6 +252,7 @@ func (u *FirewallService) OperateAddressRule(req dto.AddrRuleOperate, reload boo
if err := client.RichRules(fireInfo, req.Operation); err != nil {
return err
}
_ = u.addAddressRecord(req)
}
if reload {
return client.Reload()
Expand Down Expand Up @@ -276,6 +288,14 @@ func (u *FirewallService) UpdateAddrRule(req dto.AddrRuleUpdate) error {
return client.Reload()
}

func (u *FirewallService) UpdateDescription(req dto.UpdateFirewallDescription) error {
var firewall model.Firewall
if err := copier.Copy(&firewall, &req); err != nil {
return errors.WithMessage(constant.ErrStructTransform, err.Error())
}
return hostRepo.SaveFirewallRecord(&firewall)
}

func (u *FirewallService) BatchOperateRule(req dto.BatchRuleOperate) error {
client, err := firewall.NewFirewallClient()
if err != nil {
Expand Down Expand Up @@ -323,7 +343,7 @@ func (u *FirewallService) operatePort(client firewall.FirewallClient, req dto.Po
}

if client.Name() == "ufw" {
if len(fireInfo.Address) != 0 && fireInfo.Address != "Anywhere" {
if len(fireInfo.Address) != 0 && !strings.EqualFold(fireInfo.Address, "Anywhere") {
return client.RichRules(fireInfo, req.Operation)
}
return client.Port(fireInfo, req.Operation)
Expand Down Expand Up @@ -363,6 +383,29 @@ func (u *FirewallService) loadPortByApp() []portOfApp {
return datas
}

func (u *FirewallService) cleanUnUsedData(client firewall.FirewallClient) {
list, _ := client.ListPort()
addressList, _ := client.ListAddress()
list = append(list, addressList...)
if len(list) == 0 {
return
}
records, _ := hostRepo.ListFirewallRecord()
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 {
_ = hostRepo.DeleteFirewallRecordByID(record.ID)
}
}
func (u *FirewallService) pingStatus() string {
if _, err := os.Stat("/etc/sysctl.conf"); err != nil {
return constant.StatusNone
Expand Down Expand Up @@ -441,3 +484,28 @@ func (u *FirewallService) addPortsBeforeStart(client firewall.FirewallClient) er

return client.Reload()
}

func (u *FirewallService) addPortRecord(req dto.PortRuleOperate) error {
if req.Operation == "remove" {
return hostRepo.DeleteFirewallRecord(req.Port, req.Protocol, req.Address, req.Strategy)
}

return hostRepo.SaveFirewallRecord(&model.Firewall{
Port: req.Port,
Protocol: req.Protocol,
Address: req.Address,
Strategy: req.Strategy,
Description: req.Description,
})
}

func (u *FirewallService) addAddressRecord(req dto.AddrRuleOperate) error {
if req.Operation == "remove" {
return hostRepo.DeleteFirewallRecord("", "", req.Address, req.Strategy)
}
return hostRepo.SaveFirewallRecord(&model.Firewall{
Address: req.Address,
Strategy: req.Strategy,
Description: req.Description,
})
}
1 change: 1 addition & 0 deletions backend/init/migration/migrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ func Init() {
migrations.AddRemoteDB,
migrations.UpdateRedisParam,
migrations.UpdateCronjobWithDb,
migrations.AddTableFirewall,
})
if err := m.Migrate(); err != nil {
global.LOG.Error(err)
Expand Down
10 changes: 10 additions & 0 deletions backend/init/migration/migrations/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -570,3 +570,13 @@ var UpdateCronjobWithDb = &gormigrate.Migration{
return nil
},
}

var AddTableFirewall = &gormigrate.Migration{
ID: "20230814-add-table-firewall",
Migrate: func(tx *gorm.DB) error {
if err := tx.AutoMigrate(&model.Firewall{}); err != nil {
return err
}
return nil
},
}
1 change: 1 addition & 0 deletions backend/router/ro_host.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ func (s *HostRouter) InitHostRouter(Router *gin.RouterGroup) {
hostRouter.POST("/firewall/batch", baseApi.BatchOperateRule)
hostRouter.POST("/firewall/update/port", baseApi.UpdatePortRule)
hostRouter.POST("/firewall/update/addr", baseApi.UpdateAddrRule)
hostRouter.POST("/firewall/update/description", baseApi.UpdateFirewallDescription)

hostRouter.GET("/ssh/conf", baseApi.LoadSSHConf)
hostRouter.POST("/ssh/search", baseApi.GetSSHInfo)
Expand Down
Loading