② 端口为何“关了还通”?三层防火墙与 Nginx 反向代理的正确姿势

目标:把公网暴露面降到最小,同时保证服务可用与可观测。彻底搞懂“云防火墙/系统防火墙/面板防火墙 + Nginx 反代 + 回环绑定”的协作逻辑,并给出可复制的落地方案。

说明:文中使用占位符域名与地址,如 example.comrss.example.com203.0.113.10 等。


全局思路

  • 只在公网开放极少的入口端口80/443/22(以及确需直连的特定端口,比如同步 22000)。

  • 所有后端服务尽量 绑定到 127.0.0.1(回环地址) 或根本不做端口映射,只让 Nginx 反代对外服务。

  • 防护分三层:

    1. 云防火墙(云厂商安全组/实例防火墙) —— 第一层“外城墙”;

    2. 系统防火墙firewalld/iptables)或第三方面板防火墙 —— 第二层“内城墙”;

    3. 应用层(Nginx 反代、TLS、限流、访问控制) —— 第三层“城门”。

这就是你看到“关闭 8081/8082/1200/8088 等端口后,站点仍然能访问”的原因:外界走的是 443 → Nginx → 127.0.0.1:后端端口,而不是直接打后端端口。


【实操教学】端到端落地

下面演示把一个后端 Web 服务(容器内 8080)上线为 rss.example.com,公网只打开 443

1)Docker/Compose:只映射到回环地址

# docker-compose.yml(示例)
services:
  app:
    image: ghcr.io/vendor/app:stable
    container_name: app
    # 绑定到宿主机回环:外网无法直连,只能本机访问
    ports:
      - "127.0.0.1:8082:8080"     # 本机回环:宿主端口:容器端口
    restart: unless-stopped

解释

  • 127.0.0.1:8082:8080只在本机开放 8082,不在公网网卡绑定;外界无法直连。

  • 也可不写 ports,用 expose: 8080 并让 Nginx 加入同一 Docker 网络直连容器(更“内网化”),但需要一点网络配置,这里用回环法更直观。

启动:

docker compose up -d
# up -d:后台启动

2)Nginx 反代到回环端口(统一走 443)

以面板/Nginx 为例(手写或面板可视化都可)。核心配置:

server {
    listen 443 ssl http2;
    server_name rss.example.com;

    # SSL 证书(Let’s Encrypt)
    ssl_certificate     /etc/letsencrypt/live/rss.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/rss.example.com/privkey.pem;

    # 强制 HSTS(可选:上线稳定后再开)
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

    location / {
        proxy_pass http://127.0.0.1:8082;

        # 反代“必备”请求头(避免样式/JS丢失 & 协议/Host 错乱)
        proxy_set_header Host              $host;
        proxy_set_header X-Real-IP         $remote_addr;
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Host  $host;
        proxy_set_header X-Forwarded-Port  $server_port;

        # (可选)超时/缓存/压缩等按需增加
        proxy_read_timeout 60s;
    }
}

# 80 强制跳转到 443(统一加密入口)
server {
    listen 80;
    server_name rss.example.com;
    return 301 https://$host$request_uri;
}

解释

  • 对外只有 443 入口;Nginx 在本机把请求转发到 127.0.0.1:8082

  • 这就是“路 A:反向代理”——公网不需要放行 8082。

  • 反代请求头的 6 行是“血坑终结者”:少了 X-Forwarded-Proto/Host 很容易出现“资源用 http 加载,被浏览器拦截”的问题。


3)云防火墙(安全组):只放行必要端口

允许:

  • 443/TCP(站点)

  • 80/TCP(仅跳转)

  • 22/TCP(SSH)

  • 特殊需求(如 Syncthing 数据通道 22000/TCP+UDP

关闭

  • 8081/8082/8088/1200… 等所有历史直连端口

  • 面板/数据库默认端口若对外无必要,一律关闭

原则:能反代就不直连;能内网就不公网。


4)系统层防火墙(可选):保持简单一致

  • 如果你已经用云防火墙统一管理端口,且宿主机后端服务都绑定回环,可以考虑 不开启 firewalld,避免三处重复维护。

  • 若必须开 firewalld,用“允许清单”策略,与云防火墙保持一致即可。


5)验证与自检

