4.7.2 apache への SSL 設定

2018年5月1日

 apache が入ったところで、サイトの常時SSL(TLS)化を実施します。暗号化通信だけならオレオレ証明書でも良いのですが、最近はブラウザではねられる事も多いので、ちゃんと認証出来る証明書を取得します。昔は証明書取得には手間もお金もかかりましたが、現在ではドメイン証明(DV)なら個人でも無料で簡単に取得出来ます。
 現在(2018/4/13)の環境は、以下の通りです。
・FreeBSD 11.1-RELEASE-p9
・apache24-2.4.33
・PHP71-7.1.16

1.SSL証明書の取得と設定

 今回SSL証明書の発行は2016年4月12日に正式サービスを開始した Let’sEncrypt にお願いします。Let’sEncrypt については、参考リンクをご参照ください。
 Let’sEncrypt による証明書発行は、Python で書かれた certbot と呼ばれるツールが提供されており、FreeBSD でも pkg 及び ports で提供されています。

(1)certbot のインストール
 今回は、ports でインストールしました。ports make前に一応 ports ツリーを最新に更新します。ports は、security/py-certbot で、py27-certbot-0.13.0_2,1 が入りました。makeのconfigは全てデフォルト(全てOK選択)です。

(2)SSL/TLS証明書取得
 certbot を実行して SSL/TLS証明書を発行してもらいます。

(3)証明書の更新
 取得した証明書は90日で失効してしまいますので、定期的に更新処理が必要です。以下の更新コマンドを cron 等に設定して定期的に更新します。

 システム更新等で SSL 情報を引き継ぐ場合は、/usr/local/etc/letsencrypt 下全てをコピーする必要がありますが、シンボリックリンクを含んでいるので、tar や cpio で構造を壊さずにコピーする必要があります(単純コピーだと更新時にエラーとなります)。

2.apache の設定

 apache の SSL 設定を行います。/usr/local/etc/apache24/extra/httpd-ssl.conf をエディタで開き、以下の様に設定します。

 次に /usr/local/etc/apache24/httpd.conf を変更します。

3.apache再起動と確認

 設定が終わったら、ポート443で通信出来る様に、ファイアウォールやルータの穴あけを忘れずに行います。
 ついでに、FreeBSDで提供されているアクセプト・フィルターのロード(accf_http.koとaccf_data.ko)を行う様にrc.confへ追加します。これは、apacheのドキュメントによると

Listen しているソケットに対して、OS が固有に持っているプロトコルについての最適化を 有効にするディレクティブです。大前提となる条件は、データが受信されるか HTTP リクエスト全体がバッファされるかするまで、カーネルがサーバプロセスに ソケットを送らないようになっている、

 そうで、動作の高速化が期待出来るそうです。(まあ、うちの様なアクセス数が少ない野良サーバには、あまり関係しないんですが、一応ONと言う事で)
 /etc/rc.conf に以下の様に追加して、apacheを再起動します。

 ブラウザから当該サイトを https://~~~ でアクセスして鍵マークまたは Chorme ならアドレスバーに「保護された通信」と出てくればOKです。Chormeでの証明書の確認は、「PF12」を押下してデベロッパーツールを表示させ「Security」タグをクリック、「View certifcate」ボタンを押せば表示されます。

4.http/2.0とhttpsへのリダイレクト

 ここでは、HTTP/2の設定を行います。HTTP/2はサーバ負荷が小さく、高速通信が可能なHTTP/1.1の後継プロトコルで、SSL/TLS 通信が必須となります。
 モジュールは、mod_http2-devel で pkg で入れてしまいます。

 devel なのでまだ開発中の様です。次に、apache に読み込ませる為、httpd.conf と httpd-ssl.conf に追記します。

 http で接続に来たクライアントに恒久的に https に変わった事を知らせ、リダイレクトするように設定します。こちらでは、複数のバーチャルホストを建てているため、httpd-vhosts.conf の 80 番ポートの場所に記述します。

 apache をリスタートして、当該サーバへ http でアクセスし、https へリダイレクトされること、また、ログ等により HTTP/2 で通信していることを確認します。

5.問題発生

(2017/07/17)
 apache-2.4.27 で mpm_prefork での HTTP/2.0 はサポートされなくなり、mpm_event へ変更。それに伴い PHP も php-fpm によるCGI 起動に変更しました。
 これにより mod_http2 で HTTP/2.0 で通信しても今のところ下記の様に落ちることは無くなりました。
(2017/06/25)

 下記の問題は、apache の mod_http2 に変更したら落ちることはなくなりました。
頻度は減ったものの落ちることに変わりなく、mod_http2 も解除して様子見です。


pkg で入れた apache の場合、HTTP2 サポートが入っていない場合が有りますので、ports から HTTP2 サポートを有効にして入れ直しました。


 さて、しばらくこの設定で動かして様子を見ていたのですが、httpd-error.log に数時間に1回位 httpd の子プロセスが signal Segmentation fault (11) で落ちていることがわかりました。wordpress での編集、操作中や、外部からの参照時も同様に落ちてます。
 なんか設定間違ったんだろうなと色々見直してもわからず、httpd で core ファイルを吐くように設定して、gdb でスタックトレースを取りました。 
 その結果、落ちるときは必ず、mod_h2 -> PHP 関数へ制御が渡った後で落ちてます。wordpress のプラグインを外したり、PHPの設定見たり、mod_hhtp2 をportsから最新を入れ替えてみたりしましたが効果がありません。

 仕方がないので、現在消極的な解決に走り、 mod_http2 は外しています。
 サーバ環境が落ち着いてきれいにしてから、もう一度トライです。

6.おまけ

 apache でのコアダンプ出力設定は以下の様に行います。
 ・httpd.conf に CoreDumpDirectory /tmp を追加。
 ・ulimit -c unlimited を実行。(デフォルトunlimited になっているはずです)
 ・sysctl kern.sugid_coredump=1 に設定。

 apache をリスタートする。コアダンプは、/tmp/httpd.core に出力されるます。

【参考にさせて頂いたサイト様】
Let’s Encrypt
Let’s Encrypt 総合ポータル
無償SSLサーバー証明書Let’s Encryptの普及とHTTP/2および常時SSL化
Let’s Encrypt編 – Apache 2.4系でHTTP/2対応サーバを構築してみるテスト
FreeBSD 11にて、Apache + SSL(Let’s Encrypt) + HTTP/2を動かす。 – 有効な無駄知識を…?
常時SSL化(https)するときのHSTS設定の方法と注意点 | ウェブマスターがウェブのことを書いたら
HTTP Strict Transport Security – Web セキュリティ | MDN


2018/05/01:改定 /usr/local/etc/letsencrypt のコピー時の注意を追加
2018/04/18:改定 apache24-2.4.33 へ変更、ssl.conf の VirtualHost 記述を *:443 に変更
2017/07/17:改定 mpm を prefork から event へ、php を php-fpm 導入でsegfault しなくなった旨追記
2017/06/25:改定 mod_http2 でも seg fault 発生。使用PHPバージョン記載
2017/06/18:初版


FreeBSDへ  サイトTOPへ

Posted by null-a