HTTP/2 対応の WordPress サイト設定メモ【Nghttp2 (nghttpx) + CentOS 7】

Linux
スポンサーリンク

Nghttp2 のプロキシー nghttpx を使って、HTTP/2 対応の WordPress サイトを設定した時のメモです。nghttpx は、HTTP/2 リクエストを HTTP/1.1 などのリクエストに変換してくれる、便利なプロキシーです。今回は、フロントエンドで HTTP/2 リクエストを nghttpx が受け取り、 バックエンドのWEBサーバ(Apache)に、HTTP/1.1リクエストを送信する構成で設定してみました。

(更新)2017年5月14日 各種インストール手順を最新版に更新しました。

nghttpx には色々な動作モードがあり、今回設定するリバースプロキシーとして使えますし、クライアントプロキシーとしても動作します。詳細は、Nghttp2 の開発者 tatsuhiro-t さんが「http2.0 - HTTP/2 & SPDY プロキシー nghttpx を使う - Qiita」で、分かりやすく解説されています。

構成図

nghttpx と Apache は、同じサーバで稼働させます。
nghttpx-01

開発ツールのインストール

サーバOSは CentOS7.3 (1611) です。Nghttp2(nghttpx) はソースからコンパイルしますので、基本コマンドと開発ツールをインストールしておきます。

yum -y groupinstall base
yum -y groupinstall development

OpenSSL 1.0.2 のインストール

ALPN(Application-Layer Protocol Negotiation)に対応している、OpenSSLバージョン1.0.2以上をインストールします。

Google Chrome バージョン51以降は、NPNが削除され、ALPNのみ対応となったようですので、WEBサーバでHTTP/2を使うには、事実上OpenSSL1.0.2以上が必須になります。
Transitioning from SPDY to HTTP/2 | Chromium Blog

 
まずはじめに OpenSSLのコンパイルに zlib を使うので、インストールしておきます。

yum -y install zlib-devel

OpenSSLのインストール(そこそこの時間がかかります)

cd /usr/local/src/
wget https://www.openssl.org/source/openssl-1.0.2k.tar.gz
tar xvzf openssl-1.0.2k.tar.gz
cd openssl-1.0.2k/
./config --prefix=/usr/local/openssl-1.0.2k shared zlib
make depend
make
make test
make install

OpenSSL1.0.2 のライブラリにパスを通しておきます。

echo /usr/local/openssl-1.0.2k/lib > /etc/ld.so.conf.d/openssl102k.conf
ldconfig

Nghttp2(nghttpx)のインストール

Nghttp2 が必要とするライブラリのインストール

yum -y install libev-devel c-ares-devel

Nghttp2 のダウンロード
※頻繁にバージョンアップされているようです。ダウンロードの前に最新リリースを確認しましょう。
https://github.com/tatsuhiro-t/nghttp2/releases/latest

cd /usr/local/src/
wget https://github.com/nghttp2/nghttp2/releases/download/v1.22.0/nghttp2-1.22.0.tar.gz

Nghttp2 のインストール。環境変数 OPENSSL_CFLAGS と OPENSSL_LIBS に先ほどインストールした、OpenSSL1.0.2 のディレクトリパスを指定してコンパイルします。また nghttpx をコンパイルするため「-enable-app」オプションを付けます。

tar xvzf nghttp2-1.22.0.tar.gz
cd nghttp2-1.22.0/
env OPENSSL_CFLAGS="-I/usr/local/openssl-1.0.2k/include" OPENSSL_LIBS="-L/usr/local/openssl-1.0.2k/lib -lssl -lcrypto" ./configure -enable-app
make
make install

/usr/local/bin/ 下に、「nghttpx」などの Nghttp2 のコマンド群がインストールされます。

SSLサーバ証明書(自己署名)の作成

Google Chrome や Firefox など、主要なWEBブラウザが、HTTP/2 接続には HTTPS 暗号化通信を必須としているため、SSLサーバ証明書が必要になります。

