远程给服务器启用防火墙,最紧张的一刻通常发生在敲下命令之后:当前 SSH 窗口还在,但新窗口连不上;或者 UFW 只显示放行了 80、443,容器的数据库端口却仍能从外网访问。两种情况都说明,规则列表与真实流量路径还没有核对完整。
下面以一台提供网站服务的 Ubuntu 主机为例。目标是明确公开 Web 入口、限制管理访问,并确认容器不会额外暴露内部服务。文中的地址属于说明性示例,网卡名和 SSH 端口必须替换为实际值;这些命令没有在本站生产服务器上执行。
先记录当前入口,再添加规则
防火墙不负责启动服务。端口没有进程监听时,放行规则不会让网站出现;应用只监听回环地址时,也不能靠开放安全组让它直接接受公网连接。因此先查看服务状态和监听地址:
sudo ss -lntup
sudo ufw status verbose
sudo ufw show added
ip -brief address
同时记录云平台的安全组或端口映射。公网请求可能先经过云侧规则,再到主机,最后进入应用或容器网络。只改其中一层,无法保证整条路径可达。Ubuntu 防火墙文档介绍了 UFW 与底层过滤规则的关系。
管理连接尤其要核对真实来源。你通过 VPN、跳板机或 NAT 登录时,服务器看到的地址可能不是笔记本本地地址。规则应该允许实际到达服务器的来源,不能把自己电脑上的 192.168... 直接当作公网来源填写。
在修改之前,确认可以使用云控制台、串口或其他独立恢复入口。保留旧 SSH 会话有帮助,但它不能替代恢复通道:连接跟踪可能使旧会话继续工作,而新连接已被拒绝。
给 SSH 留出明确的通路
假设 SSH 确实监听 TCP 22,管理员拥有固定公网地址,规则可以按来源限制。下面的 203.0.113.10 是文档示例,不能照抄为自己的地址。
sudo ufw allow from 203.0.113.10 to any port 22 proto tcp
如果 SSH 使用其他端口,先替换端口。OpenSSH 应用配置是一个预定义规则入口,不会自动跟随你对 SSH 服务做出的所有修改。可用以下命令查看本机配置实际开放什么:
sudo ufw app info OpenSSH
固定来源并不适合所有管理方式。经常变化的家庭公网地址可能使你之后无法登录,这时应先设计稳定的管理路径,例如受控 VPN 或跳板机,再收紧规则。不要用一条只对今天有效的规则,替代日后的恢复安排。
若原来已经有允许任意来源访问 SSH 的规则,添加一条更窄的 allow 不会自动收紧它。需要在确认窄规则有效后删除旧规则。每删一条都重新查看编号,避免后续编号变化导致误删其他入口。
对单机网站开放必要的协议
对典型网站主机,可以从默认拒绝入站、允许出站开始,再显式允许需要的端口。前提是已安排正确的 SSH 放行规则,并核对现有服务没有其他必要入口。
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw logging low
sudo ufw enable
HTTP/3 使用 QUIC 时,还涉及 UDP 443;只开 TCP 443 不等于已经允许 HTTP/3。是否开放 UDP,应取决于实际运行的服务。其他 UDP 应用也应单独列出,不能因为端口号一样就当成相同规则。
启用后立即从另一个终端建立新的 SSH 连接,再从外部网络访问网站。测试失败时先保留已有会话,通过恢复入口核对规则。不要在唯一连接里反复执行 reset,期望某一次恰好恢复。
IPv6 不能只看域名是否常用
服务器有 IPv6 地址、服务监听 IPv6 时,就存在另一条访问路径。IPv4 规则通过测试,并不能说明 IPv6 同样受限。检查 UFW 的 IPv6 设置、云侧策略以及应用监听情况,再从具备 IPv6 的外部环境验证。
有 AAAA 记录的域名,还可能让用户优先走 IPv6。出现“我能打开,同事打不开”的现象时,可以分别测试两种地址族,而不是立即归因于浏览器缓存。
如果决定不使用 IPv6,应在网络和应用配置中明确处理,并确认不会破坏已有依赖;仅不发布 AAAA 记录不等于服务器上的 IPv6 服务不可达。反过来,启用 IPv6 也应同时完成访问控制,而不是等上线后再补。
验收记录可以按“来源、目的地址、协议、端口、允许或拒绝”列成表。这样测试 IPv4、IPv6、管理来源和普通公网来源时,结果有可比较的标准。
Docker 发布端口需要单独核对
Docker 会为容器网络配置过滤和转发规则。发布到宿主机的容器端口,其流量路径可能绕过你以为会处理它的 UFW 主机入站规则。Docker 官方明确说明了与 UFW 的这一问题,见过滤与防火墙文档。
先看服务是否需要发布端口。应用和数据库处于同一 Compose 网络时,应用通常可以直接访问数据库服务名,无需把数据库的 5432 暴露到宿主机。减少不必要的端口发布,比后来再补很多阻止规则容易核查。
若由宿主机上的反向代理转发,可以将应用端口绑定到回环地址。下面只是结构示例,镜像需要替换为自己的应用:
services:
app:
image: example-app:1.0.0
ports:
- "127.0.0.1:8080:8080"
这项绑定控制的是发布端口;还要结合 Docker 版本、网络模式与路由配置理解实际可达性。不要把它扩写成任何环境下的绝对隔离保证。端口发布及旧版本注意事项见 Docker 端口文档。
需要对容器转发流量增加规则时,先确认 Docker 使用的防火墙后端。iptables 后端提供 DOCKER-USER 等链;原生 nftables 后端的组织方式不同,不能把另一套链名硬套过去。分别参考 iptables 后端和 nftables 后端说明。
也不要为了“让 UFW 接管”就关闭 Docker 自动管理规则。缺少必要转发或 NAT 配置,容器网络可能直接失效。高级网络策略应先在与生产接近的环境中验证,记录请求经过的链和路由。
拒绝规则不生效时,检查顺序和已有连接
简单场景可以采用默认拒绝、少量允许规则。随着例外增加,顺序会变得重要:一条较宽的允许规则可能先匹配,使后面的限制达不到预期。查看实际规则,而不是只检查新增命令有没有返回成功。
sudo ufw status numbered
sudo ufw show raw
sudo nft list ruleset
这些输出属于不同层次,不能把看到 nftables 规则就直接当成使用了某个特定管理后端。有的工具通过兼容层操作规则,有的服务自己管理独立表。排查时记录系统版本和各组件配置,避免同时用多个工具反复改同一段规则。
已有连接还可能继续受连接跟踪状态影响。验证限制时应建立新的连接,并明确来源;在原来的长连接上继续收到数据,不足以判断新建连接是否开放。
UFW 的 limit 可以为某些场景提供基础连接速率限制,但它不会理解网站用户是否成功登录。应用认证、SSH 密钥配置和必要的日志分析仍有各自作用,不能把端口过滤当成业务权限系统。
出站限制和路由转发另做设计
默认允许出站便于普通网站访问 DNS、软件源、对象存储和第三方 API。若要改成默认拒绝,应先列出依赖与实际网络路径,再制定规则。只放行 HTTPS 而漏掉解析或时间同步,可能导致看似无关的业务故障。
CDN 和云服务地址会变化,用一次解析得到的 IP 长期放行,维护成本很高。出站控制应该结合服务性质和网络架构,不宜在通用初始化脚本中一刀切。
服务器如果兼任 VPN 网关或路由器,还需要处理转发流量、内核转发设置和可能的 NAT。允许访问本机端口,与允许一个接口进来、另一个接口出去,是不同规则。先画出来源、目标和返回路径,再决定是否需要 UFW route 或更底层的配置。
留一份能帮助恢复的检查结果
修改前保存现有规则和配置,修改后记录新增、删除的具体项。截图只能帮助阅读,恢复时还需要真实配置、版本和执行顺序。避免把“清空全部规则,再只开放 SSH”称作通用回滚,它会中断其他原本正常的服务。
日志从适量级别开始,关注规则失败和异常访问,同时给日志安排轮转。高流量机器持续记录所有包,可能先耗尽磁盘。排查结束后应撤销临时高强度日志和临时开放端口。
最后从允许的管理来源、不允许的外部来源分别验证 SSH,再检查网站与数据库等敏感端口。必要时安排可控重启,确认规则和服务配置能够恢复。验收依据是这些连接结果及记录,单独一行 Status: active 不能说明整台服务器的入口已经符合预期。
原文来自 zhihu.ee,本文保留原发布时间。











