mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2026-10-19 00:00:46 +00:00
fix(firewall): support legacy ip RA checks and link documentation (#14083)
This commit is contained in:
@@ -2,7 +2,6 @@ package forwarding
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
@@ -174,14 +173,19 @@ func LoadDockerIPv4BridgePorts() (map[string]bool, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
output, err := cmd.NewCommandMgr(cmd.WithContext(ctx), cmd.WithTimeout(5*time.Second)).RunWithOptionalSudoAndStdout("ip", "-details", "-json", "link", "show")
|
||||
command := cmd.NewCommandMgr(cmd.WithContext(ctx), cmd.WithTimeout(5*time.Second))
|
||||
bridges, err := command.RunWithOptionalSudoAndStdout("ip", "-o", "link", "show", "type", "bridge")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dockerIPv4BridgePorts(networks, output)
|
||||
ports, err := command.RunWithOptionalSudoAndStdout("ip", "-o", "link", "show", "type", "veth")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dockerIPv4BridgePorts(networks, bridges, ports)
|
||||
}
|
||||
|
||||
func dockerIPv4BridgePorts(networks []network.Summary, linkJSON string) (map[string]bool, error) {
|
||||
func dockerIPv4BridgePorts(networks []network.Summary, bridgeOutput, portOutput string) (map[string]bool, error) {
|
||||
bridges := make(map[string]bool)
|
||||
for _, item := range networks {
|
||||
if item.Driver != "bridge" || item.EnableIPv6 || item.ConfigOnly {
|
||||
@@ -199,26 +203,36 @@ func dockerIPv4BridgePorts(networks []network.Summary, linkJSON string) (map[str
|
||||
bridges[name] = true
|
||||
}
|
||||
}
|
||||
var links []struct {
|
||||
Name string `json:"ifname"`
|
||||
Master string `json:"master"`
|
||||
LinkInfo struct {
|
||||
Kind string `json:"info_kind"`
|
||||
} `json:"linkinfo"`
|
||||
}
|
||||
if err := json.Unmarshal([]byte(linkJSON), &links); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
confirmedBridges := make(map[string]bool)
|
||||
for _, link := range links {
|
||||
if link.LinkInfo.Kind == "bridge" && bridges[link.Name] {
|
||||
confirmedBridges[link.Name] = true
|
||||
}
|
||||
}
|
||||
ports := make(map[string]bool)
|
||||
for _, link := range links {
|
||||
if link.LinkInfo.Kind == "veth" && confirmedBridges[link.Master] {
|
||||
ports[link.Name] = true
|
||||
for index, output := range []string{bridgeOutput, portOutput} {
|
||||
for _, line := range strings.Split(output, "\n") {
|
||||
header, _, _ := strings.Cut(line, "\\")
|
||||
fields := strings.Fields(header)
|
||||
if len(fields) == 0 {
|
||||
continue
|
||||
}
|
||||
if len(fields) < 3 || !strings.HasSuffix(fields[0], ":") || !strings.HasSuffix(fields[1], ":") {
|
||||
return nil, fmt.Errorf("invalid network link entry: %q", line)
|
||||
}
|
||||
if _, err := strconv.Atoi(strings.TrimSuffix(fields[0], ":")); err != nil {
|
||||
return nil, fmt.Errorf("invalid network link entry: %q", line)
|
||||
}
|
||||
name, _, _ := strings.Cut(strings.TrimSuffix(fields[1], ":"), "@")
|
||||
if index == 0 {
|
||||
if bridges[name] {
|
||||
confirmedBridges[name] = true
|
||||
}
|
||||
continue
|
||||
}
|
||||
for i := 3; i+1 < len(fields); i++ {
|
||||
if fields[i] == "master" {
|
||||
if confirmedBridges[fields[i+1]] {
|
||||
ports[name] = true
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ports, nil
|
||||
|
||||
@@ -15,7 +15,19 @@
|
||||
<div v-for="issue in issues" :key="issue.family" class="family-row">
|
||||
<div class="family-row__body">
|
||||
<el-tag size="small" type="info" effect="plain">{{ issue.family === 'ipv6' ? 'IPv6' : 'IPv4' }}</el-tag>
|
||||
<p>{{ issue.message }}</p>
|
||||
<p>
|
||||
{{ issue.message }}
|
||||
<el-link
|
||||
v-if="issue.helpUrl"
|
||||
class="ml-1 text-xs"
|
||||
type="primary"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
:href="issue.helpUrl"
|
||||
>
|
||||
{{ $t('commons.button.helpDoc') }}
|
||||
</el-link>
|
||||
</p>
|
||||
</div>
|
||||
<el-button
|
||||
v-if="issue.action"
|
||||
@@ -55,6 +67,7 @@ import i18n from '@/lang';
|
||||
interface FamilyIssue {
|
||||
family: 'ipv4' | 'ipv6';
|
||||
message: string;
|
||||
helpUrl?: string;
|
||||
action?: 'initialize' | 'repair' | 'bind';
|
||||
}
|
||||
const props = defineProps<{
|
||||
|
||||
@@ -182,10 +182,12 @@ import TaskLog from '@/components/log/task/index.vue';
|
||||
import FamilyIssues from '@/views/host/firewall/components/family-issues.vue';
|
||||
import RuleInitialize from '@/views/host/firewall/components/rule-initialize.vue';
|
||||
import { newUUID } from '@/utils/id';
|
||||
import { useGlobalStore } from '@/composables/useGlobalStore';
|
||||
|
||||
const props = defineProps({
|
||||
currentTab: String,
|
||||
});
|
||||
const { docsUrl } = useGlobalStore();
|
||||
|
||||
const goToFirewallSetting = () => routerToName('FirewallSetting');
|
||||
const goToScriptLibrary = () => routerToNameWithQuery('Library', { uncached: 'true' });
|
||||
@@ -272,6 +274,10 @@ const familyActions = computed(() =>
|
||||
return {
|
||||
family: issue.family === 'IPv6' ? ('ipv6' as const) : ('ipv4' as const),
|
||||
message: familyIssueText(issue),
|
||||
helpUrl:
|
||||
issue.available && issue.reason === 'ipv6_ra_required'
|
||||
? `${docsUrl.value}/user_manual/hosts/firewall`
|
||||
: undefined,
|
||||
action,
|
||||
};
|
||||
}),
|
||||
|
||||
Reference in New Issue
Block a user