如何查看firewalld当前已开放的端口?使用`firewall-cmd --list-ports`命令只能显示通过`--add-port`方式直接添加的端口,但无法展示通过服务(如http、ssh)间接开放的端口。许多用户因此误以为某些端口未开放。如何准确查看系统中所有实际生效的开放端口,包括通过服务启用的端口?此外,`--list-all`输出信息繁多,如何快速提取关键端口信息?在使用firewalld的生产环境中,如何结合`--permanent`选项正确查看持久化规则中的开放端口配置?
1条回答 默认 最新
娟娟童装 2025-12-09 19:57关注一、firewalld端口管理机制解析
在现代Linux系统中,firewalld作为动态防火墙管理工具,广泛应用于RHEL、CentOS、Fedora等发行版。其核心优势在于支持运行时配置与永久配置分离,并通过“区域(zone)”和“服务(service)”抽象简化网络策略管理。
然而,在实际运维过程中,许多工程师发现使用
firewall-cmd --list-ports命令仅能显示通过--add-port显式添加的端口,而无法反映由预定义服务(如 http、https、ssh)所开放的端口。这导致对“哪些端口真正对外开放”的误判,进而影响故障排查与安全审计。1.1 理解 firewalld 的端口开放机制
- 直接端口添加:通过
--add-port=8080/tcp添加的端口会被--list-ports显示。 - 服务级开放:启用服务如
--add-service=http,会自动加载该服务定义的所有端口(例如80/tcp),但这些不会出现在--list-ports中。 - 服务定义文件位置:
/usr/lib/firewalld/services/和/etc/firewalld/services/。
1.2 查看当前运行时所有生效端口的完整方法
要准确获取当前实际开放的端口列表(包括服务引入的端口),需结合以下命令:
# 查看默认区域中所有信息 firewall-cmd --list-all # 示例输出: # public (active) # target: default # icmp-block-inversion: no # interfaces: eth0 # sources: # services: ssh dhcpv6-client http https # ports: 8080/tcp # forward-ports: # source-ports: # protocols: # masquerade: no # forward-ports: # icmp-blocks: # rich rules:从上述输出可见,
services字段包含 http、https 等服务,需进一步解析其对应端口。1.3 提取服务对应端口:自动化脚本示例
为快速提取所有已启用服务的实际端口,可编写如下 Bash 脚本:
#!/bin/bash ZONE=$(firewall-cmd --get-default-zone) SERVICES=$(firewall-cmd --zone=$ZONE --list-services) echo "Active services in zone '$ZONE': $SERVICES" echo "Resolved ports:" for svc in $SERVICES; do PORTS=$(grep -E "^<port" /usr/lib/firewalld/services/${svc}.xml | \ sed -E 's/.*port="([^"]+)".*protocol="([^"]+).*/\1\/\2/') echo "$svc: $PORTS" done1.4 综合列出所有实际开放端口(含服务与直接端口)
以下命令组合可用于生成完整的开放端口清单:
命令 说明 firewall-cmd --list-ports仅显示直接添加的端口 firewall-cmd --list-services列出当前区域启用的服务 firewall-cmd --list-all显示完整配置,适合人工分析 firewall-cmd --permanent --list-all查看持久化规则(重启后仍生效) firewall-cmd --info-service=http查看特定服务详情(含端口) 1.5 生产环境中如何正确查看持久化规则
在生产系统中,必须区分运行时规则与永久规则。常见误区是修改了永久规则但未重载,或只查看运行时状态。
- 查看永久开放的端口:
firewall-cmd --permanent --list-ports - 查看永久启用的服务:
firewall-cmd --permanent --list-services - 合并两者并解析服务端口:
PERM_PORTS=$(firewall-cmd --permanent --list-ports) PERM_SVCS=$(firewall-cmd --permanent --list-services) ZONE=$(firewall-cmd --get-default-zone) echo "Permanent Ports:" echo "$PERM_PORTS" echo "Permanent Services and Their Ports:" for s in $PERM_SVCS; do grep -E "^<port" /usr/lib/firewalld/services/$s.xml 2>/dev/null | \ sed -E "s/.+port=\"([^\"]+)\" protocol=\"([^\"]+).*/$s: \1\/\2/" done1.6 使用流程图展示端口查询逻辑
graph TD A[开始] --> B{是否需要查看持久化规则?} B -- 是 --> C[使用 --permanent 选项] B -- 否 --> D[使用运行时命令] C --> E[执行 firewall-cmd --permanent --list-all] D --> F[执行 firewall-cmd --list-all] E --> G[提取 services 和 ports] F --> G G --> H[解析每个 service 的 XML 定义] H --> I[合并 direct ports 与 service ports] I --> J[输出完整开放端口列表]1.7 高级技巧:构建统一端口视图工具
建议在生产环境部署一个自定义脚本,定期输出标准化报告。示例功能包括:
- 自动识别默认区域
- 同时检查运行时与永久配置差异
- 输出JSON格式便于集成监控系统
- 标记潜在风险端口(如 23/telnet, 21/ftp)
#!/bin/bash # get-open-ports.sh - 获取全量开放端口 output_json() { local runtime_ports=$(firewall-cmd --list-ports | tr ' ' '\n') local perm_ports=$(firewall-cmd --permanent --list-ports | tr ' ' '\n') local svcs=$(firewall-cmd --list-services | tr ' ' '\n') echo "{ \"runtime_ports\": [$(echo $runtime_ports | sed 's/$/"/; s/^/"/; s/ /", "/g')]," echo " \"services\": {" first=true while read svc; do [ -z "$svc" ] && continue ports=$(grep -E '<port' /usr/lib/firewalld/services/$svc.xml | sed -E 's/.+port="([^"]+)".protocol="([^"]+).*/"\1\/\2"/') if [ "$first" = true ]; then first=false; else echo -n ", "; fi echo -n "\"$svc\": [$ports]" done <<< "$svcs" echo " }" echo "}" }1.8 安全与审计建议
在企业级部署中,应建立如下最佳实践:
- 避免混合使用 direct 规则与 zone/service 模型
- 定期导出并版本控制
/etc/firewalld/下的配置 - 使用
firewall-offlines-cmd在离线镜像中验证策略 - 结合
ss -tuln或netstat验证内核层实际监听状态 - 将 firewalld 输出与主机入侵检测系统(HIDS)联动
本回答被题主选为最佳回答 , 对您是否有帮助呢?解决 无用评论 打赏 举报- 直接端口添加:通过