(2015年12月15日追記)正規の認証局が発行した、サーバー証明書を無料で取得できるようになりました。よければご参照ください → Let's Encrypt サーバー証明書の取得と自動更新設定メモ

・秘密鍵の作成

openssl genrsa 2048 > server.key

・CSR(証明書署名要求)の作成

openssl req -new -key server.key > server.csr
---下記を入力--------------------------- 
Country Name (2 letter code) [XX]:JP 
State or Province Name (full name) []:<空エンター> 
Locality Name (eg, city) [Default City]:<空エンター> 
Organization Name (eg, company) [Default Company Ltd]:<空エンター> 
Organizational Unit Name (eg, section) []:<空エンター> 
Common Name (eg, your name or your server's hostname) []:<ドメイン名> 
Email Address []:<空エンター> 

Please enter the following 'extra' attributes 
to be sent with your certificate request 
A challenge password []:<空エンター> 
An optional company name []:<空エンター> 
------------------------------

・SSLサーバ証明書の作成(有効期限10年)

openssl x509 -days 3650 -req -signkey server.key < server.csr > server.crt

・秘密鍵とSSLサーバ証明書を適切な場所に移動

mv -i server.key /etc/pki/tls/private/ 
mv -i server.crt  /etc/pki/tls/certs/

・セキュリティ確保のため nghttpx の実行ユーザ「nghttp2」を作成

useradd -d /run/nghttp2 -s /sbin/nologin nghttp2

・秘密鍵とSSLサーバ証明書のオーナーを「nghttp2」ユーザに変更

chown nghttp2:nghttp2 /etc/pki/tls/private/server.key
chown nghttp2:nghttp2 /etc/pki/tls/certs/server.crt
chmod 600 /etc/pki/tls/private/server.key 
chmod 600 /etc/pki/tls/certs/server.crt

・CSRを削除

rm server.csr

nghttpx の設定

・ログファイルの保存先を作成
mkdir /var/log/nghttpx

・nghttpx の設定ファイルを作成します。
mkdir /etc/nghttpx/
vi /etc/nghttpx/nghttpx.conf

# デフォルトモードを指定 
http2-proxy=no

# 待受アドレスとポート番号 
frontend=0.0.0.0,3000

# バックエンド WEBサーバのアドレスとポート番号 
backend=127.0.0.1,80

# サーバ秘密鍵 
private-key-file=/etc/pki/tls/private/server.key

# サーバ証明書 
certificate-file=/etc/pki/tls/certs/server.crt

# Disable OCSP stapling. 自己署名のSSL証明書を使っている場合は有効にする 
no-ocsp=yes

# 実行ユーザ 
user=nghttp2

# worker スレッド数 
workers=1

# バックエンドWEBサーバとの最大接続数 
backend-http1-connections-per-host=128

# 同時に実行できる最大ストリーム数 
http2-max-concurrent-streams=100

# ログレベル 
log-level=NOTICE

# アクセスログファイル 
accesslog-file=/var/log/nghttpx/access_log

# エラーログファイル 
errorlog-file=/var/log/nghttpx/error_log

# 接続先ホスト名を、そのままバックエンドに渡す 
# バックエンドのWEBサーバで、バーチャルホストを使っている場合は必須です 
no-host-rewrite=yes

# X-Forwarded-For をバックエンドに送る 
add-x-forwarded-for=yes

※当然ですが行末にスペースが入っていると、正しく動作しません。これが原因で、小一時間ほど悩みました。

nghttpx の起動スクリプト作成

・nghttpx 用の systemd設定ファイルを作成します。
vi /etc/systemd/system/nghttpx.service

[Unit] 
Description=nghttpx 
After=network.target 

[Service] 
Type=simple 
ExecStart=/usr/local/bin/nghttpx
ExecReload=/bin/kill -SIGUSR1 ${MAINPID}
ExecStop=/bin/kill -SIGQUIT ${MAINPID}

[Install] 
WantedBy=multi-user.target

・上記設定を systemd に反映

systemctl daemon-reload

・systemd に反映されているか確認

systemctl list-unit-files | grep nghttpx
---(下記のような表示であればOKです)--------------------------- 
nghttpx.service                             disabled

・起動

systemctl start nghttpx

・自動起動設定

systemctl enable nghttpx

・「nghttp2」ユーザで、nghttpx が実行されているかを確認します。

ps aux | grep nghttpx
---(下記のような表示であればOKです)---------------------------
nghttp2   8877  0.0  0.1  57344  3944 ?        Ss   13:09   0:00 /usr/local/bin/nghttpx
 

nghttpx のログローテーション設定

・ログローテーションの設定ファイルを作成します
vi /etc/logrotate.d/nghttpx

/var/log/nghttpx/*log { 
    daily 
    missingok 
    dateext 
    rotate 60 
    sharedscripts 
    postrotate 
        /bin/systemctl reload nghttpx.service > /dev/null 2>&1
    endscript 
}

・確認します

logrotate -dv /etc/logrotate.d/nghttpx
---(下記のような表示であればOKです)---------------------------
reading config file /etc/logrotate.d/nghttpx

Handling 1 logs

rotating pattern: /var/log/nghttpx/*log  after 1 days (60 rotations)
empty log files are rotated, old logs are removed
considering log /var/log/nghttpx/access_log
(略)

バックエンド WEBサーバ(Apache)の設定

Apache httpd をインストールします。

yum -y install httpd-devel

・「X-Forwarded-For」を、出力できるログフォーマット「x-combined」を追加します。
vi /etc/httpd/conf/httpd.conf

<IfModule log_config_module>
    LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
---(下記を追加)--------------------------- 
    LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" x-combined 
 

・WordPress 用のバーチャルホストを追加します。
ServerName や DocumentRoot は、ご自分の環境に合わせて設定してください。CustomLog のログフォーマットは、上で追加した「x-combined」を指定します。また、環境変数「HTTPS on」を設定しておきます。(WordPress がこの値を参照します)
vi /etc/httpd/conf/httpd.conf

---(下記を追加)--------------------------- 
<VirtualHost *:80>
    SetEnv HTTPS on
    ServerName example.com
    DocumentRoot "/var/www/html"

    <Directory "/var/www/html">
        Options FollowSymLinks
        AllowOverride All
        <files wp-config.php>
            order allow,deny
            deny from all
        </files>
        Require all granted
    </Directory>

    SetEnvIf    Request_URI "\.(gif|jpg|png|css|js)$" nolog
    ErrorLog    logs/error_log
    CustomLog   logs/access_log x-combined env=!nolog
</VirtualHost>

WordPressのインストールは「WordPress インストールメモ(CentOS)」の記事をご参照ください。

動作確認

「https://<アドレス>:3000/」に、HTTP/2 対応のWEBブラウザで接続すると、HTTP/2 プロトコルを使って通信していることが確認できます。Safari など、HTTP/2 に対応していないWEBブラウザの場合は、自動的に nghttpx が HTTP/1.1 を使って通信してくれます。
nghttpx-02

※サーバに接続できない場合は、firewallでブロックされているかもしれません。以下のコマンドで3000/tcp の接続を許可しておきましょう。

firewall-cmd --add-port=3000/tcp --permanent 
firewall-cmd --reload

(2015年5月18日追記)
WordPress の管理画面にも、問題なくログインできます。ありがとうございました!(^^)
nghttpx-05

終わりに

2015年4月27日、HTTP/2 のRFC番号が、RFC7540 (HTTP/2)、 RFC7541(HPACK) に決まったようです。RFCの文章化が目前ですね!

コメント

タイトルとURLをコピーしました