【ISSUE】dockerとcloudflareを使ってWebサイトを簡単にSSL化対応(ワイルドカード証明書) & 面倒な証明書更新も自動化してみた
2024年12月23日 17:28
Chromeの開発元であるGoogleは以下のような声明を出しました。
(引用元: https://security.googleblog.com/2019/10/no-more-mixed-messages-about-https_3.html)
Today we’re announcing that Chrome will gradually start ensuring that https:// pages can only load secure https:// subresources. In a series of steps outlined below, we’ll start blocking mixed content (insecure http:// subresources on https:// pages) by default. This change will improve user privacy and security on the web, and present a clearer browser security UX to users.
本日、Chrome では、https:// ページが安全な https:// サブリソースのみを読み込むことができるようにすることを段階的に開始することを発表しました。以下に概説する一連の手順で、混合コンテンツ ( https:// ページの安全でない http:// サブリソース) をデフォルトでブロックするようになります。この変更により、ウェブ上でのユーザーのプライバシーとセキュリティが改善され、より明確なブラウザセキュリティUXをユーザーに提示することができます。
混合コンテンツとは、https内に存在するhttpなコンテンツのことを指します。
つまり「https://xxxxxxxxx.com/」というセキュアなサイト内で「http://yyyyyyyyyyy.com/image/test.png」のようなセキュアでないコンテンツを呼び出している状態を意味します。
つまり、httpなサイトはChromeで閲覧できなくなる可能性があるということです。
さらにこの問題が顕著なのは、日本におけるChromeの利用率が高いという点です。
(参照元: https://lab.syncer.jp/Statistic/Browser/2019/10/)
社内だけのサービス(退勤管理やソース管理など)だからといって、セキュア化していないとアクセスできない。なんてことにならないように社内のネットワーク整備をすることにしました。
では、社会人1年目、新卒入社の筆者が社内ネットワーク整備に奮闘した一部始終をどうぞ!!
→ 社内サービスがDocker on CentOS7で動いてた
→ 無料で使えるSSL証明書。90日で期限が切れるため更新が必須
→ ワイルドカード証明書を発行するのにDNSレコードを変更する必要があるため、無料で使えるCloudflareを採用。(このためだけにNSを変更したといっても過言ではない)
→ Let's Encryptの環境がさくっと作れるDocker環境。大体のDNS Providerに対応してて、それぞれの設定方法や実行方法が書いてあってありがたい。
(対応してるDNS Provider一覧はこちら)
https化へのざっくりとしたフローはこちらです。
→ いままではIPアドレス、ポート指定のアクセスだったので、サービスが増えると何かと面倒
2. ドメインのネームサーバー(NS)をCloudflareに変更
→ 現在運用していたところではDNSレコードの書き換えが制限されていた & API経由での書き換えができなかったため
3. Cloudflareでソーン編集用APIアクセスキーを作成
4. 社内サービスコンテナ内で自動更新スクリプト等の作成
5. Nginxなどに証明書を食わせる
今回は検証用の個人的なドメイン(choipre.com)(Google Domains)を使って解説します。
ドメイン取ったけど、個人サービスが完成していないので、何しても大丈夫だし。
!! 注意 !!
設定を間違えるとサイトにアクセスできなくなったりする可能性があります。必ず変更点(Diff)などはメモするようにしておいた方が、万が一のためです。バックアップなどを取りつつ作業を進めることをおすすめします。
これまで、社内サービスにはIPアドレスを使ってアクセスしていました。そのためhttps化できず、httpな状態で運用していました。まずは、社内サービスへのアクセスをサブドメインでアクセスできるようにするため、社内DNSを整備します。ドメインは、会社HPなどで元々利用しているものを利用しました。
社内だけで使えるサービスやシステムを複数運営していると、IPアドレスでのアクセスは大変になってきます。
そこで、社内サービスにもドメインを使ってアクセスできるように社内DNSを整備しました。
構築後のネットワーク図は以下のような感じになります
DNSはDockerを使って構築します。CoreDnsというDocker-imageが公開されているので、そちらを利用します。フォルダ構成としては以下の感じです。
どのドメインとIPアドレスが紐づくかをhostsファイルに記述します。Corednsの設定はファイルはCorefileというファイルに記述します。
docker-compose.ymlがあるディレクトリで以下のコマンドを流すと、DNSが起動します。
docker-composeを走らせたPC(192.168.0.100)へ各クライアントのDNS解決先を向けることでローカルのIPに対してもドメインでアクセスすることができるようになります。
なぜNSをCloudflareに変更したかというと、CloudflareではAPIを使ってドメインのゾーン情報(A, AAAA, TXTなどのDNSレコード情報)を書き換えることができます。
(参考: https://api.cloudflare.com/#zone-subscription-zone-subscription-details)
この仕組みを利用して、スクリプト上でワイルドカードのSSL証明書を発行するのに必要なレコード内容を自動で書き込みたかったからです。
(証明書更新する度に手動でDNSレコードに追記したり、削除したりするのって面倒だし、ネットワークの知識がない人が更新しないといけないってなったときに、このコマンド一発叩けばいいよ!の方がいいよね?)
Cloudflareのアカウントを持っていない人はアカウント作成してください。
アカウント作成後、トップ画面に 【サイトを追加する】 を押します。
(※ 画像は既に登録済みのドメインがあるため、Cloudflareの管理下にあるドメイン一覧がありますが、初期登録後の人は何も表示されていません。)
Cloudflareで管理したいドメインを入力します。
プラン選択画面が表示されるので 【Freeプラン】 を選択します。
(Freeプランでここまで出来るってCloudflare様様...)
ドメインの登録が完了すると、現在設定されているDNSレコードを読み取って、Cloudflareに書き込み準備をしてくれます。このときにDNSレコードを修正することもできますが、必要がない人はそのまま 【続行】 します。
ただし、AレコードとMXレコードが同一の場合、AレコードをCloudflareのプロキシから外す必要があります。プロキシから外してDNS解決のみにしないとメールサーバーが正常に動作しないためです。
(参考: Cloudflareの使用時にメールが配信不能になる - メール関連のDNSレコード)
Cloudflareに取り込むDNSレコードの設定が終わったら、ドメインのNSをCloudflareに変更するように促されます。
各ドメインの管理画面からドメインのNSを変更します。今回の検証用ドメインはGoogle Domainsで取得しているため、Google Domainsの設定画面から変更します。
ドメインのNS変更が終わったら、Cloudflareで引き続き設定を行います。ここでは、ドメインへのアクセス、コンテンツのキャッシュ・圧縮設定ができます。利用に応じた設定を行ってください。
検証用ドメインでは、以下のように設定しました。
次にNSレコードのチェックをします。既にNSの変更が検知できている場合は、以下のような表示になります。
まだ、検知できていない場合は以下のような表示になります。ドメインの設定がネットワーク全体に浸透するまでは24~48時間程かかります。Cloudflareでチェックしても変更されていなかった場合は、少し時間をおいてください。ちなみに、Cloudflareで正常にNSが変更されていることを検知すると、アカウント登録時に設定したメールアドレスに通知がきます。
legoのライブラリを利用するために必要な、CloudflareのDNSゾーン情報APIアクセスキーを作成します。キーは2種類作成します。
ゾーン情報の【DNS編集キー】と【ゾーン編集キー】です。Cloudflareのアカウント設定のAPIトークンから作成することができます。
まず、APIアクセスキーを作成する前に、画面下部にある「Global Api key」も取得しておきましょう。4.のdocker-compose.ymlに記述する必要があるためです。
アクセスキーを作成する際に、いくつかテンプレートが用意されています。今回は【ゾーンDNSを編集する】というテンプレートを編集して利用します。テンプレートを利用せずに0から作成することもできますが、慣れてから使うか、似たテンプレートを変更したほうが無難そうです。
1つのトークンに対して、複数の権限を付与することができますが、トークンが増えてくると管理がしづらくなるので、1トークン1権限で運用することとします。アクセス許可に以下を、それぞれ設定して2つのトークンを作成します。
→ ゾーン:DNS:編集
→ ゾーン:ゾーン:編集
→ 包含:特定のゾーン:ワイルドカード証明書を発行したいドメイン
トークン作成を進めると、以下のような画面が表示されます。このときに表示されるトークンをメモしてください。ここで表示されたトークンは、画面にもあるように再表示されません。そのため、必ずメモするようにしてください。メモし忘れたら、APIトークンを削除して、再作成してください。
会社の社内サービスが動いているDockerでは、以下のような運用がされています。
このことから、サービスを立ち上げるときにSSL証明書の更新処理を走るようにしておけば、最低週に1回は確認することになり、更新忘れによる証明書失効を防ぐことが出来ると考えました。サービス自体がDockerで運用されているため、SSL更新処理もDocker化して、Serviceとして登録する方向にしました。
lego(https://go-acme.github.io/lego/)を使ったSSL証明書更新用Dockerは以下のように設定しました。
docker-compose.yml を作成して、docker-composeを実行します。
実行が終わると、以下のようなログが流れ、/opt/cert
配下に証明書本体が格納されているディレクトリと、更新に必要なアカウント情報が含まれているディレクトリが生成されます。
この生成されたフォルダで、accountsフォルダは今後証明書を更新していくなかで必要になるフォルダです。証明書類はcertificatesに保管されています。
「_.choipre.com.crt」がchoipre.comのワイルドカード証明書になります。
一度、証明書発行を実行したので、今後は更新という処理を行う設定にしておく必要があります。そのため、docker-compose.ymlを以下のように変更します。
変更点は、run
から renew
コマンドに変更することです。パラメーターとして --days
を指定することで指定した日数を切ってから更新させることができます。
この、docker-composeの実行をcronなどに設定することで自動更新を行えるようになります。
4.で生成した証明書をNginxに適用していきます。証明書類は/opt/cert配下にあるものとします。
Nginxの設定ファイルに以下の記述を追記します。追記場所はNginxの設定ファイルの使用したいServer設定の中です。デフォルト構成を利用している人は server{ ... }
の中に追記します。
記述ができたら、Nginxのプロセスを再起動します。Nginxのプロセスを再起動したら、対象のアドレスに対してhttpsアクセスをすると証明書が適用されていることが分かります。
以上で、自動更新可能なワイルドカード証明書発行の実装が終わりました。
初期設定は大変ですが、今後はあらゆるサブドメインに対してSSL通信を行うことができます。これでChromeでhttpコンテンツが閲覧できなくなっても、安心ですね。
[cv:issue_marketplace_engineer]
診断を受けるとあなたの現在の業務委託単価を算出します。今後副業やフリーランスで単価を交渉する際の参考になります。また次の単価レンジに到達するためのヒントも確認できます。