常见用法:香港VPS 上装 Nginx,开 80/443,把 Gitea、Grafana、Portainer、后台 API 全暴露出去。
结果:IP 被扫、接口被刷、0day 打穿直接进内网。
更合理的用法是——香港VPS 只做“访问平面”:
- 公网不监听 Web 端口
- 所有内部服务走隧道 + SSO/MFA
- 运维走 WireGuard 私网
- 每一次访问可认证、可审计、可吊销
本文给一套自托管零信任边界:Cloudflare Tunnel 收公网、Authelia 做身份、WireGuard 管运维、审计日志集中化,附可复制配置。
一、先改心智模型:边界不是防火墙,是“认证平面”
传统边界:
text
公网 → 防火墙 → 80/443 → Nginx → 服务
问题:端口一开,攻击面就在。
零信任边界:
text
用户/运维 → 身份校验(Cloudflare Access / Authelia) → 隧道终结(不暴露任何入站端口) → 香港VPS 内网 → 具体服务
原则:
默认不信任任何网络位置,不开放任何公网端口,每次访问都验证身份+设备+上下文。
二、整体架构
text
[开发者浏览器] │ HTTPS(Cloudflare 边缘做身份前置) ▼ Cloudflare Access(邮箱/SSO/MFA) │ 通过后才建隧道 ▼ 香港VPS(cloudflared 出向连接,无入站端口) ├─ Authelia:本地 SSO/MFA 兜底 ├─ 内网服务:Gitea / Grafana / Portainer / n8n └─ WireGuard:运维私网入口(只收隧道流量) [运维终端] │ WireGuard(只连管理网) ▼ 香港VPS 内网 → 跳板机 → 源站内网
防火墙最终状态:
- 入站:只留 WireGuard UDP 端口 + 自定义 SSH 端口(限 IP)
- 80/443:不监听(全走隧道)
三、Cloudflare Tunnel:先关掉公网端口
1. 建隧道
bash
cloudflared tunnel login cloudflared tunnel create hk-zero-trust
2. 配置(只暴露认证后的服务)
yaml
# /etc/cloudflared/config.yml tunnel: hk-zero-trust credentials-file: /etc/cloudflared/<tunnel-id>.json ingress: - hostname: git.example.com service: http://127.0.0.1:3000 - hostname: grafana.example.com service: http://127.0.0.1:3001 - hostname: portainer.example.com service: http://127.0.0.1:9443 - service: http_status:404
3. 防火墙关 Web 端口
bash
ufw default deny incoming ufw allow 51820/udp # 仅 WireGuard ufw allow 22222/tcp # 仅应急 SSH(限办公 IP) ufw deny 80/tcp ufw deny 443/tcp ufw enable
效果:直连 VPS IP 的 80/443 全部不通,扫描器拿不到任何 HTTP 指纹。
四、Authelia:给自托管服务补 SSO + MFA
Docker Compose 最小件:
yaml
services: authelia: image: authelia/authelia:latest volumes: - ./authelia/config:/config networks: [internal]
配置核心:
yaml
# configuration.yml session: secret: ${SESSION_SECRET} name: authelia_session access_control: default_policy: deny rules: - domain: "git.example.com" policy: one_factor - domain: "grafana.example.com" policy: two_factor - domain: "portainer.example.com" policy: two_factor totp: issuer: hk-vps
用户首次访问:
- Cloudflare Access 验邮箱/SSO
- 转发到 Authelia 再验 TOTP
- 通过才代理到本地服务
离职/撤权:只删 Access 策略 + 删 Authelia 用户,不等逐个服务改密码。
五、运维通道:WireGuard 不暴露内网全量
香港VPS 只做“运维跳板”,不把家底摊给 VPN 客户端。
ini
# wg0.conf(中心节点) [Interface] Address = 10.10.10.1/24 ListenPort = 51820 PrivateKey = <server-key> [Peer] PublicKey = <laptop-pub> AllowedIPs = 10.10.10.2/32 # 不推 0.0.0.0/0,只给管理网段
客户端只拿到:
- 10.10.10.0/24 互通
- 能访问香港机内网服务
- 不能拿香港机当出口翻去别的内网
MTU 调 1420 防分片:
bash
ip link set wg0 mtu 1420
SSH 加固(顺手):
bash
# /etc/ssh/sshd_config PermitRootLogin no PasswordAuthentication no PubkeyAuthentication yes Port 22222
fail2ban + 审计:
bash
apt install -y auditd fail2ban auditctl -w /etc/ssh/sshd_config -p wa -k ssh_config
六、服务暴露原则:最小权限 + 分域
服务 |
暴露方式 |
认证 |
Gitea |
Tunnel + 单因子 |
SSO 邮箱 |
Grafana |
Tunnel + 双因子 |
Authelia MFA |
Portainer |
Tunnel + 双因子 |
MFA + 来源 IP |
数据库 |
不暴露 |
只走 WireGuard 内网 |
后台 API |
Tunnel + mTLS |
服务间双向证书 |
mTLS 示例(服务间):
nginx
listen 443 ssl; ssl_certificate /certs/svc.crt; ssl_certificate_key /certs/svc.key; ssl_client_certificate /certs/ca.crt; ssl_verify_client on;
七、审计与可观测:零信任没有日志等于没做
集中采集三件事:
- 访问层:Cloudflare Access 日志(谁、何时、哪服务)
- 身份层:Authelia 认证成功/失败
- 主机层:auditd + ssh 会话命令审计
bash
# 会话命令审计 auditctl -a always,exit -F arch=b64 -S execve -k shell_cmd ausearch -k shell_cmd | aureport -f
告警规则:
- 同一用户 5 分钟内 3 次 MFA 失败 → 封 10 分钟
- 非办公时段访问 Portainer → 飞书/钉钉告警
- WireGuard 新设备接入 → 记录设备指纹+时间
日志保留:
- 访问日志 90 天(合规可溯源)
- 原始认证日志加密归档,不进公网桶
八、合规边界(香港节点也要讲)
- 香港 PDPO:本地用户数据不长期落盘
- 涉及大陆用户 PII:不进零信任节点明文
- 涉及欧盟用户:GDPR 传输机制 + DPA
- 密钥:SSH CA / TLS 私钥放 KMS 或离线,不写镜像
可重建原则:
香港机没了,重装 Tunnel + Authelia + WireGuard 配置,半小时恢复,不丢业务状态。
九、最小落地清单
- [ ] VPS 初始化:禁密码、改端口、开 UFW 默认拒绝
- [ ] 装 cloudflared,建隧道,关 80/443 入站
- [ ] Authelia 接 TOTP/SSO,服务按域配策略
- [ ] WireGuard 只给管理网,不推全量路由
- [ ] 内部服务只绑 127.0.0.1 / 内网,不绑 0.0.0.0
- [ ] 服务间调用开 mTLS
- [ ] auditd 采命令级日志,Access 日志集中化
- [ ] 每月演练:撤一个用户、关一个服务、恢复一次
十、什么别放零信任边界机
- 生产主数据库(只走内网跳板)
- 未脱敏客服数据
- 长期明文会话录制
- 把 Tunnel 当公开反代裸跑(仍要身份前置)
- 密钥写进镜像层
十一、总结
香港VPS 最稳的安全姿势,不是“加 WAF、开高防”,而是:
把公网入口从“开端口”变成“先认证”。
Cloudflare Tunnel 收流量,
Authelia 验人,
WireGuard 管运维,
审计日志兜底部。
端口全关、身份前置、权限到服务级,
扫描器打不到、爆破没入口、离职一键撤权。
零信任不是大厂专利,
一台 1C1G 香港VPS,也能把边界做对。