Ubuntu 14.04でLet’s Encryptを使用してHAProxyを保護する方法

前書き

Let's Encryptは、無料のTLS / SSL証明書を簡単に取得してインストールする新しい認証局(CA)です。これにより、Webサーバーで暗号化されたHTTPSを有効にします。 必要な手順のほとんどを自動化しようとするソフトウェアクライアントCertbotを提供することにより、プロセスを簡素化します。 現在、証明書の取得とインストールのプロセス全体は、Apache Webサーバーでのみ完全に自動化されています。 ただし、Certbotを使用すると、無料のSSL証明書を簡単に取得できます。この証明書は、Webサーバーソフトウェアの選択に関係なく、手動でインストールできます。

このチュートリアルでは、Certbotを使用して無料のSSL証明書を取得し、Ubuntu 14.04のHAProxyで使用する方法を示します。 また、SSL証明書を自動的に更新する方法も示します。

HAProxy with Let’s Encrypt TLS/SSL Certificate and Auto-renewal

前提条件

このチュートリアルを実行する前に、いくつかのものが必要です。

sudo権限を持つ非rootユーザーのUbuntu14.04サーバーが必要です。 initial server setup for Ubuntu 14.04の手順1〜3に従って、このようなユーザーアカウントを設定する方法を学ぶことができます。

証明書を使用する登録ドメイン名を所有または制御する必要があります。 登録済みのドメイン名をまだお持ちでない場合は、多数のドメイン名レジストラーのいずれかに登録できます(例: Namecheap、GoDaddyなど)。

まだ作成していない場合は、ドメインがサーバーのパブリックIPアドレスを指すA Recordを作成してください。 これは、Let’s Encryptが証明書を発行するドメインを所有していることを検証する方法のために必要です。 たとえば、example.comの証明書を取得する場合、検証プロセスを機能させるには、そのドメインをサーバーに解決する必要があります。 このセットアップでは、ドメイン名としてexample.comwww.example.comを使用するため、both DNS records are requiredを使用します。

すべての前提条件が整ったら、Let’s Encryptクライアントソフトウェアであるcertbotのインストールに移りましょう。

[[step-1 -—- installing-let-39-s-encrypt-client]] ==ステップ1— Let’sEncryptクライアントのインストール

Let’s Encryptを使用してSSL証明書を取得するための最初のステップは、サーバーにcertbotソフトウェアをインストールすることです。 Certbot開発者は、ソフトウェアの最新バージョンのリポジトリを提供します。 そのリポジトリをパッケージマネージャーに追加しましょう。

sudo add-apt-repository ppa:certbot/certbot

追加の確認を求められます。 ENTERを押して続行します。 次に、パッケージキャッシュを更新して、新しいパッケージリストを取得します。

sudo apt-get update

そして最後に、certbotパッケージをインストールします。

sudo apt-get install certbot

certbotがインストールされたので、SSL証明書を取得する準備が整いました。

[[ステップ-2 -—-証明書の取得]] ==ステップ2—証明書の取得

Let's Encryptは、さまざまなプラグインを介してSSL証明書を取得するさまざまな方法を提供します。 a different tutorialでカバーされているApacheプラグインとは異なり、ほとんどのプラグインは、使用するWebサーバーを手動で構成する必要がある証明書の取得にのみ役立ちます。 証明書を取得するだけでインストールしないプラグインは、サーバーに証明書を発行するかどうかを認証するために使用されるため、「認証者」と呼ばれます。

Standaloneプラグインを使用してSSL証明書を取得する方法を説明します。

ポート80が開いていることを確認する

スタンドアロンプ​​ラグインは、SSL証明書を取得する非常に簡単な方法を提供します。 これは、サーバー上で小さなWebサーバー(デフォルトではポート80)を一時的に実行することで機能します。このサーバーに、Let’s Encrypt CAは、証明書を発行する前にサーバーのIDに接続して検証できます。 そのため、この方法では、ポート80が使用されていない必要があります。 つまり、ポート80を使用している場合は、通常のウェブサーバーを必ず停止してください(つまり、 http)、このプラグインを使用する前。

たとえば、HAProxyを使用している場合は、次のコマンドを実行して停止できます。

