通过主机名转发 ssh 连接到 docker 容器

通过主机名转发 ssh 连接到 docker 容器

我陷入了一种非常特殊的情况,尽管还有其他方法可以做到这一点,但我有点痴迷于此,并想找到一种完全像这样的方法:

背景

假设我有一台服务器,运行着几项隐藏在隔离的 docker 容器中的服务。由于这些服务大部分都是 http,因此我使用 nginx 代理向每项服务公开特定的子域。例如,节点服务器在 docker 容器上运行,其端口80绑定到127.0.0.1:8000主机上。我将在 nginx 中创建一个 vhost,将所有请求代理到myapp.mydomain.comhttp://127.0.0.1:8000这样,docker 容器就无法从外部访问,除非通过myapp.mydomain.com

现在我想开始戈格斯docker 容器指向gogs.mydomain.comgogs 容器。所以我开始这个 gogs 容器端口8000绑定到127.0.0.1:8001主机上。并且 nginx 站点将请求代理到,gogs.mydomain.com并且http://127.0.0.1:8001运行良好……

但是,gogs 是一个 git 容器,我也想通过它来访问仓库,[email protected]:org/repo但目前设置无法实现。实现该功能的一种方法是将容器的端口绑定到主机上的22端口,然后 git ssh url 可以是类似这样的格式。0.0.0.0:8022[email protected]:8022/repo

(这似乎不起作用;当我使用这样的 uri 推送到原点时,git 要求git输入用户的密码gogs.mydomain.com- 而不是gogs.mydomain.com:8022- 但这可能是我做错的事情并且超出了这个问题的范围,但是,我也很感激任何对此的诊断)

问题

我主要担心的是,我希望 ssh 端口<gogs container>:22被代理,就像我使用 nginx 代理 http 端口一样;也就是说,任何 ssh 连接都会gogs.mydomain.com传递到容器的端口22。现在我无法将容器的 ssh 端口绑定到主机的 ssh 端口,因为主机上已经有一个 sshd 在运行。此外,这意味着任何连接都会*.mydomain.com传递到容器的 sshd。


我想要任何 ssh 连接来:

  • mydomain.com host.mydomain.com或 mydomain 的 IP 地址被接受并转发到主机上的 sshd
  • gogs.mydomain.com或者git.mydomain.com被接受并传递给 gogs 容器上的 sshd
  • *.mydomain.com*除了上述可能性之外还有什么)被拒绝

如果是 http,我可以通过 nginx 轻松完成。有没有办法对 ssh 执行此操作?


(也想大胆地问一下:有没有办法实现这一点任何一般是 tcp 服务吗?

任何关于我在这里尝试做这件事的方式的见解,也都欢迎。当我尝试做的事情非常愚蠢时,我不介意别人告诉我。


我心里已经想好了:

也许我可以将主机上的 sshd 套接字与容器作为ro卷共享?这意味着容器内的 sshd 可以接收所有连接*.mydomain.com。有没有办法让容器内的 sshd拒绝除 或 之外的所有连接gogs.mydomain.comgit.mydomain.com但是,主机上的 sshd 将接收所有到 的连接,*.mydomain.com包括gogs.mydomain.com; 因此会发生冲突。我不知道,我还没有真正尝试过。应该我试试看?

答案1

通过“主机名”执行此操作根本不属于 ssh 的范围。ssh 协议本身不支持基于名称的虚拟主机(实际上 HTTP 是此处规则的例外)。

接收端的 SSHd 永远无法知道您要求客户端连接到哪个主机名,因为此信息未在协议内部传递。

如果您只需要几个客户端来使用它,您可以配置每个客户端连接到您的服务器,然后跳转到 docker 容器,如下所示:

Host yourcontainer
        Hostname internal.ip.of.your.container
        ProxyCommand ssh your.docker.host nc %h %p

这样 ssh 将调用代理命令,该命令将打开到主机的 ssh 会话并调用netcat以建立到容器的连接。这样您实际上不需要将容器的 ssh 端口暴露给外界。

答案2

最近的 OpenSSH 版本具有 ProxyJump 指令和 -J 标志:

ssh -J proxyuser@jumphost user@target

相关内容