socat 経由でホーム サーバーに接続するための SSL 証明書

socat 経由でホーム サーバーに接続するための SSL 証明書

私は自宅の Raspberry Pi で Nextcloud を実行しています。DynDNS プロバイダー spDYN.de のホスト名で IPv6 アドレスを更新します。ただし、私のプロバイダーは IPv6 接続のみを提供しているため (IPv4 には DS-Lite を使用)、他の IPv6 接続からのみホスト名に直接アクセスでき、IPv4 ネットワークから接続するには IPv4-IPv6 ポストマッパーを使用する必要があります。

これは大した問題ではありません。私のウェブサイトはIPv6とIPv4の両方の接続を持つサーバーでホストされているので、socatを使用しました。このチュートリアル私のウェブサイトをホストしているサーバーにポートマッパーを設定し、ウェブサイトのドメインから特定のポートをダイナミック DNS ホスト名のポート 443 にルーティングします。これは完璧に機能しますが、SSL 証明書に問題が発生します。

RasPi では、certbot を使用してダイナミック DNS ホスト名の「Let's encrypt」証明書を作成しましたが、これは問題なく機能し、接続はセキュリティ保護されていると表示されます。また、Web サーバーでは、ポートマッパーに使用しているドメインの同様の証明書を作成しましたが、それ自体は機能します。ただし、RasPi にアクセスするために特定の転送ポートでドメインにアクセスすると、ブラウザーは引き続き自分のドメインを含む URL を表示しますが、RasPi からダイナミック DNS ホスト名用に発行された証明書を受け取ります。結果として、当然ながら、証明書が「間違った」ドメイン用に発行されるため、セキュリティ チェックは失敗します。RasPi で自分のドメインの証明書を発行しようとしましたが、「権限がありません」と表示されて失敗します。

この問題を解決するにはどうすればいいでしょうか? どのような種類の証明書をどこに設定する必要がありますか?

答え1

証明書エラーを回避するには、使用されているドメインに一致する証明書を pi が送信する必要があります。これには 2 つのアプローチがあります。

  1. 両方のドメインに 1 つの証明書を使用し、pi とメイン サーバーの両方にインストールします。クライアントがクエリでどのドメインを使用したかは関係なく、証明書は一致します。
  2. クライアントが期待する証明書を選択して送信します。

オプション1はより簡単で一般的な方法です。google.comの証明書を見てください。piとメインサーバーの両方に同じ証明書(両方のドメイン用)がインストールされます。Let's Encryptからそのような証明書を取得するには、メインサーバーでpiの動的ドメインのウェブサイトも実行し、1つ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/wwwpi の動的名にバインドされた現在のサーバー上の別の Web サイト用に作成するローカル ディレクトリを参照し、/http/mainwebsite/wwwメイン Web サイトの既存のディレクトリになります。


オプション 2 はより複雑ですが、より「クリーンな」結果が得られます。クライアントは、入力したドメインに一致する証明書を取得します。Raspberry Pi で、nginx を stream モジュール (または同等のもの) とともに実行します。これは、TLS 接続が開かれると、SNI フィールドを調べ (TLS 接続を受け入れずに)、そこに含まれるドメインに基づいて、接続を転送するアップストリームを選択します。これにより、Raspberry Pi に転送される外部ポートのメイン ドメインからの要求を処理する方法を選択できます。正しいポートで行われた場合と同じようにメイン 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>

関連情報