sudo service haproxy stop

ポート80が使用されているかどうかわからない場合は、次のコマンドを実行できます。

netstat -na | grep ':80.*LISTEN'

このコマンドを実行しても出力がない場合は、スタンドアロンプ​​ラグインを使用できます。

Certbotを実行する

次のコマンドを実行して、スタンドアロンプ​​ラグインを使用します。

sudo certbot certonly --standalone --preferred-challenges http --http-01-port 80 -d example.com -d www.example.com

メールアドレスを入力し、Let's Encryptの利用規約に同意するよう求められます。 その後、httpチャレンジが実行されます。 すべてが成功すると、certbotは次のような出力メッセージを出力します。

Output:IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at
   /etc/letsencrypt/live/example.com/fullchain.pem. Your cert
   will expire on 2017-09-06. To obtain a new or tweaked version of
   this certificate in the future, simply run certbot again. To
   non-interactively renew *all* of your certificates, run "certbot
   renew"
 - Your account credentials have been saved in your Certbot
   configuration directory at /etc/letsencrypt. You should make a
   secure backup of this folder now. This configuration directory will
   also contain certificates and private keys obtained by Certbot so
   making regular backups of this folder is ideal.
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

上記の出力例で強調表示された証明書のパスと有効期限を書き留めておきます。

[.note]#Note:ドメインがCloudFlareなどのDNSサービスを介してルーティングされている場合は、証明書を取得するまで一時的に無効にする必要があります。

証明書ファイル

証明書を取得すると、次のPEMエンコードファイルが作成されます。

  • cert.pem:ドメインの証明書

  • chain.pem: Let’sEncryptチェーン証明書

  • fullchain.pem:cert.pemchain.pemの組み合わせ

  • privkey.pem:証明書の秘密鍵

作成したばかりの証明書ファイルの場所を知っておくことは重要です。そのため、それらをWebサーバーの構成で使用できます。 ファイル自体は、/etc/letsencrypt/archiveのサブディレクトリに配置されます。 ただし、Certbotは、/etc/letsencrypt/live/your_domain_nameディレクトリにある最新の証明書ファイルへのシンボリックリンクを作成します。

次のコマンドを実行して(ドメイン名に置き換えて)ファイルが存在することを確認できます。

sudo ls /etc/letsencrypt/live/your_domain_name

出力は、前述の4つの証明書ファイルになります。

fullchain.pemとprivkey.pemを組み合わせます

SSLターミネーションを実行するようにHAProxyを構成する場合、HAProxyとエンドユーザー間のトラフィックが暗号化されるため、fullchain.pemprivkey.pemを1つのファイルに結合する必要があります。

まず、結合されたファイルが配置されるディレクトリ/etc/haproxy/certsを作成します。

sudo mkdir -p /etc/haproxy/certs

次に、このcatコマンドを使用して結合ファイルを作成します(強調表示されたexample.comをドメイン名に置き換えます)。

DOMAIN='example.com' sudo -E bash -c 'cat /etc/letsencrypt/live/$DOMAIN/fullchain.pem /etc/letsencrypt/live/$DOMAIN/privkey.pem > /etc/haproxy/certs/$DOMAIN.pem'

次のコマンドを使用して、秘密鍵を含む結合ファイルへの安全なアクセス:

sudo chmod -R go-rwx /etc/haproxy/certs

これで、HAProxyでSSL証明書と秘密鍵を使用する準備が整いました。

[[step-3 -—- installing-haproxy]] ==ステップ3—HAProxyのインストール

この手順では、HAProxyのインストールについて説明します。 サーバーに既にインストールされている場合は、この手順をスキップしてください。

デフォルトのUbuntuリポジトリにないHAProxy 1.6をインストールします。 ただし、PPAを使用する場合は、次のコマンドでパッケージマネージャーを使用してHAProxy 1.6をインストールできます。

sudo add-apt-repository ppa:vbernat/haproxy-1.6

ロードバランサーのローカルパッケージインデックスを更新し、次のように入力してHAProxyをインストールします。

sudo apt-get update
sudo apt-get install haproxy

HAProxyはインストールされましたが、構成する必要があります。

