Comment by morpheuskafka

5 days ago

They are saying they want to directly SSH into a VM/container based on the web hostname it serves. But that's not how the HTTP traffic flows either. With only one routable IP for the host, all traffic on a port shared by VMs has to go to a server on the host first (unless you route based on port or source IP with iptnbles, but that is not hostname based).

The HTTP traffic goes to a server (a reverse proxy, say nginx) on the host, which then reads it and proxies it to the correct VM. The client can't ever send TCP packets directly to the VM, HTTP or otherwise. That doesn't just magically happen because HTTP has a Host header, only because nginx is on the host.

What they want is a reverse proxy for SSH, and doesn't SSH already have that via jump/bastion hosts? I feel like this could be implement with a shell alias, so that:

ssh user@vm1.box1.tld becomes: ssh -j jumpusr@box1.tld user@vm1

And just make jumpusr have no host permissions and shell set to only allow ssh.

> The HTTP traffic goes to a server (a reverse proxy, say nginx) on the host, which then reads it and proxies it to the correct VM.

That's one implementation. Another implementation is the proxy looks at the SNI information in the ClientHello and can choose the correct backend using that information _without_ decrypting anything.

Encrypted SNI and ECH requires some coordination, but still doesn't require decryption/trust by the proxy/jumpbox which might be really important if you have a large number of otherwise independent services behind the single address.

The point is that they want the simple UX of "ssh vm1.box1.tld" takes you to the same machine that browsing to vm1.box1.tld takes you to, without requiring their users to set any additional configuration.

  • You can have that already? It's just dns. Are you saying different vms share the same box1 ip? Well then yeah, you want a reverse proxy on some shared ip.

    • > Well then yeah, you want a reverse proxy on some shared ip.

      At that point you run into the problem that SSH doesn't have a host header and write this blog post.

      2 replies →

If jump host shell aliases were a valid option, then setting a port would be a much easier valid option.

I ended up doing something like this for a separate use case (had to host a bunch of Drupal instances, and for some reason end users needed shell access).

For the proxy I did not rely on a “proper” ssh daemon (like openssh), but wrote my own using a go library called gliderlabs/ssh. That in particular allowed me to implement only a tcp forwarding callback [1] , and not provide any shell access on a protocol level. Also made deployment nicer - no need for a full VM, just a container was sufficient.

It is also worth nothing that the -j can be moved into .ssh/config using the ProxyJump option. It does mean end users need a config file - but it does allow typing just a plain ssh command.

[1] https://pkg.go.dev/github.com/gliderlabs/ssh#ForwardedTCPHan...