事前準備・前提条件
今回は客先のサーバーの環境を前提条件に進めていく。
■ centosのバージョン確認
cat /etc/redhat-release
- CentOS 6.x
- Apache 2.2系
既存のサーバーに手を加えるに当たって気をつけておく点として、ApacheにすでにSSLが適用されている場合、再起動時にパスフレーズ入力を求められる。もしパスフレーズがわからなければApacheが起ち上がらなくなるので事前に確認する必要がある。
まずはhttpd/conf.dの中を覗いてSSLを利用している部分がないかを確認する
mod_sslが入ってなければそもそもSSLを利用していない。
■ mod_sslが入っていない場合はインストールする
$ yum -y install mod_ssl
certbotの準備
certbotを利用するにあたってpython2.7が必要なので、準備します。準備方法はいろいろありますが、python2.6が標準で入っていたため、依存関係崩さないように2.6と2.7を共存させる。
■ Software Collectionを更新
$ yum install centos-release-scl-rh
$ python --version
$ yum install rh-python37
$ vi /etc/profile.d/python37.sh
#!/bin/bash
source /opt/rh/rh-python36/enable
export X_SCLS="`scl enable rh-python36 'echo $X_SCLS'`"
■ profileを読み込む(~/.bashrcなどでもよい)
$ source ~/.profile
■ pipをupdate
$ pip install -U pip virtualenv cryptography
(もし/opt/eff.org/certbot/が既にあれば削除して再作成)
$ rm -r /opt/eff.org/certbot/
■ certbotをインストール
$ curl https://dl.eff.org/certbot-auto -o /usr/bin/certbot-auto
curl: (35) SSL connect error
そのままcurlでインストールしようとしたらエラーが出た。どこで躓いているのかを確認してみる。
■ どこでつまづいているのかエラー内容を確認
$ curl -L --verbose https://dl.eff.org/certbot-auto -o /usr/bin/certbot-auto
* About to connect() to dl.eff.org port 443 (#0)
* Trying 151.101.108.201... connected
* Connected to dl.eff.org (151.101.108.201) port 443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* CAfile: /etc/pki/tls/certs/ca-bundle.crt
CApath: none
* NSS error -12190
* Closing connection #0
* SSL connect error
curl: (35) SSL connect error
諸々不具合が出ているようだが、まずはcurlのバージョンが古いだけの場合が多いようなのでとりあえずアップデートする。
■ curlをアップデート
$ yum update curl
$ yum update nss
■ certbotの依存関係を処理するのに使われるパッケージをアップデート
$ yum update libcurl
■ certbotをインストール(再)
$ curl https://dl.eff.org/certbot-auto -o /usr/bin/certbot-auto
■ certbot-autoに実行権限を与える
$ chmod 700 /usr/bin/certbot-auto
■ certbot-autoを動かすと依存パッケージが勝手にインストールされる
$ certbot-auto --version
certbot-autoに何かしらの動作をさせると初回動作時にインストールが行われるがここでエラーが出る場合も
■ certbot-autoをインストール
$ certbot-auto --version
Bootstrapping dependencies for RedHat-based OSes... (you can skip this with --no-bootstrap)
yum is /usr/bin/yum
yum is hashed (/usr/bin/yum)
Failed to set locale, defaulting to C
Loaded plugins: fastestmirror, priorities, refresh-packagekit, security
Setting up Install Process
...(中略)...
Error: Package: python-devel-2.6.6-66.el6_8.x86_64 (updates)
Requires: python-libs(x86-64) = 2.6.6-66.el6_8
Installed: python-libs-2.6.6-68.el6_10.x86_64 (@sl-security)
python-libs(x86-64) = 2.6.6-68.el6_10
Available: python-libs-2.6.6-64.el6.x86_64 (base)
python-libs(x86-64) = 2.6.6-64.el6
Available: python-libs-2.6.6-66.el6_8.x86_64 (updates)
python-libs(x86-64) = 2.6.6-66.el6_8
You could try using --skip-broken to work around the problem
You could try running: rpm -Va --nofiles --nodigest
Could not install OS dependencies. Aborting bootstrap!
どうやらRedHat系列のOS起動時の依存関係が云々かんぬんということらしいが、(you can skip this…)とあるのでスキップしちゃう。
$ certbot-auto --version --no-bootstrap
certbot 1.9.0
すんなりインストール完了。
これでcertbotの準備はできた。
Apache2.2の設定①
wwwディレクトリ配下の各ドメインのドキュメントルートは基本的にディレクトリ名をドメインにしているという前提で説明していきます。ディレクトリ名をドメイン名にしていない場合は適宜読み替えてください。
■ 認証用ファイルを設置するディレクトリを作成する
mkdir /var/www/certbot/(任意のドメイン名など)
■ Apacheのバーチャルホスト設定ファイルに追記する
vi /etc/httpd/conf.d/(任意のドメイン).conf
<VirtualHost *:80>
DocumentRoot /var/www/(ドキュメントルートのディレクトリパス)
ServerName (設定対象のドメイン名)
...
# for Let's Encrypt
Alias /.well-known /var/www/certbot/(任意のドメイン名)/.well-known
<Directory /var/www/certbot/(任意のドメイン名)>
Require all granted
</Directory>
</VirtualHost>
バーチャルホストの設定ファイルは/etc/httpd/conf.dディレクトリ内に.conf拡張子で置いておくと勝手に読み込んでくれる。ドメイン毎に1つのファイルで書いてもいいけど、SSLの設定ファイルも細かく切り分けて管理すると便利。
■ バーチャルホストファイル構成例
example.com.conf ←ポート80の設定用
example.com.ssl.conf ←ポート443(SSL)の設定用
example.com.ssl.conf_200320 (バックアップなどは拡張子をconfから変更することで読み込まれなくなる)
バーチャルホストの設定ができたら設定をリロードする
ssl.conf内のvirtualhostディレクティブをごそっと削除
# apachectl -t
CentOS7
# systemctl reload httpd
CentOS6
# service httpd reload
Let’s Encrypt証明書を取得
証明書を取得するコマンド
certbotの準備ができたら、早速証明書を取得する。
■ 証明書を取得する
# time /usr/bin/certbot-auto certonly \
--webroot \
-w /var/www/certbot/sample.domain.jp \
-d sample.domain.jp \
--preferred-challenges http \
-m <登録するメールアドレス>
■ メールアドレスを登録しない場合(--register-unsafely-without-email)
# time /usr/bin/certbot-auto certonly \
--webroot \
-w /var/www/certbot/sample.domain.jp \
-d sample.domain.jp \
--preferred-challenges http \
--register-unsafely-without-email
■ 取得テストをする場合(--dry-run)
# time /usr/bin/certbot-auto certonly \
--webroot \
-w /var/www/certbot/sample.domain.jp \
-d sample.domain.jp \
--preferred-challenges http \
--register-unsafely-without-email \
--dry-run
■ 一つの証明書で複数ドメインを認証する場合(適宜、-w,-dを増やす)
# time /usr/bin/certbot-auto certonly \
--webroot \
-w /var/www/certbot/sample.domain.jp \
-d sample.domain.jp \
-w /var/www/certbot/sample2.domain.jp \
-d sample2.domain.jp \
-w /var/www/certbot/www/sample.domain.jp \
-d www.sample.domain.jp \
--preferred-challenges http \
--register-unsafely-without-email
–dry-runで証明書リクエストテスト
まずは取得テスト(dry-run)を行ってから取得するようにしましょう。取得時に上手く動かなかったり変な状態で取得してしまうと同一ドメインに対する証明書リクエストの申請上限(10回くらいだった気がする)に引っかかり1週間ほど認証サーバーから拒否されて再取得ができなくなります。
そこそこ長いコマンドなので僕はシェルスクリプトに記述してそれを実行している。–dry-runの切り替えも楽。
#!/bin/bash
time /usr/bin/certbot-auto certonly \
--webroot \
-w /var/www/certbot/sample.domain.jp \
-d sample.domain.jp \
--preferred-challenges http \
--register-unsafely-without-email \
--dry-run
–dry-runでsuccessしたら–dry-runを削除(コメントアウト)して実行する。
■ --dry-runで実行
# bash get_sslcert.sh
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator webroot, Installer None
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for sample.domain.jp
Using the webroot path /var/www/certbot/sample.domain.jp for all unmatched domains.
Waiting for verification...
Cleaning up challenges
IMPORTANT NOTES:
- The dry run was successful.
real 0m7.321s
user 0m2.797s
sys 0m0.286s
証明書を取得
challenge failed for domain sample.domain.jpなどと出たら認証がうまくいっていない。
考えられる原因はタイポの他に、認証用ファイルの設置ディレクトリが未作成などが考えられる。
■ 本番実行(--dry-runをコメントアウト)
# bash get_sslcert.sh
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator webroot, Installer None
Registering without email!
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must
agree in order to register with the ACME server at
https://acme-v02.api.letsencrypt.org/directory
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(A)gree/(C)ancel: a ←利用規約に同意
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for sample.domain.jp
Using the webroot path /var/www/certbot/sample.domain.jp for all unmatched domains.
Waiting for verification...
Cleaning up challenges
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/sample.domain.jp/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/sample.domain.jp/privkey.pem
Your cert will expire on 2021-02-03. To obtain a new or tweaked
version of this certificate in the future, simply run certbot-auto
again. To non-interactively renew *all* of your certificates, run
"certbot-auto 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
real 0m11.163s
user 0m3.463s
sys 0m0.325s
「- Congratulations! Your certificate and chain have been saved at: ~」
と出力されれば、証明書の取得は成功です。
失敗した場合は、エラーメッセージや、デバッグログ /var/log/letsencrypt/letsencrypt.log を参照して解消。
取得した証明書は以下で確認できる。
# ls -l /etc/letsencrypt/live/sample.domain.jp/
- 証明書: /etc/letsencrypt/live/sample.domain.jp/cert.pem
- 秘密鍵: /etc/letsencrypt/live/sample.domain.jp/privkey.pem
- 中間証明書: /etc/letsencrypt/live/sample.domain.jp/chain.pem
- 証明書+中間証明書: /etc/letsencrypt/live/sample.domain.jp/fullchain.pem
Apache2.2の設定②
SSLのバーチャルホスト設定を追加
証明書が取得できたらいよいよバーチャルホスト設定にSSL用のものを加える
■ SSL用のバーチャルホスト設定を作成
# vi /etc/httpd/conf.d/sample.domain.jp.ssl.conf
<VirtualHost *:443>
DocumentRoot /var/www/sample.domain.jp/public_html
ServerName sample.domain.jp
...
<Directory /var/www/certbot/sample.domain.jp>
Require all granted
</Directory>
...(↑ここまでは適宜既存の設定に合わせて設定)
...(↓ここの3行が証明書の場所を指定している)
SSLCertificateFile /etc/letsencrypt/live/sample.domain.jp/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/sample.domain.jp/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/sample.domain.jp/chain.pem
...
</VirtualHost>
# apachectl -t
# service restart httpd
ここまででSSL化は完了。https://sample.domain.jpにアクセスすると証明書が有効になったサイトが表示される。
※Apache2.2の場合、ssl.confにNameVirtualHost *:443の記述を足しておかないとSSLでVirtualHostが効かないので注意。
常時SSL化
しかし、これだとhttp://~でアクセスしたときはSSL化されていない状態のページにもアクセスできてしまうため、http://でアクセスしてもhttps://に切り替わるように設定をする。
サイトのドキュメントルートの.htaccessの設定に次の3行を加筆する。
RewriteEngine on
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
http://sample.domain.jpでアクセスしてもhttps://~に切り替わるようになっていればOK。
ページ構造内部や画像リンクなどが常時SSL化によって影響を受けて表示されない場合などがあるので表示の確認をして設定完了。
Let’s Encryptの更新設定
更新作業
Let’s Encryptは証明書の有効期限が90日と短いため更新作業が頻繁に必要になる。
更新はcertbot-auto renewで簡単に行えるが、この作業を定期的に行うのは煩雑なので、自動更新スクリプトを用意してcronに処理をさせたい。そのため、ログにもUpdateのことが残るようにちょっと装飾を加えて、httpdの再起動までセットで行う。
次のようなシェルスクリプトを用意した。
証明書の更新の部分に–dry-runをつけているので、自動化を組み込む作業時は–dry-runにて運用するのが好ましいだろう。
最後は–dry-runをコメントアウトして最終確認をして自動化させる。
#!/bin/bash
CERTBOT_CMD=/usr/bin/certbot-auto
WEBSERVER_RESTART_CMD="service httpd restart"
echo "===== Update SSL Certfile ====="
echo "`date` Update SSL Certfile start"
# 証明書の更新
${CERTBOT_CMD} renew \
--post-hook "${WEBSERVER_RESTART_CMD}" \
--dry-run
LE_STATUS=$?
# 証明書の取得に失敗したときはメールで通知
if [ "$LE_STATUS" != 0 ]; then
echo "Update SSL Certfile failed"
fi
echo "`date` Update SSL Certfile end"
# EOF
自動更新スクリプト
自動化処理は先ほどのupdate_sslcert.shをcronに定期実行させるだけだ。
■ update_sslcert.shに実行権限を付与
# chmod 755 /root/bin/update_sslcert.sh ←設置した場所によってパスは適宜
0 5 * * 0 root PATH="/sbin:$PATH" /root/work/update_sslcert.sh 1>> /var/log/update_sslcert.log 2>&1
ちなみにここでは毎週月曜日の朝5時に更新確認を行うように設定。
Let’s Encryptは証明書期限が残り30日を切ると更新される。
コメント