fix(firewall): hide inactive Docker ports (#13716)

This commit is contained in:
ssongliu
2026-09-04 21:43:05 +08:00
committed by GitHub
parent 918c441f88
commit a71aea8aec
20 changed files with 181 additions and 30 deletions
+1
View File
@@ -165,6 +165,7 @@ type DockerPortGuardEndpoint struct {
Protocol string `json:"protocol"`
ContainerID string `json:"containerID"`
ContainerName string `json:"containerName"`
ContainerState string `json:"containerState,omitempty"`
ContainerPort uint16 `json:"containerPort"`
Compose string `json:"compose,omitempty"`
Application string `json:"application,omitempty"`
+6 -6
View File
@@ -125,7 +125,7 @@ func (s *DockerPortGuardService) LoadPublishedPorts(ctx context.Context) ([]dto.
}
defer cli.Close()
endpoints, err := discoverDockerEndpoints(ctx, cli)
endpoints, err := discoverDockerEndpoints(ctx, cli, false)
if err != nil {
return nil, err
}
@@ -163,7 +163,7 @@ func (s *DockerPortGuardService) LoadOverview(ctx context.Context) (dto.DockerPo
if reconcileErr := lastDockerPortGuardReconcileError(); reconcileErr != nil {
markDockerGuardReconcileFailure(&base, reconcileErr)
}
endpoints, err := discoverDockerEndpoints(ctx, cli)
endpoints, err := discoverDockerEndpoints(ctx, cli, true)
if err != nil {
return dto.DockerPortGuardList{}, err
}
@@ -378,7 +378,7 @@ func (s *DockerPortGuardService) rejectHostInputDockerGuardEndpoints(
if err != nil {
return nil
}
endpoints, err := discoverDockerEndpoints(ctx, cli)
endpoints, err := discoverDockerEndpoints(ctx, cli, true)
if err != nil {
return nil
}
@@ -739,8 +739,8 @@ func dockerFirewallVersion(backend string) string {
return version
}
func discoverDockerEndpoints(ctx context.Context, cli *client.Client) ([]dto.DockerPortGuardEndpoint, error) {
containers, err := cli.ContainerList(ctx, containertypes.ListOptions{All: true})
func discoverDockerEndpoints(ctx context.Context, cli *client.Client, all bool) ([]dto.DockerPortGuardEndpoint, error) {
containers, err := cli.ContainerList(ctx, containertypes.ListOptions{All: all})
if err != nil {
return nil, err
}
@@ -763,7 +763,7 @@ func discoverDockerEndpoints(ctx context.Context, cli *client.Client) ([]dto.Doc
} else if hostIP == "" {
hostIP = "0.0.0.0"
}
endpoints = append(endpoints, dto.DockerPortGuardEndpoint{Family: family, HostIP: hostIP, HostPort: port.PublicPort, Protocol: port.Type, ContainerID: item.ID, ContainerName: name, ContainerPort: port.PrivatePort, Compose: compose, Application: application, Sources: []string{}})
endpoints = append(endpoints, dto.DockerPortGuardEndpoint{Family: family, HostIP: hostIP, HostPort: port.PublicPort, Protocol: port.Type, ContainerID: item.ID, ContainerName: name, ContainerState: item.State, ContainerPort: port.PrivatePort, Compose: compose, Application: application, Sources: []string{}})
}
}
return endpoints, nil
@@ -235,7 +235,10 @@ func (a *Adapter) failedCommandApplied(ctx context.Context, plan filter.NativeRu
case filter.ChangeCreate:
return markerCount > 0
case filter.ChangeAdopt:
return plan.Previous == nil || !containsObservedRule(snapshot, *plan.Previous)
if commandIndex == 0 {
return plan.Previous == nil || !containsObservedRule(snapshot, *plan.Previous)
}
return markerCount > 0
case filter.ChangeUpdate:
if commandIndex == 0 {
return markerCount == 0
@@ -342,14 +345,20 @@ func compileChange(snapshot filter.Snapshot, change filter.DesiredChange) (filte
return filter.NativeRulePlan{}, targetErr
}
position = *target.Locator.Position
appendAtEnd := position == maximumObservedPosition(snapshot)
restoreAtEnd := change.RestoreAtEnd || appendAtEnd
plan.Previous = &target
plan.Expected = observedForRule(normalized, marker, position)
if appendAtEnd {
plan.Expected.Locator.NativeID = ""
plan.Expected.Locator.Position = nil
}
plan.Commands = []filter.NativeCommand{
deletePositionCommand(position),
insertCommand(position, normalized, marker),
positionedCommand(position, normalized, marker, appendAtEnd),
}
plan.RollbackCommands = []filter.NativeCommand{
insertCommand(position, target.Rule, observedComment(target)),
positionedCommand(position, target.Rule, observedComment(target), restoreAtEnd),
deleteRuleCommand(normalized, marker),
}
case filter.ChangeUpdate:
+1
View File
@@ -395,6 +395,7 @@ export namespace Firewall {
protocol: 'tcp' | 'udp';
containerID?: string;
containerName?: string;
containerState?: 'created' | 'running' | 'paused' | 'restarting' | 'removing' | 'exited' | 'dead';
containerPort?: number;
compose?: string;
application?: string;
+10
View File
@@ -4194,6 +4194,16 @@ const message = {
dockerTrafficPathMixed: 'The selected ports use different access paths. Configure them separately.',
dockerTrafficPathUnknown:
'The access path for this port could not be determined. Check the Docker network configuration and try again.',
dockerTrafficPathReason: {
nat_inspect_failed:
'Docker NAT rules could not be read. Check the firewall commands and permissions, then refresh.',
proxy_inspect_failed:
'docker-proxy processes could not be inspected. Check access to system process information, then refresh.',
nat_chain_unreachable:
'A Docker forwarding rule exists for this port, but the NAT ingress chain is inactive. Check the Docker firewall rules or restart Docker, then refresh.',
no_matching_path:
'No active Docker forwarding rule or proxy process was found for this port. Start or restart the container, then refresh. If the issue persists, check the Docker network configuration.',
},
dockerTrafficPathPending: 'Access path pending',
dockerInputPolicyNotEffective:
'The host receives this port directly, so the existing container port protection rule does not apply. Configure it in the host firewall instead.',
+10
View File
@@ -4242,6 +4242,16 @@ const message = {
dockerTrafficPathMixed: 'Los puertos seleccionados usan rutas de acceso diferentes. Configúralos por separado.',
dockerTrafficPathUnknown:
'No se pudo determinar la ruta de acceso de este puerto. Comprueba la red de Docker e inténtalo de nuevo.',
dockerTrafficPathReason: {
nat_inspect_failed:
'No se pudieron leer las reglas NAT de Docker. Comprueba los comandos y permisos del firewall y actualiza la página.',
proxy_inspect_failed:
'No se pudieron inspeccionar los procesos docker-proxy. Comprueba el acceso a la información de procesos y actualiza la página.',
nat_chain_unreachable:
'Existe una regla de reenvío de Docker para este puerto, pero la cadena de entrada NAT no está activa. Comprueba las reglas del firewall de Docker o reinicia Docker y actualiza la página.',
no_matching_path:
'No se encontró una regla de reenvío de Docker activa ni un proceso proxy para este puerto. Inicia o reinicia el contenedor y actualiza la página. Si continúa, comprueba la red de Docker.',
},
dockerTrafficPathPending: 'Ruta de acceso pendiente',
dockerInputPolicyNotEffective:
'El host recibe este puerto directamente, por lo que la regla de protección del puerto del contenedor no se aplica. Configúralo en el firewall del host.',
+10
View File
@@ -4152,6 +4152,16 @@ const message = {
'پورت‌های انتخاب‌شده از مسیرهای دسترسی متفاوت استفاده می‌کنند. آن‌ها را جداگانه تنظیم کنید.',
dockerTrafficPathUnknown:
'مسیر دسترسی این پورت قابل تشخیص نیست. تنظیمات شبکه Docker را بررسی کرده و دوباره تلاش کنید.',
dockerTrafficPathReason: {
nat_inspect_failed:
'خواندن قوانین NAT داکر ممکن نبود. فرمان‌ها و مجوزهای فایروال را بررسی و سپس صفحه را تازه‌سازی کنید.',
proxy_inspect_failed:
'بررسی پردازش‌های docker-proxy ممکن نبود. دسترسی به اطلاعات پردازش‌های سیستم را بررسی و سپس صفحه را تازه‌سازی کنید.',
nat_chain_unreachable:
'قانون هدایت داکر برای این پورت وجود دارد، اما زنجیره ورودی NAT فعال نیست. قوانین فایروال داکر را بررسی یا داکر را راه‌اندازی مجدد کرده و صفحه را تازه‌سازی کنید.',
no_matching_path:
'برای این پورت قانون هدایت فعال داکر یا پردازش پراکسی یافت نشد. کانتینر را راه‌اندازی یا مجدداً راه‌اندازی کرده و صفحه را تازه‌سازی کنید. اگر مشکل ادامه داشت، شبکه داکر را بررسی کنید.',
},
dockerTrafficPathPending: 'مسیر دسترسی نامشخص',
dockerInputPolicyNotEffective:
'این پورت مستقیماً توسط میزبان دریافت می‌شود، بنابراین قانون فعلی محافظت پورت کانتینر اعمال نمی‌شود. آن را در فایروال میزبان تنظیم کنید.',
+10
View File
@@ -4179,6 +4179,16 @@ const message = {
dockerTrafficPathMixed: '選択したポートは異なるアクセス経路を使用しています個別に設定してください',
dockerTrafficPathUnknown:
'このポートのアクセス経路を確認できませんDocker ネットワーク設定を確認して再試行してください',
dockerTrafficPathReason: {
nat_inspect_failed:
'Docker NAT ルールを読み取れませんファイアウォールコマンドと実行権限を確認してから更新してください',
proxy_inspect_failed:
'docker-proxy プロセスを確認できませんシステムのプロセス情報を読み取れることを確認してから更新してください',
nat_chain_unreachable:
'このポートの Docker 転送ルールは見つかりましたがNAT 入口チェーンが有効ではありませんDocker のファイアウォールルールを確認するか Docker を再起動してから更新してください',
no_matching_path:
'このポートに有効な Docker 転送ルールまたはプロキシプロセスが見つかりません対象のコンテナを起動または再起動してから更新してください解決しない場合は Docker ネットワーク設定を確認してください',
},
dockerTrafficPathPending: 'アクセス経路を確認中',
dockerInputPolicyNotEffective:
'このポートはホストが直接受信するため既存のコンテナポート保護ルールは適用されませんホストファイアウォールで設定してください',
+10
View File
@@ -4102,6 +4102,16 @@ const message = {
dockerTrafficPathMixed: '선택한 포트가 서로 다른 접근 경로를 사용합니다. 각각 설정하세요.',
dockerTrafficPathUnknown:
' 포트의 접근 경로를 확인할 없습니다. Docker 네트워크 설정을 확인한 다시 시도하세요.',
dockerTrafficPathReason: {
nat_inspect_failed:
'Docker NAT 규칙을 읽을 없습니다. 방화벽 명령과 실행 권한을 확인한 새로 고침하세요.',
proxy_inspect_failed:
'docker-proxy 프로세스를 확인할 없습니다. 시스템 프로세스 정보에 대한 접근 권한을 확인한 새로 고침하세요.',
nat_chain_unreachable:
' 포트의 Docker 전달 규칙은 있지만 NAT 진입 체인이 활성화되지 않았습니다. Docker 방화벽 규칙을 확인하거나 Docker를 다시 시작한 새로 고침하세요.',
no_matching_path:
' 포트에 활성 Docker 전달 규칙이나 프록시 프로세스가 없습니다. 해당 컨테이너를 시작하거나 다시 시작한 새로 고침하세요. 문제가 계속되면 Docker 네트워크 설정을 확인하세요.',
},
dockerTrafficPathPending: '접근 경로 확인 대기',
dockerInputPolicyNotEffective:
' 포트는 호스트가 직접 수신하므로 기존 컨테이너 포트 보호 규칙이 적용되지 않습니다. 호스트 방화벽에서 설정하세요.',
+9
View File
@@ -4069,6 +4069,15 @@ const message = {
'ຕັ້ງຄ່າຂໍ້ຈຳກັດການເຂົ້າເຖິງສຳລັບພອດທີ່ Docker ເຜີຍແຜ່ໃນໂຮສ. ພອດທີ່ບໍ່ໄດ້ປ້ອງກັນຈະໃຊ້ຮູບແບບເຂົ້າເຖິງເລີ່ມຕົ້ນຂອງ Docker.',
dockerTrafficPathMixed: 'ພອດທີ່ເລືອກໃຊ້ເສັ້ນທາງເຂົ້າເຖິງຕ່າງກັນ. ກະລຸນາຕັ້ງຄ່າແຍກກັນ.',
dockerTrafficPathUnknown: 'ບໍ່ສາມາດກຳນົດເສັ້ນທາງເຂົ້າເຖິງຂອງພອດນີ້ໄດ້. ກວດສອບເຄືອຂ່າຍ Docker ແລ້ວລອງໃໝ່.',
dockerTrafficPathReason: {
nat_inspect_failed: 'ບໍ່ສາມາດອ່ານກົດ NAT ຂອງ Docker ໄດ້. ກວດສອບຄຳສັ່ງແລະສິດຂອງໄຟວໍ ແລ້ວໂຫຼດໃໝ່.',
proxy_inspect_failed:
'ບໍ່ສາມາດກວດສອບໂປຣເຊສ docker-proxy ໄດ້. ກວດສອບສິດເຂົ້າເຖິງຂໍ້ມູນໂປຣເຊສລະບົບ ແລ້ວໂຫຼດໃໝ່.',
nat_chain_unreachable:
'ພົບກົດສົ່ງຕໍ່ Docker ສຳລັບພອດນີ້ ແຕ່ NAT ingress chain ບໍ່ເຮັດວຽກ. ກວດສອບກົດໄຟວໍ Docker ຫຼືເລີ່ມ Docker ໃໝ່ ແລ້ວໂຫຼດໃໝ່.',
no_matching_path:
'ບໍ່ພົບກົດສົ່ງຕໍ່ Docker ຫຼືໂປຣເຊສ proxy ທີ່ເຮັດວຽກສຳລັບພອດນີ້. ເລີ່ມ ຫຼືເລີ່ມຄອນເທນເນີໃໝ່ ແລ້ວໂຫຼດໃໝ່. ຖ້າຍັງມີບັນຫາ ໃຫ້ກວດສອບເຄືອຂ່າຍ Docker.',
},
dockerTrafficPathPending: 'ລໍຖ້າກວດສອບເສັ້ນທາງ',
dockerInputPolicyNotEffective:
'ພອດນີ້ຖືກຮັບໂດຍໂຮສໂດຍກົງ ດັ່ງນັ້ນກົດປ້ອງກັນພອດຄອນເທນເນີຈຶ່ງບໍ່ມີຜົນ. ກະລຸນາຕັ້ງຄ່າໃນໄຟວໍຂອງໂຮສ.',
+10
View File
@@ -4261,6 +4261,16 @@ const message = {
'Tetapkan sekatan akses untuk port yang diterbitkan oleh bekas Docker pada hos. Port tanpa perlindungan mengekalkan tingkah laku akses lalai Docker.',
dockerTrafficPathMixed: 'Port yang dipilih menggunakan laluan akses berbeza. Tetapkannya secara berasingan.',
dockerTrafficPathUnknown: 'Laluan akses port ini tidak dapat ditentukan. Semak rangkaian Docker dan cuba lagi.',
dockerTrafficPathReason: {
nat_inspect_failed:
'Peraturan NAT Docker tidak dapat dibaca. Semak arahan dan kebenaran tembok api, kemudian muat semula.',
proxy_inspect_failed:
'Proses docker-proxy tidak dapat diperiksa. Semak akses kepada maklumat proses sistem, kemudian muat semula.',
nat_chain_unreachable:
'Peraturan pemajuan Docker wujud untuk port ini, tetapi rantaian masuk NAT tidak aktif. Semak peraturan tembok api Docker atau mulakan semula Docker, kemudian muat semula.',
no_matching_path:
'Tiada peraturan pemajuan Docker aktif atau proses proksi ditemui untuk port ini. Mulakan atau mulakan semula bekas, kemudian muat semula. Jika masalah berterusan, semak konfigurasi rangkaian Docker.',
},
dockerTrafficPathPending: 'Laluan akses belum ditentukan',
dockerInputPolicyNotEffective:
'Port ini diterima terus oleh hos, jadi peraturan perlindungan port bekas sedia ada tidak digunakan. Tetapkannya dalam firewall hos.',
+10
View File
@@ -4282,6 +4282,16 @@ const message = {
'As portas selecionadas usam caminhos de acesso diferentes. Configure-as separadamente.',
dockerTrafficPathUnknown:
'Não foi possível determinar o caminho de acesso desta porta. Verifique a rede do Docker e tente novamente.',
dockerTrafficPathReason: {
nat_inspect_failed:
'Não foi possível ler as regras NAT do Docker. Verifique os comandos e as permissões do firewall e atualize a página.',
proxy_inspect_failed:
'Não foi possível inspecionar os processos docker-proxy. Verifique o acesso às informações dos processos e atualize a página.',
nat_chain_unreachable:
'Existe uma regra de encaminhamento do Docker para esta porta, mas a cadeia de entrada NAT não está ativa. Verifique as regras do firewall do Docker ou reinicie o Docker e atualize a página.',
no_matching_path:
'Nenhuma regra de encaminhamento do Docker ativa ou processo proxy foi encontrado para esta porta. Inicie ou reinicie o contêiner e atualize a página. Se o problema continuar, verifique a rede do Docker.',
},
dockerTrafficPathPending: 'Caminho de acesso pendente',
dockerInputPolicyNotEffective:
'O host recebe esta porta diretamente, portanto a regra de proteção da porta do contêiner não se aplica. Configure-a no firewall do host.',
+10
View File
@@ -4248,6 +4248,16 @@ const message = {
dockerTrafficPathMixed: 'Выбранные порты используют разные пути доступа. Настройте их отдельно.',
dockerTrafficPathUnknown:
'Не удалось определить путь доступа к этому порту. Проверьте сеть Docker и повторите попытку.',
dockerTrafficPathReason: {
nat_inspect_failed:
'Не удалось прочитать правила NAT Docker. Проверьте команды и права межсетевого экрана, затем обновите страницу.',
proxy_inspect_failed:
'Не удалось проверить процессы docker-proxy. Проверьте доступ к информации о системных процессах, затем обновите страницу.',
nat_chain_unreachable:
'Правило перенаправления Docker для этого порта найдено, но входная цепочка NAT не активна. Проверьте правила Docker или перезапустите Docker, затем обновите страницу.',
no_matching_path:
'Для этого порта не найдено активное правило перенаправления Docker или процесс прокси. Запустите или перезапустите контейнер, затем обновите страницу. Если проблема сохраняется, проверьте сеть Docker.',
},
dockerTrafficPathPending: 'Путь доступа не определён',
dockerInputPolicyNotEffective:
'Хост принимает этот порт напрямую, поэтому существующее правило защиты порта контейнера не применяется. Настройте его в межсетевом экране хоста.',
+10
View File
@@ -4263,6 +4263,16 @@ const message = {
dockerTrafficPathMixed: 'Seçilen portlar farklı erişim yolları kullanıyor. Bunları ayrı ayrı yapılandırın.',
dockerTrafficPathUnknown:
'Bu portun erişim yolu belirlenemedi. Docker yapılandırmasını kontrol edip tekrar deneyin.',
dockerTrafficPathReason: {
nat_inspect_failed:
'Docker NAT kuralları okunamadı. Güvenlik duvarı komutlarını ve izinlerini kontrol edip sayfayı yenileyin.',
proxy_inspect_failed:
'docker-proxy işlemleri incelenemedi. Sistem işlem bilgilerine erişimi kontrol edip sayfayı yenileyin.',
nat_chain_unreachable:
'Bu port için bir Docker yönlendirme kuralı var ancak NAT giriş zinciri etkin değil. Docker güvenlik duvarı kurallarını kontrol edin veya Dockerı yeniden başlatıp sayfayı yenileyin.',
no_matching_path:
'Bu port için etkin bir Docker yönlendirme kuralı veya proxy işlemi bulunamadı. Konteyneri başlatın ya da yeniden başlatıp sayfayı yenileyin. Sorun sürerse Docker yapılandırmasını kontrol edin.',
},
dockerTrafficPathPending: 'Erişim yolu bekleniyor',
dockerInputPolicyNotEffective:
'Bu port doğrudan ana makine tarafından alındığından mevcut konteyner port koruma kuralı uygulanmaz. Ana makine güvenlik duvarında yapılandırın.',
+8
View File
@@ -3919,6 +3919,14 @@ const message = {
dockerGuardHelper: ' Docker 容器發佈到主機的連接埠設定存取限制未設定防護的連接埠維持 Docker 預設存取方式',
dockerTrafficPathMixed: '所選連接埠使用不同的存取方式請分別設定',
dockerTrafficPathUnknown: '暫時無法確認此連接埠的存取方式請檢查 Docker 網路設定後重試',
dockerTrafficPathReason: {
nat_inspect_failed: '無法讀取 Docker NAT 規則請檢查防火牆命令及執行權限後重新整理',
proxy_inspect_failed: '無法檢查 docker-proxy 程序請確認可讀取系統程序資訊後重新整理',
nat_chain_unreachable:
'已找到此連接埠的 Docker 轉送規則 NAT 入口鏈未生效請檢查 Docker 防火牆規則或重新啟動 Docker 後重新整理',
no_matching_path:
'未找到此連接埠生效的 Docker 轉送規則或代理程序請啟動或重新啟動對應容器後重新整理若仍異常請檢查 Docker 網路設定',
},
dockerTrafficPathPending: '存取方式待確認',
dockerInputPolicyNotEffective: '此連接埠由主機直接接收現有容器連接埠防護規則不會生效請改用主機防火牆設定',
dockerInputUseHostFirewall: '此連接埠需要透過主機防火牆設定存取規則請前往主機防火牆進行設定',
+8
View File
@@ -3968,6 +3968,14 @@ const message = {
dockerGuardHelper: ' Docker 容器发布到宿主机的端口配置访问限制未设置防护的端口保持 Docker 默认访问方式',
dockerTrafficPathMixed: '所选端口使用不同的访问方式请分别设置',
dockerTrafficPathUnknown: '暂时无法确认该端口的访问方式请检查 Docker 网络配置后重试',
dockerTrafficPathReason: {
nat_inspect_failed: '无法读取 Docker NAT 规则请检查防火墙命令及执行权限后刷新重试',
proxy_inspect_failed: '无法检查 docker-proxy 进程请确认系统进程信息可读取后刷新重试',
nat_chain_unreachable:
'已找到该端口的 Docker 转发规则 NAT 入口链未生效请检查 Docker 防火墙规则或重启 Docker 后刷新',
no_matching_path:
'未找到该端口生效的 Docker 转发规则或代理进程请启动或重启对应容器后刷新若仍异常请检查 Docker 网络配置',
},
dockerTrafficPathPending: '访问方式待确认',
dockerInputPolicyNotEffective: '该端口由主机直接接收现有容器端口防护规则不会生效请改用主机防火墙设置',
dockerInputUseHostFirewall: '该端口需要通过主机防火墙设置访问规则请前往主机防火墙进行配置',
@@ -179,6 +179,7 @@ import i18n from '@/lang';
import { MsgSuccess, MsgWarning } from '@/utils/message';
import { ElMessageBox, type FormInstance, type FormRules } from 'element-plus';
import {
dockerGuardEndpointManagementMessage,
dockerGuardEndpointStatusMessage,
dockerGuardManagementTarget,
isValidDockerGuardSource,
@@ -294,6 +295,13 @@ const toggleSelection = (key: string) => {
};
const openPolicy = (endpoints: Firewall.DockerGuardEndpoint[]) => {
if (!endpoints.length) return;
const endpointToDiagnose = endpoints.find(
(endpoint) => dockerGuardManagementTarget(endpoint) === 'needs_diagnosis',
);
if (endpointToDiagnose) {
MsgWarning(dockerGuardEndpointManagementMessage(endpointToDiagnose));
return;
}
const targets = new Set(endpoints.map(dockerGuardManagementTarget));
if (targets.size !== 1) {
MsgWarning(i18n.global.t('firewall.dockerTrafficPathMixed'));
@@ -304,10 +312,6 @@ const openPolicy = (endpoints: Firewall.DockerGuardEndpoint[]) => {
MsgWarning(i18n.global.t('firewall.dockerInputUseHostFirewall'));
return;
}
if (target !== 'container_guard') {
MsgWarning(i18n.global.t('firewall.dockerTrafficPathUnknown'));
return;
}
policyEndpoints.value = endpoints;
const first = endpoints[0];
form.mode = hasMixedFamilies.value ? 'deny_all' : policyConfigConsistent.value ? first.mode || 'deny_sources' : '';
@@ -395,9 +399,11 @@ const portMappingLabel = (row: Firewall.DockerGuardPortGroup) => {
};
const protectionSummary = (row: Firewall.DockerGuardEndpoint) => {
const target = dockerGuardManagementTarget(row);
if (target === 'host_firewall') return i18n.global.t('firewall.dockerInputUseHostFirewall');
if (target === 'needs_diagnosis') return i18n.global.t('firewall.dockerTrafficPathUnknown');
if (!row.policyUUID) return i18n.global.t('firewall.dockerGuardUnprotected');
if (!row.policyUUID) {
if (target === 'host_firewall') return i18n.global.t('firewall.dockerInputUseHostFirewall');
if (target === 'needs_diagnosis') return dockerGuardEndpointManagementMessage(row);
return i18n.global.t('firewall.dockerGuardUnprotected');
}
let summary = i18n.global.t('firewall.denyAll');
if (row.mode === 'deny_sources') {
summary = `${i18n.global.t('firewall.deny')}: ${formatHostAddressList(row.sources, row.family)}`;
@@ -241,8 +241,10 @@ import { downloadWithContent } from '@/utils/file';
import { getCurrentDateFormatted } from '@/utils/date';
import {
dockerGuardEndpointKey,
dockerGuardEndpointManagementMessage,
dockerGuardEndpointStatusMessage,
dockerGuardManagementTarget,
isDockerGuardRuntimeEndpoint,
} from '@/views/host/firewall/docker/model';
import { formatHostAddressList } from '@/views/host/firewall/utils/validation';
import { newUUID } from '@/utils/id';
@@ -294,6 +296,7 @@ const containerRows = computed(() => {
.filter((container) => container.key !== '__orphan__')
.map((container) => {
const name = container.name || i18n.global.t('firewall.orphanEndpoints');
const runtimeEndpoints = container.endpoints.filter(isDockerGuardRuntimeEndpoint);
const containerMatches = [name, container.application, container.compose]
.filter(Boolean)
.some((item) => item!.toLowerCase().includes(keyword));
@@ -304,7 +307,7 @@ const containerRows = computed(() => {
.some((item) => String(item).toLowerCase().includes(keyword));
};
const portGroups = container.portGroups.flatMap((group) => {
const endpoints = group.endpoints.filter(endpointMatches);
const endpoints = group.endpoints.filter(isDockerGuardRuntimeEndpoint).filter(endpointMatches);
if (!endpoints.length) return [];
if (endpoints.length === group.endpoints.length) return [group];
return endpoints.map((endpoint) => ({
@@ -317,7 +320,7 @@ const containerRows = computed(() => {
return {
...container,
name,
endpoints: container.endpoints.filter(endpointMatches),
endpoints: runtimeEndpoints.filter(endpointMatches),
portGroups,
};
})
@@ -406,12 +409,11 @@ const displaySources = (endpoint: Firewall.DockerGuardEndpoint) =>
formatHostAddressList(endpoint.sources, endpoint.family);
const endpointStatusMessage = (endpoint: Firewall.DockerGuardEndpoint) =>
dockerGuardEndpointStatusMessage(data.base, endpoint);
const isDockerPolicyEndpoint = (endpoint: Firewall.DockerGuardEndpoint) =>
dockerGuardManagementTarget(endpoint) === 'container_guard' && Boolean(endpoint.policyUUID);
const isDockerPolicyEndpoint = (endpoint: Firewall.DockerGuardEndpoint) => Boolean(endpoint.policyUUID);
const endpointPrompt = (endpoint: Firewall.DockerGuardEndpoint) => {
const target = dockerGuardManagementTarget(endpoint);
if (target === 'host_firewall') return i18n.global.t('firewall.dockerInputUseHostFirewall');
if (target === 'needs_diagnosis') return i18n.global.t('firewall.dockerTrafficPathUnknown');
if (target === 'needs_diagnosis') return dockerGuardEndpointManagementMessage(endpoint);
return i18n.global.t('firewall.dockerGuardUnprotected');
};
@@ -7,6 +7,9 @@ type DockerGuardEndpointIdentity = Pick<Firewall.DockerGuardEndpoint, 'family' |
export const dockerGuardEndpointKey = (endpoint: DockerGuardEndpointIdentity): string =>
`${endpoint.family}|${endpoint.hostIP}|${endpoint.hostPort}|${endpoint.protocol}`;
export const isDockerGuardRuntimeEndpoint = (endpoint: Firewall.DockerGuardEndpoint): boolean =>
!endpoint.containerState || ['running', 'paused', 'restarting'].includes(endpoint.containerState);
export const dockerGuardManagementTarget = (
endpoint: Firewall.DockerGuardEndpoint,
): NonNullable<Firewall.DockerGuardEndpoint['managementTarget']> => {
@@ -16,6 +19,13 @@ export const dockerGuardManagementTarget = (
return 'needs_diagnosis';
};
export const dockerGuardEndpointManagementMessage = (endpoint: Firewall.DockerGuardEndpoint): string => {
if (endpoint.managementReason) {
return i18n.global.t(`firewall.dockerTrafficPathReason.${endpoint.managementReason}`);
}
return i18n.global.t('firewall.dockerTrafficPathUnknown');
};
export const isValidDockerGuardSource = (family: Firewall.DockerGuardEndpoint['family'], value: string): boolean =>
isValidAddressForFamily(family, value);
@@ -45,7 +55,7 @@ export const dockerGuardEndpointStatusMessage = (
if (!endpoint.policyUUID || endpoint.effective) return '';
const target = dockerGuardManagementTarget(endpoint);
if (target === 'host_firewall') return i18n.global.t('firewall.dockerInputPolicyNotEffective');
if (target === 'needs_diagnosis') return i18n.global.t('firewall.dockerTrafficPathUnknown');
if (target === 'needs_diagnosis') return dockerGuardEndpointManagementMessage(endpoint);
const ipv6 = endpoint.family === 'ipv6';
return dockerGuardFamilyStatusMessage(base, ipv6 ? 'IPv6' : 'IPv4', ipv6 ? base.ipv6 : base.ipv4);
};
@@ -396,7 +396,7 @@ import i18n from '@/lang';
import { getCurrentDateFormatted } from '@/utils/date';
import { downloadWithContent } from '@/utils/file';
import { MsgError, MsgSuccess } from '@/utils/message';
import { dockerGuardManagementTarget } from '@/views/host/firewall/docker/model';
import { dockerGuardEndpointManagementMessage, dockerGuardManagementTarget } from '@/views/host/firewall/docker/model';
import { formatHostAddress } from '@/views/host/firewall/utils/validation';
import RuleImport from '@/views/host/firewall/rule/import/index.vue';
import RuleOperate from '@/views/host/firewall/rule/operate/index.vue';
@@ -422,6 +422,7 @@ interface UsageEntry {
pid?: number;
docker?: boolean;
dockerManagementTarget?: Firewall.DockerGuardEndpoint['managementTarget'];
dockerEndpoint?: Firewall.DockerGuardEndpoint;
}
interface DisplayNotice {
@@ -775,19 +776,25 @@ const ruleUsageEntries = (row: RuleRow): UsageEntry[] => {
owner: `Docker: ${endpoint.containerName || endpoint.containerID?.slice(0, 12) || '-'}`,
docker: true,
dockerManagementTarget: dockerGuardManagementTarget(endpoint),
dockerEndpoint: endpoint,
}));
return [...processes, ...docker];
};
const usageEntryPortText = (entry: UsageEntry) => entry.ports.join(', ') || '-';
const dockerUsageMessage = (entry: UsageEntry) => {
if (entry.dockerManagementTarget === 'host_firewall') {
return i18n.global.t('firewall.dockerInputUseHostFirewall');
}
if (entry.dockerManagementTarget === 'container_guard') {
return i18n.global.t('firewall.dockerInputNotProtected');
}
return entry.dockerEndpoint
? dockerGuardEndpointManagementMessage(entry.dockerEndpoint)
: i18n.global.t('firewall.dockerTrafficPathUnknown');
};
const usageEntryLabel = (entry: UsageEntry) =>
entry.docker
? `${entry.owner} (${usageEntryPortText(entry)}) — ${i18n.global.t(
entry.dockerManagementTarget === 'host_firewall'
? 'firewall.dockerInputUseHostFirewall'
: entry.dockerManagementTarget === 'container_guard'
? 'firewall.dockerInputNotProtected'
: 'firewall.dockerTrafficPathUnknown',
)}`
? `${entry.owner} (${usageEntryPortText(entry)}) — ${dockerUsageMessage(entry)}`
: `${entry.owner} (${usageEntryPortText(entry)})`;
const openUsageDetail = (entry: UsageEntry) => {
if (entry.docker) {