相关原理
HTTP 虚拟主机
节点如何用一个端口按域名把请求分给不同隧道,以及 Host 与 SNI 的区别
1. 一个端口怎么服务多个站点
按端口分隧道时,一条隧道占一个远程端口,访客连 节点:端口 即可。但 80 与 443 只有一个,不可能每条隧道各分一个,于是 HTTP/HTTPS 隧道改成按域名区分:所有 HTTP 隧道共用节点的 80,所有 HTTPS 隧道共用 443,节点看请求里的域名决定交给哪条隧道。
这就是虚拟主机(vhost):同一组地址与端口上挂着多个站点。
2. Host 与 SNI
区分域名靠两处信息,取决于请求是明文还是加密:
| 请求 | 读哪里 | 是否加密 |
|---|---|---|
HTTP | 请求头里的 Host | 明文 |
HTTPS | 握手第一个包里的 SNI | 仅这一段明文 |
HTTPS 隧道不做解密:节点只读 ClientHello 里的 SNI 决定交给谁,之后整条连接原样透传给 frpc。
3. 80 与 443 是两套 vhost
HTTP 与 HTTPS 在节点上分开处理,互不占用:同一个域名可以同时有一条 HTTP 隧道和一条 HTTPS 隧道,分别落在 80 和 443 上,它们不会因为域名相同而冲突。
4. 一个域名只能对应一个同类型后端
同一个节点上,同一个域名在同一套 vhost 里只能有一个后端。再启动一条同类型、同域名的隧道时,节点无法判断该把请求交给谁,日志会报 router config conflict。
不算冲突的情况:
- 同域名、不同协议:一条
HTTP、一条HTTPS,各占各的表 - 同域名、不同节点:每个节点有各自的 vhost 表
- 不同域名:本来就是用来区分站点的
5. 没有域名的请求
Host 与 SNI 都可能缺失:直接用 IP 访问、客户端不发 SNI,或者中间设备改写了请求头。
节点只按域名查表,查不到就没有后端,连接直接失败。它不会像 nginx 那样回落到 default_server——节点上不存在默认站点,也没有任何一条隧道会被当作兜底。
6. 域名从哪来
vhost 只认域名,所以域名要先证明属于您:添加进域名白名单并通过 DNS 验证,之后才能在建隧道时选择。同时还要把域名指向节点,访客才到得了,填写规则见 DNS 配置。
节点读的是请求里的域名,不关心这个域名解析到了哪里。前面套 CDN 时,回源请求带着同一个域名,选路结果与直连时相同。
7. 结论
- vhost 用域名代替端口做区分,让多条隧道共用一个入口
- 明文看
Host,加密看 SNI,节点不需要解密 - 80 与 443 是两套独立的表,同域名可以各占一条
- 同一个节点、同一个域名、同一协议只能有一个后端
- 没有域名就没有选路依据,节点不提供默认站点