自托管 Netbird:隐私优先的托管覆盖网络替代方案

发布: (2025年12月30日 GMT+8 16:10)
7 min read
原文: Dev.to

Source: Dev.to

抱歉,我无法直接访问外部链接获取文章内容。请您把需要翻译的文本粘贴在这里,我会按照您的要求将其翻译成简体中文,并保留原始的格式、Markdown 语法以及技术术语。

介绍

作为受监管环境中的基础设施工程师,我们经常面临两难境地:像 TailscaleTwingate 这样的现代覆盖网络解决方案提供了出色的用户体验,但它们的集中式控制平面引发了合规性担忧。对于在严格的数据治理框架(GDPR、BSI IT‑Grundschutz、行业特定法规)下运营的组织而言,自托管的替代方案成为了必需,而非可选。

托管 vs. 自托管 覆盖网络

方面托管(Tailscale / Twingate)自托管(Netbird)
控制平面位置美国 / 云服务提供商本地部署 / 私有 VPS
元数据暴露连接日志、对等 IP 对提供商可见完全隔离
数据主权取决于提供商的基础设施完全控制
供应商锁定专有协调协议开放协议(WireGuard)
审计追踪由提供商控制自行管理

对于公共部门实体或处理敏感数据的组织而言,控制平面的位置会成为合规障碍。

Netbird 架构

┌─────────────────────────────────────────┐
│               Netbird                    │
│  ──► Control Plane (Management Server)   │
│  ──► Data Plane (WireGuard tunnels)      │
└─────────────────────────────────────────┘

关键特性

  • 不通过管理服务器进行流量路由 – 初始协调完成后,节点直接建立 WireGuard 隧道。
  • STUN/TURN 备用 – 仅在直接连接失败时使用(企业防火墙、对称 NAT)。
  • 身份提供商集成 – 使用 OIDC(OpenID Connect)进行认证;兼容 Zitadel、Keycloak、Authentik 等。

标准的 Netbird 部署会将管理 API 和 STUN/TURN 服务暴露到互联网。为减轻暴力破解和资源耗尽的风险,我们集成了 CrowdSec,这是一套协作式入侵防御系统。

  • 自定义日志解析 – Netbird 基于 Go 的日志需要自定义 Grok 模式来检测认证失败。
  • 行为分析 – 漏桶模型用于识别重复的节点登录失败尝试。
  • 防火墙强制 – 直接通过 iptables/nftables 集成,在恶意 IP 到达应用逻辑前进行拦截。
  • 社区情报 – 与 CrowdSec 的全球阻断列表共享威胁数据(可选加入)。

示例场景
检测到在 30 分钟内出现 ≥ 5 次 Netbird 节点认证失败 → 将来源 IP 封禁 48 小时。

堆栈概览

组件角色
Caddy自动 TLS(Let’s Encrypt)的反向代理
Netbird Management对等体协调,策略执行
Zitadel自托管 OIDC 身份提供者(可替换为 Authentik/Keycloak)
Coturn用于 NAT 穿透的 STUN/TURN 服务器(通过显式端口绑定实现网络隔离)
CrowdSec + Firewall Bouncer实时威胁拦截

配置理念

  • 避免使用 network_mode: host 以实现服务隔离。
  • 使用显式的 IPv4/IPv6 端口绑定,而不是通配符监听。
  • 日志轮转限制(每个容器 100 MiB),防止磁盘耗尽。

完整的 Docker‑Compose 配置可在仓库中获取:

➡️ Netbird‑self‑hosted‑stack on GitHub

Docker‑Compose 摘录(Coturn)

coturn:
  image: coturn/coturn:latest
  restart: unless-stopped
  ports:
    - "${PUBLIC_IP}:3478:3478/udp"
    - "${PUBLIC_IP}:3478:3478/tcp"
    - "${PUBLIC_IP}:5349:5349/tcp"
    - "${PUBLIC_IP}:49152-65535:49152-65535/udp"
  volumes:
    - ./config/turnserver.conf:/etc/turnserver.conf:ro

为什么不使用 network_mode: host

  • 将容器保留在 Docker 的桥接网络中。
  • 使 CrowdSec 防火墙规则能够统一地应用于所有服务。
  • 防止在临时端口上意外暴露主机服务。

CrowdSec 集成

Netbird 的 JSON 格式日志与默认的 CrowdSec 解析器不匹配,因此我们提供了自定义 Grok 模式。

解析器示例 – netbird-auth.yaml

# /etc/crowdsec/parsers/s01-parse/netbird-auth.yaml
type: grok-patterns
name: netbird/auth-failure
description: Detect Netbird management authentication failures
grok:
  patterns:
    - '%{TIMESTAMP_ISO8601:timestamp} %{WORD:log_level} %{DATA:component} - Authentication failed for peer %{DATA:peer_id}'
  on_failure:
    - ignore

对应场景 – netbird-brute-force.yaml

# /etc/crowdsec/scenarios/netbird-brute-force.yaml
type: threshold
name: netbird/brute-force
description: Detect multiple authentication failures from the same IP
filter: "evt.Line contains 'Authentication failed'"
group_by: "source_ip"
threshold: 5
time_window: 30m
ban_duration: 48h

完整的解析器和场景配置已包含在仓库中。

生产结果 (Hetzner VPS, Ubuntu 24.04 LTS)

指标数值
负载平均值0.12
内存使用率~12 %
CrowdSec 阻止的 IP 数量~28 000 (CAPI + 本地决策)
SSH 攻击 (端口 2222 + CrowdSec)↓ 从 ≈ 40 /天 降至 0

提示:.env 文件排除在版本控制之外(git add .env → 通过 .gitignore 忽略)。

部署堆栈

使用 Docker Compose(或您偏好的编排工具)启动服务:

docker compose up -d
# or, if using Docker Swarm/Kubernetes, apply the provided manifests

验证所有容器是否正在运行:

docker compose ps

生成 CrowdSec Bouncer 密钥

# Inside the CrowdSec container (or on the host if CrowdSec is installed locally)
docker exec -it crowdsec /usr/local/bin/crowdsec bouncer add
# The command will output a bouncer key, e.g.:
#   Bouncer key: 1234567890abcdef1234567890abcdef12345678

复制生成的密钥。

将密钥添加到 .env

编辑 .env 文件并设置 CROWDSEC_BOUNCER_KEY 变量:

CROWDSEC_BOUNCER_KEY=1234567890abcdef1234567890abcdef12345678

重新启动堆栈以应用更改:

docker compose restart crowdsec

概览

自托管 Netbird 提供一个 生产就绪、合规的覆盖网络,且不牺牲可用性。通过集成 CrowdSec,您可以在基础设施层通过基于日志的威胁检测实现安全加固——无需自定义应用代码。

为什么使用此技术栈?

  • 数据主权: 将所有流量和元数据保留在您受控的环境中。
  • 合规性: 符合严格的公共部门法规(例如 GDPR、NIS2)。
  • 灵活性: 可与现有 CI/CD 流水线和本地硬件协同工作。

免责声明: 这些配置 按原样 提供,仅用于教育目的。在投入生产前,请根据贵组织的安全策略进行审查。

进一步阅读

  • Netbird 文档
  • CrowdSec 文档

祝网络愉快! 🚀

Back to Blog

相关文章

阅读更多 »