文章重点解析 EasyTier 自建方案中的架构角色划分:Caddy 作为反向代理提供安全访问入口,easytier-web-embed 是管理平面,负责 Web UI、API 和机器配置下发;easytier-core 是数据平面,处理 TUN、P2P、NAT 穿透和路由。作者强调 Web 用户与 EasyTier 网络不是同一概念,并解释了 Core 为何使用 host 网络模式而 Web 使用 Bridge 网络,以及如何通过端口映射让 Core 用 localhost 访问 Config Server。理解这些关系是部署成功的关键。

EasyTier 是一个开源、去中心化的异地组网工具,可以将家庭 NAS、云服务器、办公电脑等位于不同网络环境中的设备组成一个虚拟局域网。

它支持 NAT 穿透、P2P 直连、中继转发、子网代理和多种传输协议,不要求所有设备拥有公网 IP,也不依赖中心服务器承载实际业务流量。

本文采用一套完整的自建方案:

                Internet
                   │
                   │ HTTPS :443
                   ▼
             ┌───────────┐
             │   Caddy   │
             └─────┬─────┘
                   │
             Docker Network
                   │
                   ▼
       ┌─────────────────────┐
       │ easytier-web-embed  │
       │ Web / API :11211    │
       │ Config :22020/UDP   │
       └──────────┬──────────┘
                  │
                  │ Config Server
                  ▼
       ┌─────────────────────┐
       │   easytier-core     │
       │ network_mode: host  │
       │ /dev/net/tun        │
       └──────────┬──────────┘
                  │
                  ▼
            EasyTier Network

三个组件的职责分别是:

组件

作用

easytier-core

负责虚拟网络、P2P、NAT 穿透、路由和实际数据传输

easytier-web-embed

提供 Web 控制台、API 和 Core 配置下发

Caddy

提供 HTTPS、域名和 Web 访问控制

可以将 EasyTier Web 理解为管理平面,而 easytier-core 才是真正的数据平面。


一、EasyTier 如何组网

假设有三台机器:

云服务器
家庭 NAS
办公电脑

加入同一个 EasyTier 网络后,可以获得类似:

             EasyTier Network

        10.10.10.1  Gateway
                 │
         ┌───────┴───────┐
         │               │
   10.10.10.2       10.10.10.3
       NAS               PC

之后可以像访问普通局域网设备一样:

ping 10.10.10.2
ssh 10.10.10.1

EasyTier 会优先尝试建立 P2P:

Node A <──────────────> Node B
             P2P

如果由于 NAT、防火墙或运营商网络限制无法建立直连,则可以通过其他 EasyTier 节点进行中继:

Node A
   │
   ▼
 Relay
   │
   ▼
Node B

因此,一个用于帮助节点发现彼此的 Gateway 或 Peer,并不意味着后续全部业务流量都必须经过它。

实际网络建立后可能变成:

           Gateway
          /       \
       Node A     Node B
          \       /
           \_____/
             P2P

这也是 EasyTier 与传统中心化 VPN 在使用方式上的主要区别之一。


二、完整部署:Caddy + EasyTier Web + EasyTier Core

本文使用 Docker Compose 部署 EasyTier Web 和 Core,Caddy 独立运行,并通过一个公共 Docker Network 与 Web 控制台通信。

目录可以组织为:

easytier/
├── docker-compose.yml
├── web/
│   ├── app/
│   └── machine-id
└── core/
    ├── app/
    └── machine-id

caddy/
├── docker-compose.yml
├── Caddyfile
├── data/
└── config/

首先创建公共网络:

docker network create caddy-network

2.1 部署 Caddy

docker-compose.yml:

services:
  caddy:
    image: caddy:2-alpine
    container_name: caddy
    restart: unless-stopped

    ports:
      - "80:80"
      - "443:443"

    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - ./data:/data
      - ./config:/config

    networks:
      - caddy-network

networks:
  caddy-network:
    external: true

Caddy 将作为 EasyTier Web 的 HTTPS 入口,也可以同时代理服务器上的其他服务。


2.2 部署 EasyTier Web 和 Core

EasyTier 使用一个 Compose 同时运行 Web 和 Core:

