NetBird+Caddy:不暴露公网的远程访问方案

引言:家庭实验室的远程访问难题
对于运行家庭实验室(Homelab)的自托管爱好者来说,如何在离家时安全地访问内网服务,是一个绑不开的话题。家庭实验室是技术爱好者在自己家中搭建的服务器环境,用于运行各种自托管服务,如媒体服务器(Jellyfin/Plex)、密码管理器(Vaultwarden)、文件同步(Nextcloud)等。自托管运动的兴起源于对数据主权的追求——用户希望将个人数据保存在自己掌控的硬件上,而非依赖第三方云服务。然而,自托管带来的最大挑战之一就是远程访问:如何在外出时安全地连接到家中的服务,同时不将这些服务暴露给互联网上的潜在攻击者。
一种常见但危险的做法是直接将服务端口暴露到公网,或使用端口转发——这会显著扩大攻击面。攻击者可以通过端口扫描工具(如 Shodan、Masscan)发现暴露在公网上的服务,进而利用已知漏洞发起攻击。
近期 Reddit 上一位用户提出的问题,正好代表了许多进阶玩家的需求:如何在不将任何服务暴露到公网的前提下,通过 NetBird 这类 WireGuard 组网工具远程访问由 Caddy 反向代理的服务,并保持内外网使用同一套域名?
这个问题看似简单,实则涉及 DNS 解析、反向代理和零信任组网三者的协同。本文将拆解其中的核心矛盾,并给出可落地的方案。

