nginxリバースプロキシで暗号化できます


45

前書き

開発サーバー(現在はUbuntu 14.04 LTSを実行しています)があります。これは、さまざまなポートでさまざまな開発ツールをホストするためにしばらく使用しています。ポートは覚えにくいため、すべてのサービスにポート80を使用し、ホスト名に基づいて内部でポート転送を行うことにしました。

domain.com:5432と書く代わりに、sub.domain.comから簡単にアクセスできます。

たとえば、ポート7547を使用し、sub.domain.comで実行されているアプリケーションXには、次のnginx構成があります。

upstream sub {
    server 127.0.0.1:7547;
}

server {
    listen 80;
    server_name sub.domain.com www.sub.domain.com;
    access_log /var/log/nginx/sub.log combined;
    location / {
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_pass http://127.0.0.1:7547;
            proxy_set_header Authorization "";
    }
}

質問

私が選択した現在の構成構造を考えると、letsencryptを使用してhttpsの下でさまざまなサービスを実行することは可能ですか?


3
私はこのトピックに関するブログ記事を書いた:tom.busby.ninja/letsecnrypt-nginx-reverse-proxy-no-downtime
トム・バズビー

回答:


81

はい。HTTPサーバーへのnginxプロキシリクエストを送信し、それ自体がHTTPSを介してクライアントに応答することができます。これを行う場合、nginx <-> proxy connectが、予想される攻撃者である誰かによってスニッフィングされる可能性が低いことを確認する必要があります。安全で十分なアプローチに次のものがあります。

  • 同じホストへのプロキシ(あなたと同じように)
  • ファイアウォールの背後にある他のホストへのプロキシ

パブリックインターネット上の別のホストへのプロキシは、十分に安全とは言えません。

プロキシとして使用しているのと同じWebサーバーを使用してLet's Encrypt証明書を取得する手順を次に示します。

Let's Encryptから初期証明書を要求する

server句を変更して、サブディレクトリ.well-knownをローカルディレクトリから提供できるようにします。例:

server {
    listen 80;
    server_name sub.domain.com www.sub.domain.com;
    […]
    location /.well-known {
            alias /var/www/sub.domain.com/.well-known;
    }

    location / {
        # proxy commands go here
        […]
    }
}

http://sub.domain.com/.well-known Let's Encryptサーバーは、それが発行する課題への回答を探します。

その後、certbotクライアントを使用して、webrootプラグインを使用して(ルートとして)Let's Encryptから証明書を要求できます。

certbot certonly --webroot -w /var/www/sub.domain.com/ -d sub.domain.com -d www.sub.domain.com

これで、キー、証明書、および証明書チェーンがインストールされます /etc/letsencrypt/live/sub.domain.com/

証明書を使用するためのnginxの構成

まず、次のような新しいサーバー句を作成します。

server {
    listen 443 ssl;

    # if you wish, you can use the below line for listen instead
    # which enables HTTP/2
    # requires nginx version >= 1.9.5
    # listen 443 ssl http2;

    server_name sub.domain.com www.sub.domain.com;

    ssl_certificate /etc/letsencrypt/live/sub.domain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/sub.domain.com/privkey.pem;

    # Turn on OCSP stapling as recommended at 
    # https://community.letsencrypt.org/t/integration-guide/13123 
    # requires nginx version >= 1.3.7
    ssl_stapling on;
    ssl_stapling_verify on;

    # Uncomment this line only after testing in browsers,
    # as it commits you to continuing to serve your site over HTTPS
    # in future
    # add_header Strict-Transport-Security "max-age=31536000";

    access_log /var/log/nginx/sub.log combined;

    # maintain the .well-known directory alias for renewals
    location /.well-known {
        alias /var/www/sub.domain.com/.well-known;
    }

    location / {
        # proxy commands go here as in your port 80 configuration
        […]
    }
}

nginxをリロードします。

service nginx reload

HTTPSが機能することを確認するには、ブラウザ(およびサポートを希望するその他のブラウザ)にアクセスhttps://sub.domain.comhttps://www.sub.domain.com、証明書エラーを報告しないことを確認します。

推奨:また、raymii.org:nginxの強力なSSLセキュリティを 確認し、SSL Labsで設定をテストします。

(推奨)HTTPリクエストをHTTPSにリダイレクトする

https://一部のユーザーがにアクセスして安全でないコンテンツを提供するのではなく、サイトがURL のバージョンで機能することを確認したらhttp://sub.domain.com、HTTPSバージョンのサイトにリダイレクトします。

ポート80 server句全体を次のように置き換えます。

server {
    listen 80;
    server_name sub.domain.com www.sub.domain.com;
    rewrite     ^   https://$host$request_uri? permanent;
}

また、ポート443構成でこの行のコメントを外して、ブラウザーがサイトのHTTPバージョンを試さないことを忘れないようにする必要があります。

add_header Strict-Transport-Security "max-age=31536000";

証明書を自動的に更新する

このコマンドを(ルートとして)使用して、certbotが認識しているすべての証明書を更新し、新しい証明書(既存の証明書と同じパスを持つ)を使用してnginxをリロードできます。

certbot renew --renew-hook "service nginx reload"

certbotは60日以上経過した証明書のみを更新しようとするため、このコマンドを非常に定期的に実行し、可能な場合は自動的実行するのが安全です(推奨)。たとえば、次のコマンドをに配置できます/etc/crontab

# at 4:47am/pm, renew all Let's Encrypt certificates over 60 days old
47 4,16   * * *   root   certbot renew --quiet --renew-hook "service nginx reload"

ドライランで更新をテストできます。これは、Let's Encryptステージングサーバーに接続して、ドメインに接続する実際のテストを行いますが、結果の証明書保存しません

certbot --dry-run renew

または、次の方法で早期更新を強制できます。

certbot renew --force-renew --renew-hook "service nginx reload"

注:ドライランは何度でも実行できますが、実際の更新にはLet's Encryptレート制限が適用されます


あなたの解決策は私には役立たないようです。基本的に同じ構成です。それはgoopen.tkのために動作しますが、www.goopen.tkない
ALKO

3
@Alko、答えの指示は正しく、この問題をカバーしています。certbotまたはその他のツールを使用する場合、ドメインをwww形式とwww以外の形式の両方で指定することを忘れないでください。
パウロコギー

以下の下ではlocation /.well-known、あなたが去る必要が.well-knownパスにアウト。使用することはalias /var/www/sub.domain.com、ありませんalias /var/www/sub.domain.com/.well-known
gldraphael

1
「rewrite ^ https:// $ host $ request_uri?permanent;」を使用する理由を誰かが私に説明できますか?ここで「return 301 https:// $ server_name $ request_uri;」の代わりに
ZaxLofful

場所のパスを引用符で囲む必要があることがわかりました。location '/.well-known' {。これがバージョンの問題なのか、自分の設定なのかはわかりませんが、他の誰かが動けなくなる場合があります。
フランクV

2

はい、nginxhttpsのエンドポイントとして使用し、httpを介してバックエンドと協力できます。たとえば、私の設定:

server {
        server_name host;
        listen 443 ssl;
...
 location /svn/ {
            auth_ldap off;

            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;

            proxy_pass http://localhost:1080/svn/;
            proxy_redirect http://localhost:1080/ https://host/;
        }
...
}

しかし、私が知っているように、暗号化では、証明書を取得するときにすべてのサブドメインをポイントする必要があり、これが問題である場合は、https://host/service代わりにurlを選択しますhttps://service.host

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.