使用 nginx 在与 HTTP(S) 不同的虚拟服务器上提供 SSH 服务

使用 nginx 在与 HTTP(S) 不同的虚拟服务器上提供 SSH 服务

我的问题与同时提供 ssh 和 https 服务或者将 http 请求重定向到 ssh。我不想多路复用该流。我有一个虚拟服务器可以“备用”。

我在想,是否有可能拥有不同的虚拟服务器,我可以始终通过 ssh 连接,而其他人可以始终通过 https 连接。没有多路复用;干净/直接的解决方案,无需做决定。因此,例如,服务器web.myserver.com将是仅支持 https 的服务器和ssh.myserver.com仅支持 ssh 的服务器。

如果可能的话,最好不要产生额外的“流开销”。在我看来,stream顶级指令似乎有这种开销。

编辑:添加更多信息到目前为止我尝试过什么:

stream{}配置部分我放了以下代码:

    upstream ssh {
        server 192.168.1.5:22;
    }
    server {
        listen 443;
        listen [::]:443;
        proxy_pass ssh;
    }

当我尝试连接到 ssh 时,我收到了以下日志信息:

debug2: resolving "***" port 443
debug3: resolve_host: lookup ***:443
debug3: ssh_connect_direct: entering
debug1: Connecting to *** [***] port 443.
debug3: set_sock_tos: set socket 3 IP_TOS 0x48
debug1: Connection established.
...
debug1: Local version string SSH-2.0-OpenSSH_9.2
debug1: kex_exchange_identification: banner line 0: HTTP/1.1 400 Bad Request
debug1: kex_exchange_identification: banner line 1: Server: nginx/1.18.0
debug1: kex_exchange_identification: banner line 2: Date: Thu, 09 Mar 2023 15:10:38 GMT
debug1: kex_exchange_identification: banner line 3: Content-Type: text/html
debug1: kex_exchange_identification: banner line 4: Content-Length: 157
debug1: kex_exchange_identification: banner line 5: Connection: close
debug1: kex_exchange_identification: banner line 6: 
debug1: kex_exchange_identification: banner line 7: <html>
debug1: kex_exchange_identification: banner line 8: <head><title>400 Bad Request</title></head>
debug1: kex_exchange_identification: banner line 9: <body>
debug1: kex_exchange_identification: banner line 10: <center><h1>400 Bad Request</h1></center>
debug1: kex_exchange_identification: banner line 11: <hr><center>nginx/1.18.0</center>
debug1: kex_exchange_identification: banner line 12: </body>
debug1: kex_exchange_identification: banner line 13: </html>
kex_exchange_identification: Connection closed by remote host

答案1

根据您的最新评论,您似乎想在非常早期的阶段,直接在建立连接时进行流量分割。

此时,接收服务器没有关于您尝试连接的主机名的信息,因此它早期无法做太多事情。它的工作方式是,您的客户端进行 DNS 查找以获取web.myserver.com或的 IP ssh.myserver.com,然后与该 IP(在本例中为端口 443)进行 TCP 连接。现在,您在该 IP 上的该端口上侦听的任何内容都会经过正常的 TCP 连接建立,其中只有 IP/端口信息,没有主机名。

由于似乎要求两者都响应相同的端口(443),具体取决于您的设置(即,如果您有可能向代理服务器添加第二个 IP),您可以通过 IP 区分并让 DNS 映射每个web.myserver.comIP ssh.myserver.com,然后根据客户端连接到的 IP 尽早进行拆分(例如使用某些iptables规则)。

如果没有可能添加第二个 IP,那么我实在看不到解决方案,至少在建立连接后检查前几个数据包,这正是上述涉及nginx stream部分的解决方案所做的。您提到的“流开销”应该是最小的,因为该stream部分会在最初确定目的地后直接转发所有数据包而不进行检查。但似乎“流开销”并不是您试图避免的唯一部分,正如您所说:

不提供额外的“流开销”将被渴望

(重点是我的……)。如果您分享任何其他要求,使得nginx解决方案不适用于您的用例,我可以用任何其他可能想到的可能性来更新我的答案(或者社区中的其他人可能会想到更好的方法)。

相关内容