Ubuntu14.04でLet’sEncryptを使用してHAProxyを保護する方法
序章
Let’s Encryptは、無料のTLS / SSL証明書を簡単に取得してインストールできる新しい認証局(CA)であり、Webサーバーで暗号化されたHTTPSを有効にします。 必要な手順のほとんどを自動化しようとするソフトウェアクライアントCertbotを提供することにより、プロセスを簡素化します。 現在、証明書の取得とインストールのプロセス全体は、ApacheWebサーバーでのみ完全に自動化されています。 ただし、Certbotを使用すると、無料のSSL証明書を簡単に取得できます。この証明書は、選択したWebサーバーソフトウェアに関係なく、手動でインストールできます。
このチュートリアルでは、Certbotを使用して無料のSSL証明書を取得し、Ubuntu14.04のHAProxyで使用する方法を示します。 また、SSL証明書を自動的に更新する方法についても説明します。
前提条件
このチュートリアルに従う前に、いくつかのことが必要になります。
sudo
権限を持つroot以外のユーザーがいるUbuntu14.04サーバーが必要です。 このようなユーザーアカウントを設定する方法については、Ubuntu 14.04 の初期サーバー設定の手順1〜3を参照してください。
証明書を使用する登録済みドメイン名を所有または管理する必要があります。 まだドメイン名を登録していない場合は、そこにある多くのドメイン名レジストラの1つに登録できます(例: Namecheap、GoDaddyなど)。
まだ作成していない場合は、ドメインがサーバーのパブリックIPアドレスを指すAレコードを作成してください。 これは、Let’sEncryptが証明書を発行しているドメインを所有していることを検証する方法のために必要です。 たとえば、example.com
の証明書を取得する場合、検証プロセスを機能させるには、そのドメインをサーバーに解決する必要があります。 この設定では、ドメイン名としてexample.com
とwww.example.com
を使用するため、両方のDNSレコードが必要です。
すべての前提条件が整ったら、Let’sEncryptクライアントソフトウェアであるcertbot
のインストールに進みましょう。
ステップ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—証明書を取得する
Let’s Encryptは、さまざまなプラグインを介してSSL証明書を取得するためのさまざまな方法を提供します。 別のチュートリアルで説明されているApacheプラグインとは異なり、ほとんどのプラグインは、使用するWebサーバーを手動で構成する必要がある証明書の取得にのみ役立ちます。 証明書のみを取得し、それらをインストールしないプラグインは、サーバーに証明書を発行する必要があるかどうかを認証するために使用されるため、「オーセンティケーター」と呼ばれます。
スタンドアロンプラグインを使用してSSL証明書を取得する方法を説明します。
ポート80が開いていることを確認します
スタンドアロンプラグインは、SSL証明書を取得するための非常に簡単な方法を提供します。 これは、サーバー上で小さなWebサーバー(デフォルトではポート80
)を一時的に実行することで機能します。これに、Let’s Encrypt CAは、証明書を発行する前にサーバーのIDに接続して検証できます。 そのため、この方法では、ポート80
が使用されていない必要があります。 つまり、ポート80
を使用している場合は、通常のWebサーバーを必ず停止してください(つまり、 http
)、このプラグインを使用する前に。
たとえば、HAProxyを使用している場合は、次のコマンドを実行して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’sEncryptの利用規約に同意するよう求められます。 その後、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
上記の出力例で強調表示されている、証明書のパスと有効期限をメモしておく必要があります。
注:ドメインがCloudFlareなどのDNSサービスを介してルーティングされている場合は、証明書を取得するまで一時的に無効にする必要があります。
証明書ファイル
証明書を取得すると、次のPEMエンコードファイルが作成されます。
- cert.pem:ドメインの証明書
- chain.pem:Let’sEncryptチェーン証明書
- fullchain.pem:
cert.pem
andchain.pem
combined - 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.pem
とprivkey.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
これで、SSL証明書と秘密鍵をHAProxyで使用する準備が整いました。
ステップ3—HAProxyをインストールする
このステップでは、HAProxyのインストールについて説明します。 サーバーにすでにインストールされている場合は、この手順をスキップしてください。
デフォルトのUbuntuリポジトリにないHAProxy1.6をインストールします。 ただし、PPAを使用する場合は、次のコマンドを使用して、パッケージマネージャーを使用してHAProxy1.6をインストールできます。
- sudo add-apt-repository ppa:vbernat/haproxy-1.6
ロードバランサーのローカルパッケージインデックスを更新し、次のように入力してHAProxyをインストールします。
- sudo apt-get update
- sudo apt-get install haproxy
これでHAProxyがインストールされましたが、構成する必要があります。
ステップ4—HAProxyを設定する
このセクションでは、SSLセットアップを使用して基本的なHAProxyを構成する方法を示します。 また、Let’sEncrypt証明書を自動更新できるようにHAProxyを構成する方法についても説明します。
テキストエディタでhaproxy.cfg
を開きます。
- sudo nano /etc/haproxy/haproxy.cfg
次のいくつかのセクションで編集するときは、このファイルを開いたままにしておきます。
グローバルセクション
global
セクションにいくつかの基本設定を追加しましょう。
最初に実行したいのは、maxconnを適切な数に設定することです。 これは、HAProxyが許可する同時接続の数に影響し、QoSに影響を与え、Webサーバーがクラッシュしてあまりにも多くの要求を処理しようとするのを防ぐことができます。 あなたの環境に何がうまくいくかを見つけるためにそれをいじくり回す必要があるでしょう。 global セクションに次の行(妥当と思われる値を含む)を追加します。
maxconn 2048
次に、この行を追加して、生成される一時DHEキーの最大サイズを構成します。
tune.ssl.default-dh-param 2048
デフォルトセクション
defaultsセクションの下に次の行を追加します。
option forwardfor
option http-server-close
forwardforオプションは、各リクエストにX-Forwarded-For
ヘッダーを追加するようにHAProxyを設定し、http-server-close
オプションは、接続を閉じながらキープアライブを維持することで、HAProxyとユーザー間の遅延を減らします。
フロントエンドセクション
これで、frontend
セクションを定義する準備が整いました。
最初に追加したいのは、着信HTTP接続を処理し、それらをデフォルトのバックエンド(後で定義します)に送信するフロントエンドです。 ファイルの最後に、www-httpというフロントエンドを追加しましょう。 必ずhaproxy_public_IP
をHAProxyサーバーのパブリックIPアドレスに置き換えてください。
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
をドメイン名(以前に作成した証明書ファイルに対応している必要があります)に置き換える必要があります。
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
行の数をバックエンドサーバーの数に合わせて調整してください)。
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
バックエンドを追加します
backend letsencrypt-backend
server letsencrypt 127.0.0.1:54321
このバックエンドは、証明書の要求と更新に使用されるLet’s Encrypt ACMEチャレンジのみを処理し、ポート54321
でローカルホストにトラフィックを送信します。 Let’s Encrypt SSL証明書を更新するときは、80
および443
の代わりにこのポートを使用します。
これで、HAProxyを開始する準備が整いました。
- sudo service haproxy restart
注: haproxy.cfg
構成ファイルで問題が発生した場合は、例としてこのGitHubGistを確認してください。
Let’s Encrypt TLS / SSL証明書が用意され、自動更新スクリプトを設定する準備が整いました。 この時点で、WebブラウザでドメインにアクセスしてTLS/SSL証明書が機能することをテストする必要があります。
ステップ5—自動更新の設定
Let’s Encryptの証明書はわずか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
行を変更する必要があるため、次のようになります。
http01_port = 54321
ファイルを保存して閉じます。 次に、--dry-run
を指定して更新プロセスをテストし、実際には何も更新しないようにします。
- sudo certbot renew --dry-run
Certbotはポート54321で更新チャレンジをリッスンし、haproxyはポート80から54321へのリクエストをプロキシします。
cronジョブを作成する
次に、crontabを編集して、certbot renew
コマンドを毎日実行する新しいジョブを作成します。 rootユーザーのcrontabを編集するには、次のコマンドを実行します。
- sudo crontab -e
ファイルの最後に以下を追加します。
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トラフィックを安全に処理しています。