services:
  easytier-web:
    image: easytier/easytier:latest
    container_name: easytier-web-embed
    hostname: easytier-web
    restart: unless-stopped

    ports:
      - "22020:22020/udp"

    environment:
      - TZ=Asia/Shanghai

    volumes:
      - ./web/app:/app
      - ./web/machine-id:/etc/machine-id:ro

    entrypoint: easytier-web-embed

    command: >
      --api-host https://yourdomain.com/

    networks:
      - caddy-network


  easytier-core:
    image: easytier/easytier:latest
    hostname: easytier-core
    restart: unless-stopped

    network_mode: host

    privileged: true

    cap_add:
      - NET_ADMIN
      - NET_RAW

    environment:
      - TZ=Asia/Shanghai

    devices:
      - /dev/net/tun:/dev/net/tun

    volumes:
      - ./core/app:/app
      - ./core/machine-id:/etc/machine-id:ro

    command: >
      --config-server udp://127.0.0.1:22020/srvkey
      --hostname gateway-aliyun


networks:
  caddy-network:
    external: true

启动:

docker compose up -d

查看运行状态:

docker compose ps

整个容器网络关系为:

                   Docker Host

      caddy-network
 ┌──────────────────────────────┐
 │                              │
 │ Caddy ───── EasyTier Web     │
 │ :443          :11211         │
 │                  │           │
 └──────────────────┼───────────┘
                    │ :22020
                    ▼
             Host Network
                    │
             EasyTier Core
                    │
                  TUN
                    │
                    ▼
             EasyTier Network


2.3 配置 Caddy

Caddyfile:

https://yourdomain.com {
    handle /api/v1/auth/captcha {
        respond 404
    }

    handle /api/v1/auth/register {
        respond 404
    }

    handle {
        reverse_proxy http://easytier-web:11211
    }
}

正常的 Web 请求路径为:

Browser
   │
   │ HTTPS
   ▼
Caddy
   │
   │ Docker Network
   ▼
easytier-web:11211

因此 Compose 中不需要将:

11211

映射到宿主机。

公网只访问:

443

而 Caddy 通过 caddy-network 直接访问 EasyTier Web。

Docker 会为同一网络中的容器提供 DNS,因此:

easytier-web

可以直接作为反向代理目标。


三、理解这套配置

部署完成后,有几个地方值得单独说明,因为它们决定了整个架构为什么能够工作。

3.1 Web 和 Core 为什么使用不同网络模式

EasyTier Web 本质上是普通 Web/API 服务,因此运行在 Docker Bridge Network 即可:

Caddy
   │
Docker Bridge
   │
EasyTier Web

Core 则需要处理:

  • TUN 虚拟网卡;

  • 系统路由;

  • NAT;

  • TCP / UDP Listener;

  • NAT Traversal;

  • P2P;

  • Relay。

因此使用:

network_mode: host

让 Core 直接进入宿主机网络栈:

EasyTier Core
      │
      ▼
Host Network
      │
      ├── eth0
      ├── lo
      ├── routes
      └── TUN

这样可以避免额外经过一层 Docker Bridge。


3.2 Core 为什么连接 127.0.0.1:22020

Core 的配置:

--config-server udp://127.0.0.1:22020/srvkey

第一次看到时可能会产生疑问,因为 Web 和 Core 并不是同一个容器。

关键在于 Core 使用:

network_mode: host

所以 Core 容器中的:

127.0.0.1

实际上就是宿主机。

Web 则通过:

ports:
  - "22020:22020/udp"

把 Config Server 映射到了宿主机。

完整路径为:

EasyTier Core
     │
     │ udp://127.0.0.1:22020
     ▼
Host :22020/UDP
     │
     ▼
Docker Port Mapping
     │
     ▼
EasyTier Web Config Server

因此 Web 可以继续运行在 Bridge Network,而 Core 仍然可以通过 localhost 访问它。


3.3 Web 用户与 EasyTier 网络不是一个概念

例如:

--config-server udp://127.0.0.1:22020/srvkey

最后的:

srvkey

代表 Web Console 中管理该机器的用户。

而真正决定 Core 加入哪个 EasyTier 网络的是:

network-name
network-secret

两者关系可以理解为:

Web Account
    │
    ▼
Machine
    │
    ▼
EasyTier Core
    │
    ▼
EasyTier Network
    │
    ├── network-name
    └── network-secret

Web Console 管理的是“机器和配置”,EasyTier Network 描述的则是“这些机器如何组成虚拟网络”。


3.4 --api-host

Web 使用:

--api-host https://yourdomain.com/

因为浏览器实际访问的是:

https://yourdomain.com

而不是 Docker 内部地址:

http://easytier-web:11211

注册、验证码以及部分前端 API 请求都会使用这个地址。

反向代理场景下,应让 api-host 与用户实际访问 Web Console 的外部地址对应。


3.5 TUN、Capabilities 与 machine-id

Core 映射:

devices:
  - /dev/net/tun:/dev/net/tun

