NGINX 反向代理 SSH 映射問題
我們公司有幾個虛擬(Ubuntu)伺服器在執行。每個都有其網路連接橋接,因此它從路由器獲取自己的 IP 地址(DHCP 保留)。我們需要執行幾個具有自己子域的網站。
我們有我們的頂級域名(比如說 example.com)
然後我們有 sub1.example.com、sub2.example.com 和 sub3.example.com
最簡單的方法似乎是執行反向代理(以便將來我們可以將一些移動到雲並使用負載平衡)。
我已經使用執行 NGINX 的 Ubuntu 20.04 LTS 設置了一個新 VM,並將其配置為反向代理。
我目前有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 地址等)
為了完整起見,我使用的範例標題為Selecting an upstream based on server name
我的配置(修改):
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 user@sub1.example.com
)。目前,我必須通過 ssh 連接到我給自己提供外部訪問權限的一台伺服器,然後從那裡 ssh 進入內部伺服器。唯一想到的是,這可能不適用於現有的 HTTPS 代理,但也許
stream
模組也應該能夠處理這些(如果可以,我可以設置標頭嗎?否則後端只能看到來自反向代理的請求)。我懷疑這是一個簡單的問題並且我忽略了一些東西,但是在花了 8 個小時閱讀和嘗試不同的東西之後,我覺得是時候尋求幫助了……
SSH 客戶端不使用 TLS 協議的 SNI 擴展,這些擴展是為支持使用 HTTPS 的共享主機而開發的。您可以嘗試通過以下方式設置您的 ssh 客戶端:
Host example.com *.example.com ProxyCommand openssl s_client -quiet -servername %h -connect example.com:2222
但是我不知道它是否會起作用。您可以在此處閱讀有關
s_client
openssl 命令的更多資訊。另請查看這篇文章:使用 TLS/SNI 和 NGINX 的代理 SSH。
顯而易見的是,ssh 不是 https,它的協議不會發送一個主機名,您可以使用該主機名進行匹配,就像使用 https 一樣。
我有一些具有類似限制的主機,因為它們是沒有全域 IPv4 地址的虛擬機。對於這些,我通過 ssh 和 IPv6 訪問它們。如果由於某種原因您還沒有部署 IPv6,那麼您現在已經落後了幾年…