NGINX 反向代理 SSH 映射问题

NGINX 反向代理 SSH 映射问题

我们公司运行着几台虚拟(Ubuntu)服务器。每台服务器都桥接了网络连接,因此它们从路由器(DHCP 保留)获取自己的 IP 地址。我们需要运行几个拥有自己子域的网站。

我们有我们的顶级域名(比如说 example.com)

然后我们有 sub1.example.com、sub2.example.com 和 sub3.example.com

看起来,最简单的方法是运行反向代理(以便将来我们可以将一些移动到云端并使用负载平衡)。

我已经设置了一个运行 NGINX 的 Ubuntu 20.04 LTS 的新虚拟机,并将其配置为反向代理。

我目前有 3 种配置:

重定向https:

server {
    listen 80;
    listen [::]:80;
    
    server_name *.example.com;
    return 301 https://$host$request_uri;
}

SSL 代理:

server {
    listen 443 ssl;
    server_name example.com;
    location / {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_set_header X-Forwarded_Proto https;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_redirect off;
        proxy_pass https://10.10.x.y;
        proxy_http_version 1.1;
    }
    
    ssl_certificate        /etc/<path_to_cert>/fullchain.pem;
    ssl_certificate_key    /etc/<path_to_cert>/privkey.pem;
}

SSL 代理子域名:

server {
    listen 443 ssl;
    server_name sub1.example.com sub2.example.com sub3.example.com;
    location / {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_set_header X-Forwarded_Proto https;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_redirect off;
        proxy_pass https://10.10.x.y;
        proxy_http_version 1.1;
    }
    
    ssl_certificate        /etc/<path_to_cert>/fullchain.pem;
    ssl_certificate_key    /etc/<path_to_cert>/privkey.pem;
}

一切都运行良好。

为了能够在家编辑我们的网站,我想配置代理来传递 SSH 流量,这就是我感到困惑的地方。

我已经阅读了这里、其他网站和 NGINX 文档的许多帖子,但我似乎并没有弄清楚这一点。

我直接按照文档中的示例进行操作: https://nginx.org/en/docs/stream/ngx_stream_ssl_preread_module.html

看起来很简单。

我的配置几乎相同(仅更改了与我的公司相关的部分,例如 IP 地址等)

为了完整起见,我使用的示例标题为根据服务器名称选择上游

我的配置(已修改):

map $ssl_preread_server_name $name {
    example.com           backend_main;
    sub1.example.com      backend_1;
    sub2.example.com      backend_2;
    sub3.example.com      backend_3;
    default               backend_proxy;
}

upstream backend_main { server 10.10.x.y:22; }
upstream backend_1 { server 10.10.x.y:22; }
upstream backend_2 { server 10.10.x.y:22; }
upstream backend_3 { server 10.10.x.y:22; }
upstream backend_proxy { server 10.10.x.y:22; }

server {
    listen      2222;
    proxy_pass  $name;
    ssl_preread on;
}

log_format proxy '$remote_addr [$time_local] '
    '$protocol $status $bytes_sent $bytes_received '
    '$session_time "$upstream_addr" '
    '"$upstream_bytes_sent" "$upstream_bytes_received" "$upstream_connect_time"';

access_log /var/log/nginx/proxy-access.log proxy;
error_log /var/log/nginx/proxy-error.log;

上面的代码块位于stream {...}块内,位于/etc/nginx/nginx.conf块之后html {...}(注释mail {...}块之前)。

路由器将外部端口 22 转发到反向代理的内部端口 2222。

我面临的问题是map总是选择默认选项。如果我删除/注释默认设置,我根本无法连接。如果我更改默认设置上的 IP 地址,它会将我连接到该服务器,但同样,只能连接到“默认”设置。

最终目标是能够直接通过 ssh 进入其中一个子域(例如)。目前,我必须通过 ssh 进入一个我授予自己外部访问权限的服务器,然后从那里通过 ssh 进入一个内部服务器。ssh [email protected]

唯一想到的是,这可能无法与现有的 HTTPS 代理很好地运行,但也许stream模块也应该能够处理这些(如果可以,我是否可以设置标题?否则后端只能看到来自反向代理的请求)。

我怀疑这是一个简单的问题,我忽略了一些东西,但是在花了 8 个小时阅读和尝试不同的事情之后,我觉得是时候寻求帮助了......

答案1

SSH 客户端不使用 TLS 协议的 SNI 扩展,该扩展是为了支持使用 HTTPS 的共享主机而开发的。您可以尝试按以下方式设置 ssh 客户端:

Host example.com *.example.com
    ProxyCommand openssl s_client -quiet -servername %h -connect example.com:2222

但是我不知道它是否可行。你可以阅读更多关于s_clientopenssl 命令的信息这里。另请查看这篇文章:使用 TLS/SNI 和 NGINX 代理 SSH

答案2

显而易见的是,ssh 不是 https,并且它的协议不会发送您可以像使用 https 那样进行匹配的主机名。

我有几个主机也有类似的限制,因为它们是没有全局 IPv4 地址的虚拟机。对于这些主机,我使用 IPv6 通过 ssh 访问它们。如果出于某种原因您还没有部署 IPv6,那么您已经落后了好几年了……

相关内容