现有架构分析:为什么这套设计值得借鉴
先来看这位用户的原始配置,其实设计得相当规范:
- 域名托管在 Cloudflare,DNS 记录指向服务器的 LAN 内网 IP;
- 所有 Docker 服务均不向宿主机暴露端口,只有 Caddy 监听 80 和 443;
- 即便在局域网内,也无法通过
http://server-ip:service-port直接访问某个服务,必须走https://service.example.com经由 Caddy。
Docker 容器默认运行在隔离的虚拟网络中。当容器不通过 -p 参数映射端口到宿主机时,外部网络(包括局域网内的其他设备)无法直接访问容器内的服务。容器间的通信则通过 Docker 内部网络(bridge、overlay 等)完成。这种设计天然形成了网络隔离层——即使攻击者获得了局域网访问权限,也无法直接与未映射端口的容器通信,必须通过配置了端口映射的入口服务(如反向代理)才能到达后端应用。
这种设计的优势非常明显:
单一入口,统一管控
所有流量都必须经过 Caddy 这个唯一入口。Caddy 是一个现代化的 Web 服务器和反向代理,以其自动 HTTPS 功能著称。与 Nginx 和 Traefik 等同类工具相比,Caddy 的配置语法极为简洁,且默认为所有托管的站点自动申请和续签 Let's Encrypt TLS 证书。在 Homelab 场景中,Caddy 通常作为所有 Web 服务的统一入口,根据请求的域名(Host Header)将流量路由到不同的后端容器,同时处理 TLS 终止、HTTP/2 升级等工作。
这意味着 TLS 证书、访问日志、身份鉴权、限流等策略都可以集中在反向代理层实现,而不必在每个服务里单独配置。
内网服务零直连
由于 Docker 服务不映射端口,即使有人进入了局域网,也无法绕过 Caddy 直接触碰后端服务。这本质上是一种内网层面的最小暴露原则。
核心矛盾:DNS 解析的错位问题
问题的症结在于 DNS 指向了 LAN IP。
当用户在家时,jellyfin.example.com 解析到内网 IP(例如 192.168.1.10),Caddy 正常工作。但当用户通过 NetBird 远程连接时,设备加入了一个 WireGuard 覆盖网络(Overlay Network),服务器在这个网络中拥有一个 NetBird IP(通常是 100.x.x.x 网段)。
WireGuard 是一种现代 VPN 协议,由 Jason Donenfeld 于 2015 年设计,2020 年正式并入 Linux 内核。相比 OpenVPN 和 IPSec,WireGuard 的代码量仅约 4000 行(前者动辄数十万行),这意味着更小的攻击面和更易于审计的安全性。它使用 Noise 协议框架进行密钥交换,采用 ChaCha20 加密、Poly1305 认证和 BLAKE2s 哈希。覆盖网络(Overlay Network)是在现有物理网络之上构建的虚拟网络层,NetBird/Tailscale 等工具利用 WireGuard 在设备间建立加密隧道,使分布在不同网络中的设备如同处于同一局域网中。100.x.x.x 网段属于 CGNAT(运营商级 NAT)地址空间(100.64.0.0/10),被这类工具借用作为覆盖网络的内部地址。
此时如果继续解析到 192.168.1.10,远程设备根本无法路由到这个内网地址——除非 NetBird 配置了完整的子网路由(Network Routes)。而即便配置了子网路由,把整个家庭内网都暴露给远程设备,也违背了最小权限原则。
用户的三个核心诉求非常清晰:
- 所有服务只能通过 Caddy 访问;
- 内外网使用同一套域名(如
jellyfin.example.com); - 绝不将服务暴露到公网。
方案一:NetBird DNS 覆盖 + Split-Horizon 分离解析
最优雅的思路是让 DNS 在不同网络环境下返回不同的 IP,也就是所谓的 Split-Horizon DNS(分离式解析)。
Split-Horizon DNS(也称 Split-Brain DNS)是一种 DNS 部署策略,即同一个域名在不同的网络环境下返回不同的解析结果。这项技术在企业环境中已使用多年:员工在公司内网时,DNS 将 mail.company.com 解析到内部 IP,而在外部网络访问时解析到公网 IP 或 VPN 网关地址。实现机制通常依赖于 DNS 查询来源的判断——不同的 DNS 服务器(或同一服务器的不同视图)根据请求者所在网络返回对应的记录。
利用 NetBird 内置 DNS 功能
NetBird 提供了内置的 DNS 管理功能,可以在其管理面板中为特定域名配置解析规则。你可以设置一条 Nameserver Group 或自定义 DNS 记录,让 *.example.com 在 NetBird 网络内解析到服务器的 NetBird IP(如 100.64.0.5)。
在 NetBird 场景中,客户端连接到覆盖网络后,其 DNS 查询会被 NetBird 客户端拦截并优先使用覆盖网络内配置的 DNS 规则,从而自动完成解析切换。这一过程对用户完全透明,无需手动切换 DNS 服务器。
这样:
- 在家时,走本地 DNS(Cloudflare 记录),解析到 LAN IP;
- 远程连接 NetBird 后,NetBird 客户端接管 DNS 查询,
jellyfin.example.com解析到 NetBird IP。
由于 Caddy 在 NetBird IP 的 80/443 端口同样监听,请求依然会正确落到反向代理上,服务端配置完全无需改动。
关键细节:TLS 证书处理
因为使用的是同一域名,Caddy 申请的 TLS 证书对内外网都有效,浏览器不会报证书错误。建议使用 DNS-01 挑战(通过 Cloudflare API)来签发证书,这样即使服务器不暴露 80 端口给公网,也能正常自动续签 Let's Encrypt 证书。
Let's Encrypt 提供免费的 TLS 证书,但需要通过「挑战」验证域名所有权。最常见的 HTTP-01 挑战要求在 80 端口提供特定文件,这意味着服务器必须对公网可达。而 DNS-01 挑战则通过在域名的 DNS 记录中添加特定的 TXT 记录来证明控制权,完全不需要服务器暴露任何端口。Caddy 通过集成 Cloudflare 等 DNS 提供商的 API,可以自动完成 TXT 记录的创建和清理,实现证书的全自动申请与续签。这对于不暴露公网端口的 Homelab 场景至关重要——你的服务器可以完全隐藏在防火墙后面,同时仍然持有合法的 TLS 证书。
方案二:为远程访问启用独立子域
如果不想折腾 Split DNS,也可以采用更简单的分域策略:
- 保留
jellyfin.example.com用于家庭内网; - 新增一套指向 NetBird IP 的记录,例如通过一个专门的 DNS 区域或
/etc/hosts(在客户端)指定。
不过这种方式牺牲了「内外网同一域名」的诉求,需要维护两套地址,体验上不如方案一统一。对追求简洁的用户来说,方案一仍是首选。
为什么选择 NetBird 而非传统 VPN
NetBird 基于 WireGuard 构建,属于新一代**零信任组网(Zero Trust Networking)**工具,与 Tailscale 定位类似,但完全开源且支持自托管控制平面。
零信任(Zero Trust)是一种安全架构理念,其核心原则是「永不信任,始终验证」。传统网络安全模型假设内网是安全的(城堡与护城河模型),一旦进入内网便拥有广泛访问权限。零信任模型则要求每次访问都必须经过身份验证和授权,无论请求来自内网还是外网。NetBird 和 Tailscale 等工具将这一理念应用到网络层:每个设备都有独立的加密身份,访问控制列表(ACL)精确定义了哪些设备可以与哪些资源通信,且所有通信都经过端到端加密。这与传统 VPN 的「连上就能访问一切」形成了鲜明对比。
相比传统的 OpenVPN 方案,它的优势在于:
- 点对点直连:基于 NAT 穿透,多数情况下无需公网 IP。NAT 穿透是 P2P 通信中的关键技术,用于在双方都位于 NAT 设备后面时建立直接连接。NetBird 使用的 ICE(Interactive Connectivity Establishment)框架会依次尝试多种穿透策略:首先通过 STUN 服务器发现自己的公网地址并尝试直连,如果失败(如双方都在对称 NAT 后面),则回退到 TURN 中继服务器转发流量。WireGuard 的 UDP 特性使得 NAT 穿透成功率很高——大多数家用路由器的 NAT 对 UDP 较为友好,这意味着即使用户没有公网 IP(如使用运营商 CGNAT),NetBird 也能建立设备间的加密通道;
- 细粒度访问控制:可通过 ACL 精确控制哪些设备能访问哪些资源;
- 免暴露公网:服务器完全不需要开放任何入站端口给互联网。
这正好契合了用户「绝不暴露公网」的核心目标——所有远程流量都在加密的 WireGuard 隧道内传输,攻击者从公网根本探测不到你的服务存在。
落地建议与总结
综合来看,针对这一场景,推荐的实践路径是:
- 保持 Caddy 作为唯一入口不变,服务继续不暴露端口;
- 在 NetBird 管理面板配置 DNS,让相关域名在覆盖网络内解析到服务器的 NetBird IP;
- 使用 Cloudflare DNS-01 方式签发 TLS 证书,保证内外网证书一致;
- 通过 NetBird ACL 限制访问权限,仅授权可信设备访问 80/443。
这套方案既满足了「同一域名、单一入口、零公网暴露」的三重需求,又充分发挥了 WireGuard 组网的安全性。对于正在搭建家庭实验室或小型自托管环境的用户而言,这是一个兼顾安全与体验的成熟范式。
核心要点
相关推荐

Go微服务实战:商城、AI Agent与IM系统集成架构详解
深入解析Go微服务架构下商城、AI Agent与IM即时通讯系统的集成方案,涵盖统一鉴权、gRPC通信、组件化Agent引擎设计、群聊机器人等生产级落地场景,适合希望掌握存量系统集成能力的Go开发者。

X平台推荐算法被曝过滤巴西选举内容,算法透明度再引争议
X平台(原Twitter)被用户发现在For You推荐流中过滤巴西选举相关内容,引发算法透明度与言论自由争议。本文深入分析事件背景、技术实现方式及对平台治理的深层影响。

抗投毒概念锚定:防御AI数据污染的新思路
深入解析Poison-Resistant Concept Anchoring方案,通过签名锚点与有界更新机制防御数据投毒攻击。实验显示该方法可隔离62%投毒数据,同时保持0%正常数据误拦率,为联邦学习和开源模型协作提供可行的安全防御框架。