nginxでHTTP2に対応させようとしたら詰まった話

nginx

現在新サーバーに移行のため準備をしているのですがその際WEBサーバーの通信規格をHTTP1.1からHTTP2へ移行を試みていました。

実装自体は各サイトの設定ファイルを編集し

server 
{
	listen 443 ssl http2;
}

にしてあとはSSLの証明書などセキュリティ上必要な記述などを行えば問題ないことを確認しネット上の情報を頼りに実行したのですが詰まったところがあったので備忘録として書いていきます。

どのように詰まったかというとアクセスするとERR_HTTP2_PROTOCOL_ERRORというエラーが出てきます。これがどういうエラーかというと単純にHTTP2のプロトコルがなんかおかしくてデータが来ないというエラーだそうで解決法を検索すると複数の解決法が出てきました。

  1. ブラウザのキャッシュクリアやアップデート、日付を合わせるといったクライアント側の対処法
  2. サーバー側のgzipという圧縮システムが2重に圧縮してしまう可能性があるのでオフにする対処法
  3. SSLの証明書や設定に関する記述を修正する対処法
  4. プロキシやキャッシュに関する設定がおかしいので修正する対処法

これらの情報が出てきたので試してみました。まあちなみに先に結果を書いておくのですがこれらの試みはすべて失敗します。

1.ブラウザのキャッシュクリアやアップデート、日付を合わせるといったクライアント側の対処法

これは単純に使うブラウザ変えるなり端末変えるなりシークレットモードを使うなりキャッシュをリセットできれば問題ないです。アップデートこのに関してはこの記事を見つけるような人は頻繁にアップデートしてることでしょうから問題ないでしょう。時間はサーバークライアント両方あっていることを確認済みですがntpサーバにアクセスして合わせておきましょう。しかしここまでやってもエラーが出ている状態です。この方法では解決しませんでした

2.サーバー側のgzipという圧縮システムが2重に圧縮してしまう可能性があるのでオフにする対処法

これはgzipという通信を圧縮する機能がどういうわけか2重に圧縮をかけ正常なデータのやり取りができない場合があるそうなので一度機能をオフにします。gzipの設定を変更します。nginx.confを編集します。

http
{
       gzip off;
}

これでサーバーにリロードをかけてアクセスしてもつながりません。この方法でもダメなようです。

3.SSLの証明書や設定に関する記述を修正する対処法

SSL Server TestがランクA+になるまで修正しましょう。この件がなくてもやっておくべきです。基本的には常にSSLを使用するようにリダイレクトなどを設定し使用する暗号方式を新しいもののみ使用するようにすれば簡単にA以上をとれます。しかし想定内ではありますがこれでもつながりません。この方法でも駄目なようです。

4.プロキシやキャッシュに関する設定がおかしいので修正する対処法

ネット上にあるテンプレートを流用したり公式ドキュメントを見たりして試行錯誤します。いくつか古くなって廃止されてる記述があったため書き換えます。参考にする記事によっては数年前のもので現在は使用ができない設定があったりするので気を付けましょう。まあこれでもエラーは治らないようです

ネット上の解決法は全滅してしまいました。
ブラウザの開発者画面を見ても該当のエラーしかなくサーバー側のアクセスログではなんと200を返却しています。これはどういうことでしょう。送信するところまではうまくいっているのかと頭を悩ませます。しかしここまでうまくいかないともっと問題は別のところにあるのではないかと考え始めました。

解決

そこで今までいじっていないところで怪しいものは何かないかと設定を見直します。そこで目についたのがセキュリティのために付与しているヘッダーです。ここでchromeのnet-exportを使い通信を追跡します。(最初からやっとくべきだった…)すると見つけました

t=41444 [st=12888]    HTTP2_SESSION_RECV_INVALID_HEADER
                      --> error = "Invalid character 0x0A in header value."
                      --> header_name = "content-security-policy"
                      --> header_value = " default-src 'self' 'unsafe-inline' 'unsafe-eval'

見覚えのあるヘッダーです。このエラーを出してるヘッダーはCSPのヘッダーでページを改ざんされても記述されてない外部ソースの利用を制限できます。試しにCSP用の設定をすべてコメントしてみます。単純にコメントにしてしまいます。すると動きました

動いたということはCSPの設定が原因のようです。セキュリティ確保のため消したくはないのでなぜエラーを出しているのか調べました。どうやら改行をいれてCSPヘッダーを記述するとほとんどのブラウザでエラーを出すようです。一行で書くと見づらいので複数行に分けて記述したのがあだとなりました
一行に修正しサイトにアクセスしたところ正常に動作しました

まとめ

HTTP2のプロトコルエラーという文字に踊らされて特定が難航しました、実際にはヘッダーの記述に問題がありました。そうそうに処理のトレースを実施するべきでした。HTTP1.1では特に問題なく動いていたため余計に気づくのが遅れてしまいました。ともかくこれでHTTP2対応になったのでヨシッ

コメント

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