1
0
mirror of https://github.com/1Panel-dev/1Panel.git synced 2025-03-13 17:24:44 +08:00

feat: 防火墙范围端口规则显示占用详情 (#2369)

Refs #729 

![image](https://github.com/1Panel-dev/1Panel/assets/73214554/0818e6b8-af81-4368-a7f9-5a55363b5c11)
This commit is contained in:
ssongliu 2023-09-21 18:02:21 +08:00 committed by GitHub
parent 975ff06d69
commit f4094e03b8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 95 additions and 34 deletions

View File

@ -46,9 +46,6 @@ func (u *FirewallService) LoadBaseInfo() (dto.FirewallBaseInfo, error) {
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()
@ -111,14 +108,19 @@ func (u *FirewallService) SearchWithPage(req dto.RuleSearch) (int64, interface{}
}
}
if req.Type == "port" {
apps := u.loadPortByApp()
for i := 0; i < len(datas); i++ {
datas[i].UsedStatus = checkPortUsed(datas[i].Port, datas[i].Protocol, apps)
}
}
var datasFilterStatus []fireClient.FireInfo
if len(req.Status) != 0 {
for _, data := range datas {
portItem, _ := strconv.Atoi(data.Port)
if req.Status == "free" && !common.ScanPortWithProto(portItem, data.Protocol) {
if req.Status == "free" && len(data.UsedStatus) == 0 {
datasFilterStatus = append(datasFilterStatus, data)
}
if req.Status == "used" && common.ScanPortWithProto(portItem, data.Protocol) {
if req.Status == "used" && len(data.UsedStatus) != 0 {
datasFilterStatus = append(datasFilterStatus, data)
}
}
@ -167,23 +169,6 @@ func (u *FirewallService) SearchWithPage(req dto.RuleSearch) (int64, interface{}
}
}
if req.Type == "port" {
apps := u.loadPortByApp()
for i := 0; i < len(backDatas); i++ {
port, _ := strconv.Atoi(backDatas[i].Port)
backDatas[i].IsUsed = common.ScanPort(port)
if backDatas[i].Protocol == "udp" {
backDatas[i].IsUsed = common.ScanUDPPort(port)
continue
}
for _, app := range apps {
if app.HttpPort == backDatas[i].Port || app.HttpsPort == backDatas[i].Port {
backDatas[i].APPName = app.AppName
break
}
}
}
}
go u.cleanUnUsedData(client)
return int64(total), backDatas, nil
@ -626,3 +611,50 @@ func listIpRules(strategy string) ([]string, error) {
}
return rules, nil
}
func checkPortUsed(ports, proto string, apps []portOfApp) string {
if strings.Contains(ports, "-") {
port1, err := strconv.Atoi(strings.Split(ports, "-")[0])
if err != nil {
global.LOG.Errorf(" convert string %s to int failed, err: %v", strings.Split(ports, "-")[0], err)
return ""
}
port2, err := strconv.Atoi(strings.Split(ports, "-")[1])
if err != nil {
global.LOG.Errorf(" convert string %s to int failed, err: %v", strings.Split(ports, "-")[1], err)
return ""
}
var usedPorts []string
for i := port1; i <= port2; i++ {
portItem := fmt.Sprintf("%v", i)
isUsedByApp := false
for _, app := range apps {
if app.HttpPort == portItem || app.HttpsPort == portItem {
isUsedByApp = true
usedPorts = append(usedPorts, fmt.Sprintf("%s (%s)", portItem, app.AppName))
break
}
}
if !isUsedByApp && common.ScanPortWithProto(i, proto) {
usedPorts = append(usedPorts, fmt.Sprintf("%v", i))
}
}
return strings.Join(usedPorts, ",")
}
for _, app := range apps {
if app.HttpPort == ports || app.HttpsPort == ports {
return fmt.Sprintf("%s (%s)", ports, app.AppName)
}
}
port, err := strconv.Atoi(ports)
if err != nil {
global.LOG.Errorf(" convert string %v to int failed, err: %v", port, err)
return ""
}
if common.ScanPortWithProto(port, proto) {
return ports
}
return ""
}

View File

@ -8,7 +8,7 @@ type FireInfo struct {
Strategy string `json:"strategy"` // accept drop
APPName string `json:"appName"`
IsUsed bool `json:"isUsed"`
UsedStatus string `json:"usedStatus"`
Description string `json:"description"`
}

View File

@ -371,4 +371,9 @@ html {
background: none;
border: none;
}
}
.limit-height-popover {
max-height: 300px;
overflow: auto;
}

View File

@ -83,18 +83,31 @@
:data="data"
>
<el-table-column type="selection" fix />
<el-table-column :label="$t('commons.table.protocol')" :min-width="90" prop="protocol" />
<el-table-column :label="$t('commons.table.port')" :min-width="120" prop="port" />
<el-table-column :label="$t('commons.table.protocol')" :min-width="70" prop="protocol" />
<el-table-column :label="$t('commons.table.port')" :min-width="70" prop="port" />
<el-table-column :label="$t('commons.table.status')" :min-width="120">
<template #default="{ row }">
<el-tag type="info" v-if="row.isUsed">
{{
row.appName
? $t('firewall.used') + ' ( ' + row.appName + ' )'
: $t('firewall.used')
}}
</el-tag>
<el-tag type="success" v-else>{{ $t('firewall.unUsed') }}</el-tag>
<div v-if="row.port.indexOf('-') !== -1 && row.usedStatus">
<el-tag type="info" class="mt-1">
{{ $t('firewall.used') + ' * ' + row.usedPorts.length }}
</el-tag>
<el-popover placement="right" popper-class="limit-height-popover" :width="250">
<template #default>
<ul v-for="(item, index) in row.usedPorts" :key="index">
<li>{{ item }}</li>
</ul>
</template>
<template #reference>
<svg-icon iconName="p-xiangqing" class="svg-icon"></svg-icon>
</template>
</el-popover>
</div>
<div v-else>
<el-tag type="info" v-if="row.usedStatus">
{{ $t('firewall.used') }}
</el-tag>
<el-tag type="success" v-else>{{ $t('firewall.unUsed') }}</el-tag>
</div>
</template>
</el-table-column>
<el-table-column :min-width="80" :label="$t('firewall.strategy')" prop="strategy">
@ -220,6 +233,9 @@ const search = async () => {
.then((res) => {
loading.value = false;
data.value = res.data.items || [];
for (const item of data.value) {
item.usedPorts = item.usedStatus ? item.usedStatus.split(',') : [];
}
paginationConfig.total = res.data.total;
})
.catch(() => {
@ -361,3 +377,11 @@ onMounted(() => {
}
});
</script>
<style lang="scss" scoped>
.svg-icon {
font-size: 8px;
margin-bottom: -4px;
cursor: pointer;
}
</style>