[[step-4 -—- configuring-haproxy]] ==ステップ4—HAProxyの設定

このセクションでは、SSLセットアップで基本的なHAProxyを構成する方法を示します。 また、Let’s Encrypt証明書を自動更新できるようにHAProxyを構成する方法についても説明します。

テキストエディタでhaproxy.cfgを開きます。

sudo nano /etc/haproxy/haproxy.cfg

次のいくつかのセクションで編集するときに、このファイルを開いたままにします。

グローバルセクション

globalセクションの下にいくつかの基本設定を追加しましょう。

最初に実行したいのは、maxconnを適切な数に設定することです。 これは、HAProxyが許可する同時接続の数に影響します。これにより、QoSに影響し、Webサーバーがクラッシュしてリクエストが多すぎないようにすることができます。 あなたの環境に合うものを見つけるために、それをいじる必要があります。 次の行(妥当と思われる値)をglobalセクションに追加します。

haproxy.cfg — 1 of 7

   maxconn 2048

次に、この行を追加して、生成される一時DHEキーの最大サイズを構成します。

haproxy.cfg — 2 of 7

   tune.ssl.default-dh-param 2048

デフォルトセクション

defaultsセクションの下に次の行を追加します。

haproxy.cfg — 3 of 7

   option forwardfor
   option http-server-close

forwardforオプションは、各リクエストにX-Forwarded-Forヘッダーを追加するようにHAProxyを設定し、http-server-closeオプションは、接続を閉じながらキープアライブを維持することにより、HAProxyとユーザー間の待ち時間を短縮します。

フロントエンドセクション

これで、frontendセクションを定義する準備が整いました。

最初に追加するものは、着信HTTP接続を処理し、それらをデフォルトのバックエンド(後で定義します)に送信するためのフロントエンドです。 ファイルの最後に、www-httpというフロントエンドを追加しましょう。 必ずhaproxy_public_IPをHAProxyサーバーのパブリックIPアドレスに置き換えてください。

haproxy.cfg — 4 of 7

frontend www-http
   bind haproxy_www_public_IP:80
   reqadd X-Forwarded-Proto:\ http
   default_backend www-backend

次に、着信HTTPS接続を処理するフロントエンドを追加します。 ファイルの最後に、www-httpsというフロントエンドを追加します。 必ずhaproxy_www_public_IPをHAProxyサーバーのパブリックIPに置き換えてください。 また、example.comをドメイン名(以前に作成した証明書ファイルに対応している必要があります)に置き換える必要があります。

haproxy.cfg — 5 of 7

frontend www-https
   bind haproxy_www_public_IP:443 ssl crt /etc/haproxy/certs/example.com.pem
   reqadd X-Forwarded-Proto:\ https
   acl letsencrypt-acl path_beg /.well-known/acme-challenge/
   use_backend letsencrypt-backend if letsencrypt-acl
   default_backend www-backend

このフロントエンドは、ACL(letsencrypt-acl)を使用してLet’s Encrypt検証リクエスト(/.well-known/acme-challenge)をletsencrypt-backendバックエンドに送信します。これにより、HAProxyサービスを停止せずに証明書を更新できます。 他のすべてのリクエストは、www-backendに転送されます。これは、Webアプリケーションまたはサイトにサービスを提供するバックエンドです。

バックエンドセクション

フロントエンドの構成が完了したら、次の行を追加してwww-backendバックエンドを追加します。 強調表示された単語をWebサーバーのそれぞれのプライベートIPアドレスに必ず置き換えてください(バックエンドサーバーの数に一致するようにserver行の数を調整してください)。

haproxy.cfg — 6 of 7

backend www-backend
   redirect scheme https if !{ ssl_fc }
   server www-1 www_1_private_IP:80 check
   server www-2 www_2_private_IP:80 check

このバックエンドが受信するトラフィックは、HTTP(ポート80)を介して、serverエントリ間でバランスが取られます。

最後に、これらの行を追加して、letsencrypt-backendバックエンドを追加します

haproxy.cfg — 7 of 7

backend letsencrypt-backend
   server letsencrypt 127.0.0.1:54321

