数据包的路径
本页跟随一个连接穿过节点,从它到达节点的那一刻,到它离开前往互联网的那一刻。当你需要知道某项设置在哪里生效时,它很有用:哪一层读取证书、在哪里识别用户、限制和计数器位于何处。
点击图中的方框,即可阅读该阶段发生了什么。下面各节用更多细节说明同样的内容。
点击任意方框,查看那里发生了什么。
两条独立的路径
节点承载两种永不混合的流量:
- 数据路径:你的用户的连接,经过本页所述的各个阶段。
- 控制路径:面板通过节点自己的端口、使用双向 TLS 与节点通信。它发送配置、用户和限制,并收集计数器。面板发送的任何内容都不会经过用户的连接,用户的连接也永远到不了面板。
两者只在三个地方交汇:每个入站接受的用户表、按用户的限制表,以及流量计数器。节点持有的其他一切都来自面板并保存在内存中;参见 节点与面板。
1. 监听器
连接落在节点为某个入站打开的端口上。有三种形态:
| 形态 | 作用 |
|---|---|
| 一个入站,一个端口 | 通常的情况。该端口只属于这个入站。 |
| ingress | 一个端口(通常是 443)由多个入站共用。ingress 读取 TLS 握手中的名称和应用层协议,在节点内部把连接交给规则指定的入站。 |
| 端口集合(端口跳跃) | 用于 Hysteria 和 Hysteria2。节点监听集合中的每个端口(最多 512 个),并从每个客户端发往的那个端口应答该客户端。 |
ingress 在同一个进程内交接连接;它不会把连接转发到另一个端口。正因如此,用户的真实地址得以保留,后面每一个按用户的机制也随之有效:计数器、地址数限制和速度限制看到的都是用户,而不是 ingress。规则按顺序尝试,第一个匹配的生效。详细内容和 ingress 的两种模式见 一个端口承载多个入站。
端口跳跃由节点自己完成,无需防火墙规则。每隔几秒就更换端口的客户端仍会从它使用的端口收到回复,因为节点记得每个客户端最后一次出现在哪里。
2. TLS、REALITY 与传输
如果入站使用 TLS,握手会在这里用面板放入节点配置中的证书完成。REALITY 入站用面板生成的密钥完成自己的握手。如果 ingress 处于终止模式,这一步已经由 ingress 完成,它交给入站的是明文流。
然后,如果入站有传输,就把传输解开:WebSocket、gRPC、HTTP、HTTPUpgrade、XHTTP、mKCP 或 QUIC。剩下的是协议自己的数据流。VLESS 入站还可以带有 VLESS Encryption,这是位于 TLS 和协议之间的一层;参见 VLESS Encryption。
3. 协议:识别用户
协议(VLESS、VMess、Trojan、Shadowsocks、Hysteria2、TUIC 等)读取数据流中的凭据,并在面板为该入站提供的用户集合中查找用户。从这里开始,连接就带有了用户的名称。
- 未知的凭据会在这里被拒绝,在任何路由之前。
- 用户按凭据匹配,而不是按位置。 当账户被删除或其凭据改变时,节点会立即停止为它接受新的数据流,包括已承载多个数据流的连接(QUIC、多路复用)中的数据流。
- 这里不检查设备数限制。 节点看不到设备,只能看到地址。设备数限制在应用获取其订阅时生效;参见 流量、额度与限制。
端点自己识别用户
WireGuard、OpenVPN 和 OpenConnect 端点会跳过第 2 和第 3 阶段。它们同时是入口和出口,各自用自己的方式识别用户:WireGuard 对等端靠面板为该用户生成的密钥,OpenVPN 和 OpenConnect 靠用户的登录。流量随后直接进入路由。
来自隧道的流量
在隧道的源节点上,隧道的半边接受来自中继的数据流,并直接交给路由。这些流量在源节点上不计入用户,其地址也不计入地址数限制:中继已经统计过该用户,而在源节点上,来源地址是中继的,不是用户的。参见 隧道内部。
4. 嗅探
当路由规则需要时,节点会读取连接的最初几个字节来了解它是什么:TLS 或 HTTP 请求中的域名,或 BitTorrent 之类的协议。这样,即使应用是按地址连接的,规则也能匹配真实的域名,还能匹配用户没有声明的协议。
5. 路由
节点所在模板的路由决定连接去往哪里。规则按顺序尝试,可按域名、地址、规则集、协议、入站、用户等匹配。第一个匹配的规则选定出站;都不匹配时,由最终出站接管。
- 规则集来自面板。 面板下载每个列表,保持其最新,并通过控制链路推送给节点。节点从不自己获取列表,所以列表来源在节点上无法访问也没有任何影响。
- 节点可以在模板的路由之上追加内容。 节点自己的路由在模板的路由之后应用,一个中继就是靠这种方式只让部分流量走隧道。
- 节点上的 路由测试 会显示某个地址会匹配哪条规则、会去往哪里,而不发送任何东西。参见 路由与 DNS。
6. 限制与计数器
路由选定出站后,在任何字节移动之前,连接会被包装两次:
- 用户的限制。 地址数限制决定是否允许该用户再从一个来源地址连接。IPv4 地址单独计数,IPv6 地址按其 /64 计数,地址在最后一次出现后继续计数十分钟。速度限制是每个方向的预算,在本节点上生效。地址数限制如何在整个节点群中确定,见 流量、额度与限制。
- 计数器。 字节按入站、按出站、按用户计数,连接加入节点的实时连接列表。
限制离连接最近,所以速度限制节流的恰好就是计数器报告的那些字节。
7. 出站
出站把连接继续送出:
| 出站 | 连接去往何处 |
|---|---|
| 直连 | 从本节点的地址直接到达目标。 |
| 代理 | 经由你指定的另一台服务器,例如另一家服务商的代理。 |
| 拦截 | 拒绝。每次拒绝都按拦截出站和按节点计数。 |
| 隧道 | 到达源节点,由源节点发往互联网。 |
| 端点 | 经由 WireGuard 或类似接口出去。 |
只有经过 block 类型出站的拒绝才会被计数,这也是 BT 拦截之类的现成预设会路由到拦截出站的原因。计数随每次心跳到达面板,速率过高时面板可以发出告警;参见 监控与指标。
8. 回到用户
回复沿原路返回,以相反的顺序经过同样的各层:出站、计数器、协议、传输和 TLS。同样的计数器统计两个方向。
计数器去往哪里
节点把计数器保存在内存中,由面板收集:
- 每 30 秒,面板收集每个节点的计数器。节点在上报每个计数器的同时将其清零,所以每个字节只上报一次。
- 每 10 秒,面板合并每个节点看到的地址,并把谁可以从哪里连接的表发回。
- 按需:当你在某个用户或节点上打开实时连接时,面板才向节点询问。
