diff --git a/.vitepress/config/cn.ts b/.vitepress/config/cn.ts index 11497ee..ec2656f 100644 --- a/.vitepress/config/cn.ts +++ b/.vitepress/config/cn.ts @@ -1,4 +1,3 @@ -import fs from 'node:fs' import { defineConfig } from 'vitepress' export const cn = defineConfig({ @@ -29,6 +28,7 @@ export const cn = defineConfig({ { text: '子网代理(点对网)', link: '/guide/network/point-to-networking' }, { text: '带宽延迟优化(KCP 代理)', link: '/guide/network/kcp-proxy' }, { text: '高级功能', collapsed: true, items: [ + { text: 'Secure Mode(安全模式)', link: '/guide/network/secure-mode' }, { text: '网对网', link: '/guide/network/network-to-network' }, { text: '无 TUN 模式(免 Root 权限)', link: '/guide/network/no-root' }, { text: 'SOCKS5', link: '/guide/network/socks5' }, diff --git a/en/guide/network/secure-mode.md b/en/guide/network/secure-mode.md new file mode 100644 index 0000000..a6458ae --- /dev/null +++ b/en/guide/network/secure-mode.md @@ -0,0 +1,203 @@ +# Secure Mode + +Secure Mode is an enhanced security mechanism in EasyTier. Compared to the legacy mode, it improves security in several areas: + +1. **End-to-End Encryption (E2EE)**: Any two nodes independently negotiate encryption keys. Even if traffic passes through a third-party shared node or public relay, the relay server cannot decrypt your data. In the legacy mode, all nodes in the same network rely on a shared `network_secret` for encryption; once the password is leaked, traffic across the entire network may be compromised. +2. **Safer Handshake and Key Management**: The handshake process uses the Noise protocol framework (the same standard used by modern VPNs like WireGuard) and includes built-in replay protection. Session keys are automatically rotated, so even if a key is compromised at a certain point in time, an attacker cannot retroactively decrypt historical traffic or replay captured packets to impersonate a legitimate node. +3. **Shared Node Identity Verification**: You can pin a shared node's public key to ensure you are connecting to the intended server and not a man-in-the-middle impostor. +4. **Temporary Credentials and Tiered Authorization**: Admin nodes can issue short-term credentials for visitors or temporary devices, restricting their permissions (e.g., prohibiting relay or subnet proxy). Credentials automatically expire or can be revoked without spreading the main password. + +## What Problems Does It Solve + +In the legacy mode, all nodes that know the `network_secret` are fully equal, which causes several practical issues: + +- **Untrusted shared nodes**: When networking through a third-party shared node or public relay, you cannot confirm that you are connecting to the target server, creating a risk of man-in-the-middle hijacking. +- **No fine-grained permissions**: Temporary or guest devices must also obtain the main `network_secret`. Once leaked, the only remedy is to change the password for the entire network. +- **Difficult temporary authorization**: There is no way to grant a device a short-term permission that automatically expires after a few days. + +Secure Mode separates these scenarios: + +- Regular nodes in the same network still use `network_secret` for the strongest authentication. +- Shared nodes can prove "I am the server you want to connect to" through a fixed public key. +- Temporary nodes can join the network with a short-term credential without touching the main password. +- Credentials support TTL, manual revocation, and automatic synchronization across the entire network. + +## Upgrade Notes + +This is where mistakes are most commonly made. Please read this section before proceeding: + +1. **Upgrade the server first, then the client**. A server with Secure Mode enabled can accept connections from legacy clients; however, a client with Secure Mode enabled cannot connect to a legacy server. +2. **The credential feature requires the entire chain to support Secure Mode**. Admin nodes, temporary nodes, and regular nodes that participate in propagating trust information all need to be upgraded to a version that supports Secure Mode. +3. **Web console / web client**: The web link also integrates with the secure tunnel. It is recommended to use the latest official build to avoid compatibility issues with early versions. + +## Scenario 1: Enabling Secure Mode Between Regular Nodes + +This is the simplest use case. All regular nodes keep their original `network_name` and `network_secret`, and add `--secure-mode`: + +```sh +easytier-core -d \ + --network-name office \ + --network-secret 'replace-with-a-strong-secret' \ + --secure-mode \ + -p tcp://node-a.example.com:11010 +``` + +Effect: Nodes first establish an encrypted channel and then verify each other's identity using the shared `network_secret`. This is suitable for scenarios where all nodes belong to the same trust domain and you simply want to upgrade transport security. + +## Scenario 2: Connecting Through a Shared Node / Public Relay + +If you connect through a shared node or public relay in your network, **enabling `--secure-mode` alone only guarantees traffic encryption; it does not ensure you are connecting to the correct shared node**. To prevent connecting to the wrong server or being replaced by a man-in-the-middle, you must configure a fixed public key for the shared node and pin that public key on the client. + +### Shared Node Side: Fix the Public Key + +The shared node must explicitly save a fixed private key. Otherwise, EasyTier will randomly generate a new key on each startup, causing the client's pin to become invalid. + +```sh +easytier-core \ + --network-name public-relay \ + --secure-mode \ + --local-private-key '' \ + -l tcp://0.0.0.0:11010 \ + -l udp://0.0.0.0:11010 +``` + +- `--local-public-key` can usually be omitted; the program will automatically derive it from the private key. +- The shared node should distribute its corresponding public key to clients through a trusted channel (e.g., private message, internal documentation). + +### Client Side: Pin the Shared Node's Public Key + +It is recommended to specify `peer_public_key` in the configuration file: + +```toml +[network_identity] +network_name = "office" +network_secret = "replace-with-a-strong-secret" + +[secure_mode] +enabled = true + +[[peer]] +uri = "tcp://relay.example.com:11010" +peer_public_key = "" +``` + +Effect: Even if the shared node does not know your business network password, the client can confirm it has connected to the correct server. Without pinning the public key, you only get an "encrypted but unauthenticated" connection, which significantly reduces security. + +::: warning Important +If you connect through a shared node or public relay, **be sure to configure `peer_public_key` pinning**. Enabling `--secure-mode` alone does not mean "the shared node's identity has been verified". +::: + +## Scenario 3: Issuing Network Credentials for Temporary Devices + +This is one of the most practical features of Secure Mode. An admin node can issue short-term credentials for the network, allowing temporary devices to join using only the credential without knowing the main `network_secret`. + +### 1. Start the Admin Node + +The admin node itself is still a regular node and must retain `network_secret`. It is recommended to configure a credential persistence file; otherwise, issued credentials will be lost after a restart: + +```sh +easytier-core -d \ + --network-name office \ + --network-secret 'replace-with-a-strong-secret' \ + --secure-mode \ + --credential-file /var/lib/easytier/credentials.json \ + -p tcp://node-a.example.com:11010 +``` + +### 2. Generate a Credential + +```sh +easytier-cli credential generate --ttl 86400 +``` + +A more complete example (with permission restrictions): + +```sh +easytier-cli credential generate \ + --ttl 86400 \ + --groups guest \ + --allow-relay \ + --allowed-proxy-cidrs 192.168.10.0/24 +``` + +After generation, two key fields are returned: + +- `credential_id`: The management ID of the credential, used for subsequent listing and revocation. +- `credential_secret`: The private key that the temporary device actually needs. **This is equivalent to a highly sensitive password; please transmit it securely**. + +### 3. Temporary Node Joins the Network + +```sh +easytier-core -d \ + --network-name office \ + --secure-mode \ + --credential '' \ + -p tcp://admin.example.com:11010 +``` + +- `--credential` implicitly enables Secure Mode. **You do not need to provide `--network-secret`**. + +### 4. List and Revoke Credentials + +List currently valid credentials: + +```sh +easytier-cli credential list +``` + +Manually revoke a credential: + +```sh +easytier-cli credential revoke +``` + +Behavioral characteristics: + +- Credentials automatically expire after the `ttl` ends. +- After revocation, the trust list is synchronized through route propagation, and **already connected temporary nodes will be automatically removed**. +- It is best to issue one credential per device to facilitate tracking and revocation. + +### Credential Permission Restrictions + +Constraints can be attached when generating credentials to implement the principle of least privilege: + +| Parameter | Description | Default | +|-----------|-------------|---------| +| `groups` | Assign ACL groups to the node for tiered authorization with ACL policies | None | +| `allow_relay` | Whether the node is allowed to participate in relaying/forwarding traffic for other nodes | `false` | +| `allowed_proxy_cidrs` | Restrict which subnet proxy CIDRs the node can advertise | Empty (no proxy CIDRs allowed) | + +By default, temporary nodes **cannot** relay traffic and **cannot** proxy subnets. These must be explicitly enabled via parameters. + +## Configuration Parameters Quick Reference + +| Parameter | Description | +|-----------|-------------| +| `--secure-mode` | Enable Secure Mode | +| `--local-private-key` | Local static private key (base64). Shared nodes should explicitly specify this to avoid public key changes after restart | +| `--local-public-key` | Local static public key (base64); usually can be omitted, automatically derived from the private key | +| `--credential` | Credential private key used when joining as a temporary node | +| `--credential-file` | File path for the admin node to persist the credential database | + +Complete configuration file example: + +```toml +credential_file = "/var/lib/easytier/credentials.json" + +[network_identity] +network_name = "office" +network_secret = "replace-with-a-strong-secret" + +[secure_mode] +enabled = true +local_private_key = "" +``` + +## Migration Recommendations + +If you plan to migrate an existing network to Secure Mode, it is recommended to proceed in the following order: + +1. First upgrade all shared nodes, entry nodes, and admin nodes to a version that supports Secure Mode. +2. Enable `--secure-mode` between regular nodes while keeping the original `network_secret` unchanged. +3. Fix `local_private_key` for shared nodes and gradually configure `peer_public_key` pinning for clients. +4. Introduce the credential mechanism when there is a need for visitor or temporary devices, avoiding further spreading of the main password. diff --git a/guide/network/configurations.md b/guide/network/configurations.md index 4e18867..dbf785d 100644 --- a/guide/network/configurations.md +++ b/guide/network/configurations.md @@ -19,16 +19,21 @@ ### 网络设置 -| 参数 | 说明 | -| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | -| `--network-name` | 用于标识此VPN网络的网络名称 [env: ET_NETWORK_NAME=] | -| `--network-secret` | 网络密钥,用于验证此节点属于VPN网络 [env: ET_NETWORK_SECRET=] | -| `-i, --ipv4` | 此VPN节点的IPv4地址。如果为空,则此节点将仅转发数据包,不会创建TUN设备 [env: ET_IPV4=] | -| `--ipv6` | 此VPN节点的IPv6地址,可与IPv4配合使用以实现双栈运行 [env: ET_IPV6=] | -| `-d, --dhcp` | 由Easytier自动确定并设置IP地址,默认从10.0.0.1开始。警告:在使用DHCP时,如果网络中出现IP冲突,IP将自动更改。 [env: ET_DHCP=] | -| `-p, --peers` | 最初要连接的对等节点 [env: ET_PEERS=] | -| `-e, --external-node` | 使用公共共享节点来发现对等节点 [env: ET_EXTERNAL_NODE=] | -| `-n, --proxy-networks` | 将本地网络导出到VPN中的其他对等节点,例如:`10.0.0.0/24`。支持映射到其他CIDR,例如:`10.0.0.0/24->192.168.0.0/24` [env: ET_PROXY_NETWORKS=] | +| 参数 | 说明 | +| ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `--network-name` | 用于标识此VPN网络的网络名称 [env: ET_NETWORK_NAME=] | +| `--network-secret` | 网络密钥,用于验证此节点属于VPN网络 [env: ET_NETWORK_SECRET=] | +| `--secure-mode` | 启用 secure mode。开启后,节点会使用新的 Noise 安全握手与认证路径。默认值为 false,详见 [Secure Mode(安全模式)](/guide/network/secure-mode) [env: ET_SECURE_MODE=] | +| `--local-private-key` | secure mode 使用的本地静态私钥(base64)。未提供时会随机生成,仅适合当前运行实例;共享节点建议显式固定该值。 [env: ET_LOCAL_PRIVATE_KEY=] | +| `--local-public-key` | secure mode 使用的本地静态公钥(base64)。通常可省略,由私钥自动派生。 [env: ET_LOCAL_PUBLIC_KEY=] | +| `--credential` | 临时凭据私钥(base64)。用于不分发 `network_secret` 的临时节点接入;指定后会隐式启用 secure mode。 [env: ET_CREDENTIAL=] | +| `--credential-file` | 管理节点 credential 持久化文件路径。用于在重启后保留已生成的凭据。 [env: ET_CREDENTIAL_FILE=] | +| `-i, --ipv4` | 此VPN节点的IPv4地址。如果为空,则此节点将仅转发数据包,不会创建TUN设备 [env: ET_IPV4=] | +| `--ipv6` | 此VPN节点的IPv6地址,可与IPv4配合使用以实现双栈运行 [env: ET_IPV6=] | +| `-d, --dhcp` | 由Easytier自动确定并设置IP地址,默认从10.0.0.1开始。警告:在使用DHCP时,如果网络中出现IP冲突,IP将自动更改。 [env: ET_DHCP=] | +| `-p, --peers` | 最初要连接的对等节点 [env: ET_PEERS=] | +| `-e, --external-node` | 使用公共共享节点来发现对等节点 [env: ET_EXTERNAL_NODE=] | +| `-n, --proxy-networks` | 将本地网络导出到VPN中的其他对等节点,例如:`10.0.0.0/24`。支持映射到其他CIDR,例如:`10.0.0.0/24->192.168.0.0/24` [env: ET_PROXY_NETWORKS=] | ### RPC 设置 diff --git a/guide/network/secure-mode.md b/guide/network/secure-mode.md new file mode 100644 index 0000000..6a789d8 --- /dev/null +++ b/guide/network/secure-mode.md @@ -0,0 +1,203 @@ +# 安全模式(Secure Mode) + +安全模式是 EasyTier 的增强安全机制。相比旧模式,它在多个层面做了加强: + +1. **端到端加密(E2EE)**:任意两个节点之间会独立协商加密密钥,即使流量经过第三方共享节点或公网中继,中继服务器也无法解密你的数据。旧模式下,同一个网络内的节点靠共享的 `network_secret` 进行通信加密,一旦密码泄露,整个网络的流量都可能被窃听。 +2. **更安全的握手与密钥管理**:握手流程采用 Noise 协议框架(WireGuard 等现代 VPN 也在使用的标准),并内置防重放保护。会话密钥支持自动轮换,即使某一时刻的密钥被泄露,攻击者也无法回溯解密历史流量,或者截获旧数据包重复发送来冒充合法节点。 +3. **共享节点身份验证**:你可以锁定共享节点的公钥,确保自己连到的就是目标服务器,而不是被中间人劫持的假冒节点。 +4. **临时凭据与分级授权**:管理节点可以为访客或临时设备签发短期凭据,限制其权限(如禁止中继、禁止代理子网),凭据到期或撤销后自动失效,无需扩散主密码。 + +## 它能解决什么问题 + +在旧模式下,所有知道 `network_secret` 的节点都是完全平等的,这会带来几个实际困扰: + +- **共享节点不可信**:你通过第三方共享节点或公网中继组网时,无法确认自己连到的就是目标服务器,存在被中间人劫持的风险。 +- **权限无法细分**:临时设备、访客设备也必须拿到主 `network_secret`,一旦泄露只能整体换密码。 +- **临时授权困难**:没法给某台设备发一个"几天后自动失效"的短期权限。 + +安全模式把这些场景拆开处理: + +- 同网正式节点仍用 `network_secret` 做最强认证。 +- 共享节点可以通过固定公钥证明"我就是你要连的那台服务器"。 +- 临时节点可以只拿一份短期凭据加入网络,不必接触主密码。 +- 凭据支持设置有效期、手动撤销,并会自动同步到全网生效。 + +## 升级注意事项 + +这是最容易踩坑的地方,请先读完再操作: + +1. **先升级服务端,再升级客户端**。开启安全模式的服务端可以接受旧客户端连接;但反过来,开启安全模式的客户端连不上旧服务端。 +2. **凭据功能要求整条链路都支持安全模式**。管理节点、临时节点、以及参与传播可信信息的正式节点,都需要升级到支持安全模式的版本。 +3. **Web 控制台/网页客户端**:网页链路也接入了安全隧道,建议使用官方最新版本构建,避免早期版本的兼容性问题。 + +## 场景一:正式节点之间启用安全模式 + +这是最简单的用法。所有正式节点保留原来的 `network_name` 和 `network_secret`,再加一个 `--secure-mode` 即可: + +```sh +easytier-core -d \ + --network-name office \ + --network-secret 'replace-with-a-strong-secret' \ + --secure-mode \ + -p tcp://node-a.example.com:11010 +``` + +效果:节点之间会先建立加密通道,再用共同的 `network_secret` 确认彼此身份。适合"所有节点都属同一信任域,只想升级传输安全性"的场景。 + +## 场景二:通过共享节点/公网中继接入 + +如果你通过网络中的共享节点或公网中继接入,**只开 `--secure-mode` 只能保证流量加密,并不能确保你连到的就是正确的共享节点**。要防止连错服务器或被中间人替换,必须给共享节点配置固定公钥,并在客户端"锁定"(pin)这个公钥。 + +### 共享节点侧:固定公钥 + +共享节点必须显式保存一份固定的私钥。如果不提供,EasyTier 每次启动都会随机生成新密钥,导致客户端的锁定失效。 + +```sh +easytier-core \ + --network-name public-relay \ + --secure-mode \ + --local-private-key '' \ + -l tcp://0.0.0.0:11010 \ + -l udp://0.0.0.0:11010 +``` + +- `--local-public-key` 通常可以省略,程序会自动由私钥派生。 +- 共享节点应把对应的公钥通过可信渠道(如私聊、内部文档)发给客户端。 + +### 客户端侧:锁定共享节点公钥 + +建议在配置文件里指定 `peer_public_key`: + +```toml +[network_identity] +network_name = "office" +network_secret = "replace-with-a-strong-secret" + +[secure_mode] +enabled = true + +[[peer]] +uri = "tcp://relay.example.com:11010" +peer_public_key = "" +``` + +效果:即使共享节点不知道你的业务网络密码,客户端也能确认自己连到了正确的服务器。如果没有锁定公钥,只能得到"已加密但未确认身份"的连接,安全性大打折扣。 + +::: warning 重要 +如果你是通过共享节点或公网中继接入,**务必配置 `peer_public_key` 做锁定**。单独打开 `--secure-mode` 不等于"已经确认共享节点身份"。 +::: + +## 场景三:给临时设备发放入网凭据 + +这是安全模式最实用的功能之一。管理节点可以为网络签发短期凭据,临时设备只凭凭据加入,不需要知道主 `network_secret`。 + +### 1. 启动管理节点 + +管理节点本身是正式节点,仍需保留 `network_secret`。建议配置凭据持久化文件,否则重启后已签发的凭据会全部失效: + +```sh +easytier-core -d \ + --network-name office \ + --network-secret 'replace-with-a-strong-secret' \ + --secure-mode \ + --credential-file /var/lib/easytier/credentials.json \ + -p tcp://node-a.example.com:11010 +``` + +### 2. 生成凭据 + +```sh +easytier-cli credential generate --ttl 86400 +``` + +更完整的例子(限制权限): + +```sh +easytier-cli credential generate \ + --ttl 86400 \ + --groups guest \ + --allow-relay \ + --allowed-proxy-cidrs 192.168.10.0/24 +``` + +生成后会返回两个关键字段: + +- `credential_id`:凭据的管理 ID,用于后续查看和撤销。 +- `credential_secret`:临时设备真正需要拿的私钥,**等价于高敏感度密码,请妥善传递**。 + +### 3. 临时节点加入网络 + +```sh +easytier-core -d \ + --network-name office \ + --secure-mode \ + --credential '' \ + -p tcp://admin.example.com:11010 +``` + +- `--credential` 会隐式开启安全模式,**不需要再提供 `--network-secret`**。 + +### 4. 查看与撤销凭据 + +列出当前有效的凭据: + +```sh +easytier-cli credential list +``` + +手动撤销某条凭据: + +```sh +easytier-cli credential revoke +``` + +行为特点: + +- `ttl` 到期后凭据自动失效。 +- 撤销后,可信列表会随路由同步传播,**已接入的临时节点会被自动移除**。 +- 一份凭据最好只发给一台设备,便于追踪和撤销。 + +### 凭据的权限限制 + +生成凭据时可以附加约束,实现最小权限原则: + +| 参数 | 说明 | 默认值 | +|------|------|--------| +| `groups` | 给该节点附加 ACL 分组,用于配合 ACL 策略做分级授权 | 无 | +| `allow_relay` | 是否允许该节点参与中继/转发其他节点的流量 | `false` | +| `allowed_proxy_cidrs` | 限制该节点能对外宣告哪些子网代理网段 | 空(不允许宣告任何代理网段) | + +默认情况下,临时节点**不能**中继流量,也**不能**代理子网,需要通过参数显式放开。 + +## 配置参数速查 + +| 参数 | 说明 | +|------|------| +| `--secure-mode` | 开启安全模式 | +| `--local-private-key` | 本地固定私钥(base64)。共享节点建议显式指定,避免重启后公钥变化 | +| `--local-public-key` | 本地固定公钥(base64),通常可省略,由私钥自动派生 | +| `--credential` | 作为临时节点加入时使用的凭据私钥 | +| `--credential-file` | 管理节点持久化凭据数据库的文件路径 | + +完整的配置文件示例: + +```toml +credential_file = "/var/lib/easytier/credentials.json" + +[network_identity] +network_name = "office" +network_secret = "replace-with-a-strong-secret" + +[secure_mode] +enabled = true +local_private_key = "" +``` + +## 迁移建议 + +如果你准备把已有网络迁移到安全模式,建议按以下顺序操作: + +1. 先升级所有共享节点、入口节点、管理节点到支持安全模式的版本。 +2. 在正式节点之间开启 `--secure-mode`,保持原有 `network_secret` 不变。 +3. 为共享节点固定 `local_private_key`,并逐步给客户端配置 `peer_public_key` 锁定。 +4. 有访客/临时设备需求时,再引入凭据机制,避免继续扩散主密码。