# 观察后端端口是否仅回环监听
ss -tulpen | grep 8082
# ss:socket 状态;-tulpen:TCP/UDP + 监听 + 进程 + 端口 + 详细信息
# 期望看到:Local Address 为 127.0.0.1:8082 或 [::1]:8082

# 从服务器本机试
curl -I http://127.0.0.1:8082
# -I:只看响应头;200/302 即说明后端健康

# 从外网浏览器访问
https://rss.example.com
# 外部只能走 443->Nginx;直连 http://SERVER_IP:8082 应该超时/拒绝

常见“疑难杂症”与处理

症状 A:端口关了,监控却“依然正常”

原因

  • 你的监控工具(如 Uptime Kuma)监控的是 域名 https://rss.example.com;关闭 8082 后,通过 443→Nginx→127.0.0.1:8082 仍然畅通,因此服务仍然是健康的

  • 这正是我们想要的:只开放 443/80,后端不直连。

什么时候会误判?

  • 网站关停但 Nginx 仍返回 200(例如缓存/静态页),或返回 403/302;默认“HTTP(s)”监控只看状态码,不看内容

    改法

  • 在 Uptime Kuma 使用 “HTTP(s) – 关键字” 监控;关键字使用页面标题/标识,一旦空白页/错误页就判定故障。

  • 或者监控 TCP 端口(对某些服务更直观)。


症状 B:页面只剩文字,样式/JS 404 或被浏览器拦截

原因

  • 反代头不完整,后端以为自己是 http,在 https 页面里加载 http 资源(“混合内容”),或构造了错误的绝对路径。

    改法

  • 保证 Nginx 反代里有以下 6 行“黄金头”:

proxy_set_header Host              $host;
proxy_set_header X-Real-IP         $remote_addr;
proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host  $host;
proxy_set_header X-Forwarded-Port  $server_port;

症状 C:合上云防火墙后,SSH 掉线

原因

  • 关闭了 22/TCP

    改法

  • 永远保留 22/TCP(或你自定义的 SSH 端口)。

  • 在 Uptime Kuma 加一项 TCP 22 自监控,避免“锁死在门外”。


症状 D:容器服务暴露到了公网(

0.0.0.0:8082

原因

  • ports: 写成了 8082:8080(默认绑定所有网卡)。

    改法

  • 改为 127.0.0.1:8082:8080;或不映射端口,改走 Docker 内网 + Nginx 容器直连。


【深度解析与知识扩展】

为什么“回环 + 反代”是更适合的默认安全姿态?

  • 最小暴露面:后端模块、数据库、队列等都藏在本机或容器网络里;外界只能打进 Nginx。

  • 统一 TLS 与访问控制:证书、限流、WAF、IP 黑白名单、审计日志,全部集中在 Nginx/反代层做。

  • 降低维护复杂度:端口策略从“多后端、多端口”收敛为“少数入口端口”。

  • 自然兼容容器:容器 IP/端口随时变;反代只要指向回环或统一内网就好。

云防火墙 vs 系统防火墙 vs 面板防火墙

  • 云防火墙最外层、在操作系统之外,第一道关卡;规则生效快、可视化、易回滚。

  • 系统防火墙(firewalld):更细粒度,但规则复杂度也更高;若前两层决策明确,可以不启用以减少维护面。

  • 面板防火墙:本质也是在改系统规则;若使用云防火墙,面板防火墙不一定必开,避免三处不一致。


上线核对清单(Checklist)

  • 后端服务仅 127.0.0.1:端口 或 Docker 内网可访问

  • Nginx 反代 + 强制 HTTPS + 必备反代头

  • 云防火墙只开放 443/80/22/(必要直连端口)

  • Uptime Kuma 使用 关键字监控 对核心站点做内容校验

  • ss -tulpen 验证没有多余的 0.0.0.0:高危端口 在监听

  • 备份 Nginx 站点配置、证书与 Compose 文件


结语

合上后端端口,网站依然可用”不是玄学,而是反向代理 + 回环绑定这条经典架构路径在发挥作用。

它让你的公网暴露面大幅收敛、安全域清晰、可观测性不下降。把这条路径固化成团队的默认模板,你就离“可运维、可扩展、可迁移”的平台更近一步。

发表回复

Your email address will not be published. Required fields are marked *.

*
*

Copyright © 2025 十两东日的随想. All Rights Reserved.

鄂ICP备2025140583号-1 | 鄂公网安备42011102005804号