mirror of
https://github.com/acepanel/panel.git
synced 2026-02-04 06:47:20 +08:00
fix: 罕见情况下防火墙规则错误
This commit is contained in:
@@ -78,6 +78,7 @@ func (s *Service) UpdatePort(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
fw := firewall.NewFirewall()
|
||||
err = fw.Port(firewall.FireInfo{
|
||||
Type: firewall.TypeNormal,
|
||||
PortStart: req.Port,
|
||||
PortEnd: req.Port,
|
||||
Direction: firewall.DirectionIn,
|
||||
|
||||
@@ -156,6 +156,7 @@ func (s *Service) UpdatePort(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
fw := firewall.NewFirewall()
|
||||
err = fw.Port(firewall.FireInfo{
|
||||
Type: firewall.TypeNormal,
|
||||
PortStart: req.Port,
|
||||
PortEnd: req.Port,
|
||||
Direction: firewall.DirectionIn,
|
||||
|
||||
@@ -205,6 +205,7 @@ func (r *settingRepo) UpdatePanelSetting(ctx context.Context, setting *request.P
|
||||
// 放行端口
|
||||
fw := firewall.NewFirewall()
|
||||
err = fw.Port(firewall.FireInfo{
|
||||
Type: firewall.TypeNormal,
|
||||
PortStart: uint(config.HTTP.Port),
|
||||
PortEnd: uint(config.HTTP.Port),
|
||||
Direction: firewall.DirectionIn,
|
||||
|
||||
@@ -5,6 +5,7 @@ type FirewallStatus struct {
|
||||
}
|
||||
|
||||
type FirewallRule struct {
|
||||
Type string `json:"type"`
|
||||
Family string `json:"family" validate:"required,oneof=ipv4 ipv6"`
|
||||
PortStart uint `json:"port_start" validate:"required,gte=1,lte=65535"`
|
||||
PortEnd uint `json:"port_end" validate:"required,gte=1,lte=65535"`
|
||||
|
||||
@@ -86,6 +86,7 @@ func (s *FirewallService) GetRules(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
filledRules = append(filledRules, map[string]any{
|
||||
"type": rule.Type,
|
||||
"family": rule.Family,
|
||||
"port_start": rule.PortStart,
|
||||
"port_end": rule.PortEnd,
|
||||
@@ -113,7 +114,7 @@ func (s *FirewallService) CreateRule(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
if err = s.firewall.Port(firewall.FireInfo{
|
||||
Family: req.Family, PortStart: req.PortStart, PortEnd: req.PortEnd, Protocol: firewall.Protocol(req.Protocol), Address: req.Address, Strategy: firewall.Strategy(req.Strategy), Direction: firewall.Direction(req.Direction),
|
||||
Type: firewall.Type(req.Type), Family: req.Family, PortStart: req.PortStart, PortEnd: req.PortEnd, Protocol: firewall.Protocol(req.Protocol), Address: req.Address, Strategy: firewall.Strategy(req.Strategy), Direction: firewall.Direction(req.Direction),
|
||||
}, firewall.OperationAdd); err != nil {
|
||||
Error(w, http.StatusInternalServerError, "%v", err)
|
||||
return
|
||||
@@ -130,7 +131,7 @@ func (s *FirewallService) DeleteRule(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
if err = s.firewall.Port(firewall.FireInfo{
|
||||
Family: req.Family, PortStart: req.PortStart, PortEnd: req.PortEnd, Protocol: firewall.Protocol(req.Protocol), Address: req.Address, Strategy: firewall.Strategy(req.Strategy), Direction: firewall.Direction(req.Direction),
|
||||
Type: firewall.Type(req.Type), Family: req.Family, PortStart: req.PortStart, PortEnd: req.PortEnd, Protocol: firewall.Protocol(req.Protocol), Address: req.Address, Strategy: firewall.Strategy(req.Strategy), Direction: firewall.Direction(req.Direction),
|
||||
}, firewall.OperationRemove); err != nil {
|
||||
Error(w, http.StatusInternalServerError, "%v", err)
|
||||
return
|
||||
|
||||
@@ -7,6 +7,13 @@ var (
|
||||
OperationRemove Operation = "remove" // 移除
|
||||
)
|
||||
|
||||
type Type string
|
||||
|
||||
var (
|
||||
TypeRich Type = "rich" // rich
|
||||
TypeNormal Type = "normal" // normal
|
||||
)
|
||||
|
||||
type Protocol string
|
||||
|
||||
var (
|
||||
@@ -31,6 +38,7 @@ var (
|
||||
)
|
||||
|
||||
type FireInfo struct {
|
||||
Type Type `json:"type"` // rich or normal
|
||||
Family string `json:"family"` // ipv4 ipv6
|
||||
Address string `json:"address"` // 源地址或目标地址
|
||||
PortStart uint `json:"port_start"` // 1-65535
|
||||
|
||||
@@ -54,6 +54,7 @@ func (r *Firewall) ListRule() ([]FireInfo, error) {
|
||||
continue
|
||||
}
|
||||
var item FireInfo
|
||||
item.Type = TypeNormal
|
||||
if strings.Contains(port, "/") {
|
||||
ruleItem := strings.Split(port, "/")
|
||||
portItem := strings.Split(ruleItem[0], "-")
|
||||
@@ -82,6 +83,32 @@ func (r *Firewall) ListRule() ([]FireInfo, error) {
|
||||
}()
|
||||
|
||||
wg.Wait()
|
||||
|
||||
slices.SortFunc(data, func(a FireInfo, b FireInfo) int {
|
||||
if a.PortStart != b.PortStart {
|
||||
return int(a.PortStart - b.PortStart)
|
||||
}
|
||||
if a.PortEnd != b.PortEnd {
|
||||
return int(a.PortEnd - b.PortEnd)
|
||||
}
|
||||
if a.Protocol != b.Protocol {
|
||||
return strings.Compare(string(a.Protocol), string(b.Protocol))
|
||||
}
|
||||
if a.Family != b.Family {
|
||||
return strings.Compare(a.Family, b.Family)
|
||||
}
|
||||
if a.Strategy != b.Strategy {
|
||||
return strings.Compare(string(a.Strategy), string(b.Strategy))
|
||||
}
|
||||
if a.Direction != b.Direction {
|
||||
return strings.Compare(string(a.Direction), string(b.Direction))
|
||||
}
|
||||
if a.Type != b.Type {
|
||||
return strings.Compare(string(a.Type), string(b.Type))
|
||||
}
|
||||
return 0
|
||||
})
|
||||
|
||||
return data, nil
|
||||
}
|
||||
|
||||
@@ -113,6 +140,22 @@ func (r *Firewall) ListForward() ([]FireForwardInfo, error) {
|
||||
}
|
||||
}
|
||||
|
||||
slices.SortFunc(data, func(a FireForwardInfo, b FireForwardInfo) int {
|
||||
if a.Port != b.Port {
|
||||
return int(a.Port - b.Port)
|
||||
}
|
||||
if a.TargetPort != b.TargetPort {
|
||||
return int(a.TargetPort - b.TargetPort)
|
||||
}
|
||||
if a.Protocol != b.Protocol {
|
||||
return strings.Compare(string(a.Protocol), string(b.Protocol))
|
||||
}
|
||||
if a.TargetIP != b.TargetIP {
|
||||
return strings.Compare(a.TargetIP, b.TargetIP)
|
||||
}
|
||||
return 0
|
||||
})
|
||||
|
||||
return data, nil
|
||||
}
|
||||
|
||||
@@ -144,7 +187,7 @@ func (r *Firewall) Port(rule FireInfo, operation Operation) error {
|
||||
return fmt.Errorf("invalid port range: %d-%d", rule.PortStart, rule.PortEnd)
|
||||
}
|
||||
// 不支持的切换使用rich rules
|
||||
if (rule.Family != "" && rule.Family != "ipv4") || rule.Direction != "in" || rule.Address != "" || rule.Strategy != "accept" {
|
||||
if (rule.Family != "" && rule.Family != "ipv4") || rule.Direction != "in" || rule.Address != "" || rule.Strategy != "accept" || rule.Type == TypeRich {
|
||||
return r.RichRules(rule, operation)
|
||||
}
|
||||
|
||||
@@ -245,6 +288,7 @@ func (r *Firewall) parseRichRule(line string) (FireInfo, error) {
|
||||
}
|
||||
|
||||
fireInfo := FireInfo{
|
||||
Type: TypeRich,
|
||||
Family: match[1],
|
||||
Address: match[3],
|
||||
Protocol: Protocol(match[5]),
|
||||
|
||||
@@ -286,7 +286,7 @@ onMounted(() => {
|
||||
<n-data-table
|
||||
striped
|
||||
remote
|
||||
:scroll-x="1200"
|
||||
:scroll-x="1400"
|
||||
:loading="false"
|
||||
:columns="columns"
|
||||
:data="data"
|
||||
|
||||
@@ -28,8 +28,8 @@ const webglAddon = new WebglAddon()
|
||||
|
||||
const current = ref(0)
|
||||
const collapsed = ref(true)
|
||||
const createModal = ref(false)
|
||||
const updateModal = ref(false)
|
||||
const create = ref(false)
|
||||
const update = ref(false)
|
||||
const updateId = ref(0)
|
||||
|
||||
const list = ref<MenuOption[]>([])
|
||||
@@ -60,7 +60,7 @@ const fetchData = async () => {
|
||||
type: 'primary',
|
||||
size: 'small',
|
||||
onClick: () => {
|
||||
updateModal.value = true
|
||||
update.value = true
|
||||
updateId.value = item.id
|
||||
}
|
||||
},
|
||||
@@ -114,7 +114,7 @@ const handleDelete = async (id: number) => {
|
||||
term.value.dispose()
|
||||
}
|
||||
if (list.value.length === 0) {
|
||||
createModal.value = true
|
||||
create.value = true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -172,10 +172,10 @@ const closeSession = () => {
|
||||
try {
|
||||
term.value.dispose()
|
||||
sshWs?.close()
|
||||
terminal.value!.innerHTML = ''
|
||||
} catch {
|
||||
/* empty */
|
||||
}
|
||||
terminal.value!.innerHTML = ''
|
||||
}
|
||||
|
||||
const onResize = () => {
|
||||
@@ -206,12 +206,12 @@ const onTermWheel = (event: WheelEvent) => {
|
||||
}
|
||||
}
|
||||
|
||||
watch(createModal, () => {
|
||||
if (!createModal.value) fetchData()
|
||||
watch(create, () => {
|
||||
if (!create.value) fetchData()
|
||||
})
|
||||
|
||||
watch(updateModal, () => {
|
||||
if (!updateModal.value) {
|
||||
watch(update, () => {
|
||||
if (!update.value) {
|
||||
fetchData()
|
||||
updateId.value = 0
|
||||
}
|
||||
@@ -233,7 +233,7 @@ onUnmounted(() => {
|
||||
<common-page show-footer>
|
||||
<template #action>
|
||||
<div flex items-center>
|
||||
<n-button type="primary" @click="createModal = true">
|
||||
<n-button type="primary" @click="create = true">
|
||||
<TheIcon :size="18" icon="material-symbols:add" />
|
||||
创建主机
|
||||
</n-button>
|
||||
@@ -265,8 +265,8 @@ onUnmounted(() => {
|
||||
</n-layout-sider>
|
||||
</n-layout>
|
||||
</common-page>
|
||||
<CreateModal v-model:show="createModal" />
|
||||
<UpdateModal v-if="updateModal" v-model:show="updateModal" v-model:id="updateId" />
|
||||
<create-modal v-if="create" v-model:show="create" />
|
||||
<update-modal v-if="update" v-model:show="update" v-model:id="updateId" />
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
@@ -8,13 +8,14 @@ import { NButton, NDataTable, NFlex, NInput, NPopconfirm, NSwitch, NTag } from '
|
||||
import cron from '@/api/panel/cron'
|
||||
import file from '@/api/panel/file'
|
||||
import { formatDateTime, renderIcon } from '@/utils'
|
||||
import CreateModal from '@/views/task/CreateModal.vue'
|
||||
import type { CronTask } from '@/views/task/types'
|
||||
import { CronNaive } from '@vue-js-cron/naive-ui'
|
||||
|
||||
const logPath = ref('')
|
||||
const logModal = ref(false)
|
||||
const editModal = ref(false)
|
||||
const createModal = ref(false)
|
||||
const create = ref(false)
|
||||
|
||||
const columns: any = [
|
||||
{ type: 'selection', fixed: 'left' },
|
||||
@@ -231,7 +232,7 @@ const saveTaskEdit = async () => {
|
||||
})
|
||||
}
|
||||
|
||||
watch(createModal, () => {
|
||||
watch(create, () => {
|
||||
onPageChange(pagination.page)
|
||||
})
|
||||
|
||||
@@ -243,7 +244,7 @@ onMounted(() => {
|
||||
<template>
|
||||
<n-flex vertical>
|
||||
<n-card flex-1 rounded-10>
|
||||
<n-button type="primary" @click="createModal = true">创建计划任务</n-button>
|
||||
<n-button type="primary" @click="create = true">创建计划任务</n-button>
|
||||
</n-card>
|
||||
<n-card flex-1 rounded-10>
|
||||
<n-data-table
|
||||
@@ -261,7 +262,6 @@ onMounted(() => {
|
||||
/>
|
||||
</n-card>
|
||||
</n-flex>
|
||||
<create-modal v-model:show="createModal" />
|
||||
<realtime-log-modal v-model:show="logModal" :path="logPath" />
|
||||
<n-modal
|
||||
v-model:show="editModal"
|
||||
@@ -294,4 +294,5 @@ onMounted(() => {
|
||||
}"
|
||||
/>
|
||||
</n-modal>
|
||||
<create-modal v-model:show="create" />
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user