用于访问 Linux TUN 设备。

可以在宿主机检查:

ls -l /dev/net/tun

如果没有加载:

sudo modprobe tun

同时提供:

cap_add:
  - NET_ADMIN
  - NET_RAW

用于网络接口、路由和底层网络操作。

部分环境还可能使用:

privileged: true

如果运行环境仅依靠:

NET_ADMIN
NET_RAW
/dev/net/tun

即可正常工作,也可以减少额外权限。

另外:

./core/machine-id:/etc/machine-id:ro

用于保持机器身份稳定。

如果容器重建后 machine-id 发生变化:

Old Container → Machine A

Recreate

New Container → Machine B

Web Console 可能将其识别为新机器。

持久化后:

Old Container ─┐
               ├── Machine ID X
New Container ─┘

同一台机器应保持稳定的 machine-id,不同服务器则应使用不同值。


四、组网、Peer 与高级网络能力

Core 成功连接 Web Console 后,就可以通过 Web 页面配置实际的 EasyTier 网络。

4.1 network-name 与 network-secret

一个基本 EasyTier 网络需要:

network-name
network-secret

例如:

network-name:
home-network

network-secret:
<random-secret>

多个节点使用相同的:

network-name
+
network-secret

即可加入同一个逻辑网络。

密钥建议使用随机值:

openssl rand -base64 32

不要使用:

123456
password
easytier
home

之类的简单字符串。


4.2 Peer 与 P2P

节点需要先找到网络中的其他 EasyTier 节点。

例如:

Node A
   │
   │ Peer
   ▼
Gateway

可以配置:

tcp://gateway.example.com:11010

作为初始 Peer。

但 Peer 的作用主要是帮助建立网络连接,并不意味着所有流量永久经过它。

网络形成后:

Node A ─── Gateway ─── Node B

如果 NAT 条件允许,EasyTier 会继续尝试:

Node A <────────────> Node B
           P2P

因此公网 Gateway 可以同时承担:

  • 初始 Peer;

  • 节点发现入口;

  • P2P 失败时的 Relay。

而成功直连的节点则不需要让正常数据流量经过 Gateway。


4.3 子网代理

EasyTier 不仅能连接安装了 Core 的机器,还可以通过一个 Core 访问它背后的整个局域网。

例如:

Remote PC
    │
    │ EasyTier
    ▼
 Gateway
    │
    ├── NAS       192.168.10.10
    ├── Server    192.168.10.20
    └── Camera    192.168.10.30

Gateway 可以发布:

192.168.10.0/24

对应:

--proxy-networks 192.168.10.0/24

这样不需要在 NAS、摄像头等所有设备上安装 EasyTier。

如果两个地点恰好都使用:

192.168.1.0/24

还可以使用网段映射解决地址冲突,例如将远端:

192.168.1.0/24

映射为:

10.10.1.0/24

再通过映射后的地址访问。


五、安全与其他部署方式

5.1 Web 管理面安全

本文的 Web 入口为:

Internet
   │
   ▼
Caddy
   │
   ▼
EasyTier Web

Web 侧可以遵循几个基本原则:

  • 只通过 HTTPS 访问;

  • 不直接暴露 11211;

  • 使用高强度登录密码;

  • 创建完成用户后关闭不需要的公开注册入口;

  • 定期更新 EasyTier;

  • 必要时增加 IP ACL、Cloudflare Access 或其他认证层。

本文 Caddy 中:

handle /api/v1/auth/captcha {
    respond 404
}

handle /api/v1/auth/register {
    respond 404
}

就是在完成账户创建后,直接从反向代理层关闭注册接口。

请求会在 Caddy 结束:

Register Request
      │
      ▼
    Caddy
      │
      X
    HTTP 404

如果以后需要重新注册用户,需要同时恢复 CAPTCHA 与 Register 接口。


5.2 EasyTier 网络安全

Web 登录安全和 EasyTier 网络本身的安全是两个不同层次。

网络侧至少需要关注:

network-secret
Secure Mode
Private Mode
Relay

支持的版本中可以启用:

--secure-mode

进一步增强节点认证、端到端加密、防重放和会话密钥管理。

如果使用第三方或公共 Relay,还可以通过 Peer 公钥锁定验证所连接的 Relay 身份。

如果某个节点只用于自己的 EasyTier 网络,可以启用:

--private-mode true

限制其他网络使用该节点。

同时还可以使用 Relay 白名单限制允许转发的网络,避免公网节点承担非预期第三方流量。


5.3 不使用 Compose 时

虽然本文以 Compose 为主,但整体架构并不依赖 Docker Compose。

