SSH 没有 Host 头部
SSH has no Host header

原始链接: https://blog.exe.dev/ssh-host-header

exe.dev 由于其固定费用订阅模式,可用 IPv4 地址数量有限,因此在为虚拟机提供 SSH 访问方面面临挑战。与使用“Host”标头在共享 IP 时将请求路由到正确服务器的 HTTPS 不同,SSH 缺乏等效机制。 为此,exe.dev 实施了一个系统,虚拟机共享一个公共 IPv4 地址池,但通过连接用户公钥*和*连接源 IP 地址的组合来唯一标识。这允许 SSH 代理将连接路由到正确的虚拟机。 这需要自定义管理软件来根据用户所有权分配 IP,并在使用 NAT 的云环境中准确确定原始 IP 地址。虽然这不是一个广泛适用的解决方案,但它使 exe.dev 能够为用户维护一致的、基于域名的 SSH 体验。

## SSH 主机头问题与潜在解决方案 - Hacker News 摘要 Hacker News 上的一讨论围绕一项服务(exe.dev),该服务试图允许通过 Web 主机名访问虚拟机/容器的 SSH,而不是直接 IP 连接。用户指出这并非标准的 TCP/IP 行为——HTTP 流量依赖反向代理(如 nginx)来路由到正确的虚拟机,而 SSH 需要类似的代理。 对话探讨了这是否是一种中间人(MitM)场景,因为 SSH 密钥在虚拟机之间共享,并强调了 SSH 密钥管理方面的潜在安全问题,特别是缺乏证书封装。 几位用户建议现有的解决方案,如跳板/堡垒主机或 `sshproxy` 和 `sshpiper` 等工具,可以实现类似的功能。 一个关键的争论点是可用性:exe.dev 旨在提供“零配置”体验,避免需要自定义 SSH 配置或非标准端口(这些端口可能被防火墙阻止)。人们对这种方法的扩展性以及对主机环境的隐式信任表示担忧。
相关文章

原文

We have a challenge with ssh. Every VM has a standard URL that we use for both HTTPS and SSH, e.g. undefined-behavior.exe.xyz. Just as you can type the domain into a web browser (and have TLS and auth taken care of for you), you can run:

ssh undefined-behavior.exe.xyz

To get a shell in your VM.

This is very straightforward to implement if you give each machine its own IP address, but exe.dev gives you many VMs on a flat rate subscription.

We cannot issue an IPv4 address to each machine without blowing out the cost of the subscription. We cannot use IPv6-only as that means some of the internet cannot reach the VM over the web. That means we have to share IPv4 addresses between VMs.

For the web, this is a long-solved problem. Many sites can and do have the same IP address. Web browsers send the domain they used to reach the server in the HTTP request as the Host header. The exe.dev proxy switches on this header and send requests to the appropriate VM.

SSH, on the other hand, has no equivalent of a Host header. If we reuse IPv4 addresses between VMs, we have no way to send SSH connections to the right VM.

Instead of using one IP address for all VMs, we have a pool of public IPv4 addresses. Each VM is assigned a unique address relative to its owner.

So instead of an A record, you will find

$ dig undefined-behavior.exe.xyz

; <<>> DiG 9.10.6 <<>> undefined-behavior.exe.xyz
...
;; ANSWER SECTION:
undefined-behavior.exe.xyz. 230 IN      CNAME   s003.exe.xyz.
s003.exe.xyz.           230     IN      A       16.145.102.7

Relative to its owner means that while the IP represented by s003 is used by many VMs, it is only used by one VM owned by this user.

This is all the extra information we need to route SSH connections. When SSH connects, it presents a public key and comes in via a particular IP address. The public key tells us the user, and the {user, IP} tuple uniquely identifies the VM they are connecting to. In diagram form:

A diagram of ssh'ing into an exe.dev VM

Building a proxy that does this requires some cross-system communication: when we create a VM we have to allocate it an IP carefully based on the user (or in the near future: team) that owns it. Our ssh proxy has to be able to determine the local IP a request came in on, which is easy on bare metal, harder in a cloud environment where public IPs are NATed on to private VPC addresses. All of this requires bespoke management software, so we cannot recommend it as a general solution to people who want to multiplex VM SSH access onto an IP. But uniform, predictable domain name behavior is important to us, so we took the time to build this for exe.dev.

联系我们 contact @ memedata.com