相关原理

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 是两套独立的表,同域名可以各占一条
  • 同一个节点、同一个域名、同一协议只能有一个后端
  • 没有域名就没有选路依据,节点不提供默认站点