このバックエンドは、証明書の要求と更新に使用されるLet’s Encrypt ACMEチャレンジのみを処理し、ポート54321でローカルホストにトラフィックを送信します。 Let's Encrypt SSL証明書を更新するときは、80443の代わりにこのポートを使用します。

これで、HAProxyを開始する準備ができました。

sudo service haproxy restart

[.note]#Note:haproxy.cfg構成ファイルで問題が発生した場合は、例としてthis GitHub Gistを確認してください。

Let's Encrypt TLS / SSL証明書が配置され、自動更新スクリプトをセットアップする準備が整いました。 この時点で、Webブラウザでドメインにアクセスして、TLS / SSL証明書が機能することをテストする必要があります。

[[step-5 -—- setting-up-auto-renewal]] ==ステップ5—自動更新の設定

証明書の暗号化は90日間のみ有効ですので、更新プロセスを自動化することが重要です。

証明書が期限切れにならないようにするための実用的な方法は、更新プロセスを自動的に処理するcronジョブを作成することです。 cronジョブは毎日certbotを実行し、有効期限が切れてから30日以内であれば証明書を更新します。 certbotは、更新が成功すると、特別なrenew-hookスクリプトも実行します。 この更新スクリプトを使用して、結合された.pemファイルを更新し、haproxyをリロードします。

このスクリプトを作成して、テストしてみましょう。

更新スクリプトを作成する

/usr/local/binの新しいファイルをrootとして開きます。

sudo nano /usr/local/bin/renew.sh

これは、新しい空のテキストファイルになります。 次の短いスクリプトを貼り付けて、強調表示されたドメイン名を独自のものに更新してください。

#!/bin/sh

SITE=example.com

# move to the correct let's encrypt directory
cd /etc/letsencrypt/live/$SITE

# cat files to make combined .pem for haproxy
cat fullchain.pem privkey.pem > /etc/haproxy/certs/$SITE.pem

# reload haproxy
service haproxy reload

ファイルを保存して閉じます。 このスクリプトは、正しいLet’s Encryptディレクトリに移動し、catコマンドを実行して2つの.pemファイルを1つに連結してから、haproxyをリロードします。

次に、スクリプトを実行可能にします。

sudo chmod u+x /usr/local/bin/renew.sh

次に、スクリプトを実行します。

sudo /usr/local/bin/renew.sh

エラーなしで実行する必要があります。 haproxyのリロードに関する出力が表示されます。 次に、Certbotを更新し、この更新スクリプトを実行するように構成します。

certbot構成の更新

証明書の更新に使用するcertbot renewコマンドは、certbotを最初に実行したときに作成された構成ファイルを読み取ります。 このファイルを開き、certbotがスタンドアロンhttpサーバーを実行するために使用するポートを更新して、haproxy(ポート80および443で既にリッスンしている)と競合しないようにする必要があります。 テキストエディターで構成ファイルを開きます。

sudo nano /etc/letsencrypt/renewal/example.com.conf

http01_port行を変更する必要があるため、次のようになります。

example.com.conf

http01_port = 54321

ファイルを保存して閉じます。 次に、--dry-runを指定して更新プロセスをテストし、実際には何も更新しないようにします。

sudo certbot renew --dry-run

Certbotは更新チャレンジをポート54321でリッスンし、haproxyはポート80から54321へのリクエストをプロキシします。

Cronジョブを作成する

次に、crontabを編集して、certbot renewコマンドを毎日実行する新しいジョブを作成します。 rootユーザーのcrontabを編集するには、次を実行します。

sudo crontab -e

ファイルの最後に次を追加します。

crontabエントリ

30 2 * * * /usr/bin/certbot renew --renew-hook "/usr/local/bin/renew.sh" >> /var/log/le-renewal.log

保存して終了。 これにより、毎日午前2時30分にcertbot renewコマンドを実行する新しいcronジョブが作成されます。 コマンドによって生成された出力は、/var/log/le-renewal.logにあるログファイルにパイプされます。 証明書が実際に更新されると、--renew-hookスクリプトが実行されて、結合されたPEMファイルが作成され、haproxyが再ロードされます。

結論

それでおしまい! HAProxyは現在、無料のLet's Encrypt TLS / SSL証明書を使用して、HTTPSトラフィックを安全に処理しています。

Related