使用普通 Docker 时仍然是:

Docker Caddy
      │
Docker EasyTier Web
      │
Docker EasyTier Core

只需要分别通过 docker run 启动。

如果完全不用 Docker,也可以在 Linux 上运行:

Linux
├── Caddy
├── easytier-web-embed
└── easytier-core

此时连接关系变成:

Internet
   │
   ▼
Caddy :443
   │
   ▼
127.0.0.1:11211
   │
   ▼
EasyTier Web
   │
   │ 127.0.0.1:22020
   ▼
EasyTier Core

Core 可以注册为 systemd 服务:

[Unit]
Description=EasyTier Core
After=network-online.target
Wants=network-online.target

[Service]
Type=simple

ExecStart=/opt/easytier/easytier-core \
    --config-server udp://127.0.0.1:22020/srvkey \
    --hostname gateway

Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

Web 同样可以:

[Unit]
Description=EasyTier Web Console
After=network-online.target
Wants=network-online.target

[Service]
Type=simple

ExecStart=/opt/easytier/easytier-web-embed \
    --api-host https://yourdomain.com/

Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

Caddy 则继续使用相同的 Caddyfile,只需要把:

easytier-web:11211

改成:

127.0.0.1:11211

即可。

因此无论采用:

Docker Compose
Docker
systemd

整体逻辑始终没有变化:

Caddy
   │
EasyTier Web
   │
EasyTier Core
   │
EasyTier Network


六、运维、常见问题与总结

常用命令

查看服务:

docker compose ps

查看 Core 日志:

docker compose logs -f easytier-core

查看 Web 日志:

docker compose logs -f easytier-web

查看 EasyTier 节点:

docker compose exec easytier-core easytier-cli node

查看 Peer:

docker compose exec easytier-core easytier-cli peer

检查 TUN:

ls -l /dev/net/tun

检查 Config Server:

ss -lunp | grep 22020

检查其他监听:

ss -lntup


Core 出现 TunError

先检查:

ls -l /dev/net/tun

如果没有:

sudo modprobe tun

然后确认 Compose 中存在:

devices:
  - /dev/net/tun:/dev/net/tun

以及:

cap_add:
  - NET_ADMIN
  - NET_RAW


Web Console 看不到 Core

首先检查:

--config-server

例如:

udp://127.0.0.1:22020/srvkey

再查看:

docker compose logs easytier-web

以及:

ss -lunp | grep 22020


为什么不开放 11211?

因为 Web 的公网访问路径是:

Browser
   │
 HTTPS
   ▼
Caddy
   │
 Docker Network
   ▼
EasyTier Web :11211

11211 只需要在 Docker 内部网络中可达。


为什么 Core 使用 localhost 访问 Web?

因为 Core 使用:

network_mode: host

而 Web 的:

22020/UDP

映射到了宿主机。

所以:

127.0.0.1:22020

正好就是 Web Config Server 的宿主机入口。


Docker 重建后为什么出现新机器?

重点检查:

machine-id

Web Console 需要稳定的 machine-id 来识别同一台 Core。

容器可以重建,但:

machine-id

不能随之随机变化。


可以连接 EasyTier,但节点无法 P2P

先检查:

easytier-cli node
easytier-cli peer

如果 Relay 通信正常但始终没有 P2P,一般继续检查:

  • NAT 类型;

  • 防火墙;

  • UDP 可达性;

  • IPv6;

  • 公网端口;

  • 运营商网络限制。

P2P 失败并不一定表示 EasyTier 网络异常,只可能意味着当前流量需要经过 Relay。


总结

本文部署最终形成三个层次:

┌───────────────────────────────┐
│            Caddy              │
│       HTTPS / Web Access      │
└──────────────┬────────────────┘
               │
               ▼
┌───────────────────────────────┐
│      easytier-web-embed       │
│       Management Plane        │
└──────────────┬────────────────┘
               │
               ▼
┌───────────────────────────────┐
│        easytier-core          │
│          Data Plane           │
└──────────────┬────────────────┘
               │
               ▼
         EasyTier Network

其中 Caddy 负责:

HTTPS
TLS
域名
访问控制

EasyTier Web 负责:

Web UI
API
机器管理
配置下发

EasyTier Core 负责:

TUN
P2P
NAT Traversal
Relay
Routing
Subnet Proxy

在此基础上,还可以根据网络规模进一步增加:

Secure Mode
Private Mode
Subnet Proxy
Relay Control
Peer Public-Key Pinning

最终形成一个既有集中管理入口,又保持 EasyTier 去中心化数据通信特性的私有异地网络。