用於透過 socat 連接到家庭伺服器的 SSL 證書

用於透過 socat 連接到家庭伺服器的 SSL 證書

我在家裡的 Raspberry Pi 上運行 Nextcloud。它在 DynDNS 提供者 spDYN.de 的主機名稱上更新其 IPv6 位址。但是,由於我的提供者僅提供 IPv6 連線(使用 DS-Lite for IPv4),因此我只能從其他 IPv6 連線直接存取主機名,並且必須使用 IPv4-IPv6 後映射器從 IPv4 網路連線到它。

這不是什麼大問題,因為我的網站託管在同時具有 IPv6 和 IPv4 連接的伺服器上,所以我根據本教程在託管我的網站的伺服器上設定連接埠映射器,將特定連接埠從我的網站網域路由到動態 DNS 主機名稱上的連接埠 443。這工作得很好,但它會產生 SSL 憑證的問題:

在 RasPi 上,我使用 certbot 為動態 DNS 主機名稱建立「讓我們加密」證書,該證書運作良好,並且連線顯示為安全性。另外,在我的網頁伺服器上,我為用於連接埠映射器的網域建立了一個類似的證書,該證書本身就可以工作。但是,當我使用特定轉送連接埠存取網域以存取 RasPi 時,瀏覽器會繼續顯示包含我的網域的 URL,但它從 RasPi 接收為動態 DNS 主機名稱頒發的憑證。當然,結果是安全檢查會失敗,因為憑證是為「錯誤」的網域頒發的。我已經嘗試在我的 RasPi 上為我的網域頒發證書,但它無法告訴我我「未經授權」。

我要怎麼解決這個問題?我必須在哪裡設定哪種證書?

答案1

為了避免憑證錯誤,您需要 pi 傳送與所使用的網域相符的憑證。有兩種方法:

  1. 對兩個網域使用一個證書,安裝在 pi 和主伺服器上。無論用戶端在查詢中使用哪個網域,憑證都會符合。
  2. 選擇用戶端期望的憑證並將其發送。

選項 1 較簡單,也是常見的做法。查看 google.com 的證書! pi 和主伺服器都將安裝相同的憑證(對於兩個網域)。為了從 Let's Encrypt 獲得這樣的證書,您還需要主伺服器為 pi 的動態網域運行網站並使用certbot 指令可同時驗證對兩個網域的控制。 dyndns 名稱的主伺服器網站不需要託管來自 pi 的內容 - 它就在那裡,以便 Let's Encrypt 可以驗證您是否擁有該網站的控制權(您甚至可以在續約之間關閉該網站)。

範例 Certbot 命令(在主 Web 伺服器上執行):

letsencrypt certonly --webroot --csr request.csr -w /http/pisite/www -d mypi.spdyn.de -w /http/mainwebsite/www -d maindomain.de

其中request.csr使用任一網域作為 CN 並且在 SAN 欄位中具有兩個網域,/http/pisite/www指的是您為目前伺服器上綁定到 pi 動態名稱的另一個網站所建立的本機目錄,並且/http/mainwebsite/www是主網站的現有目錄。


選項 2 涉及更多,但會產生「更乾淨」的結果:用戶端獲得與他們輸入的網域相符的憑證。在樹莓派上,使用流模組(或等效模組)運行 nginx,當打開 TLS 連接時:檢查 SNI 字段(不接受 TLS 連接),並根據其中包含的域,選擇轉發哪個上游連接到.這使您可以選擇如何處理轉發到樹莓派的外部連接埠上主網域發出的請求。您可以將它們傳送到主Web 伺服器,就像它們是在正確的連接埠上建立的一樣,您可以將它們傳送到pi 上的其他連接埠(即Nextcloud 或其他任何連接埠),您可以使用相同的nginx 實例終止它們,並顯示您喜歡的任何頁面,或乾脆關閉連線。這是你的選擇。

以下是此方法的範例配置:

stream/sni-switch.conf

# Listen on 443, and on new connection:
#   if the SNI is mapped herein, handle it on this Nginx
#   else, forward the whole session to 192.168.1.80:443 (TCP passthrough, no decryption)

upstream mainwebserver {
    server 192.168.1.80:443;
}

upstream local_https {
    server 127.0.0.1:1443;
}

map $ssl_preread_server_name $name {
    default mainwebserver;

    pisite.spdyn.de     local_https;
}

server {
    listen 443;

    ssl_preread on;
    proxy_pass $name;
}

並且在nginx.conf

load_module /usr/lib/nginx/modules/ngx_stream_module.so;

stream {
    include /etc/nginx/stream/sni-switch.conf;
}

...

若要使用 Apache 執行此操作,請參閱。範例配置可能如下所示:

<VirtualHost *:*>
    ProxyPreserveHost On
    ProxyPass        "/" "http://192.168.1.80/"
    ProxyPassReverse "/" "http://192.168.1.80/"
    ServerName maindomain.de
</VirtualHost>

相關內容