HTTP/1.x⇒HTTP/2　仕様変更で困ったこと (利用暗号の制約・httpヘッダーの小文字化)

# **はじめに**

こちら、[そろそろ知っておきたいHTTP/2の話](https://qiita.com/uutarou10/items/7698ee3336c70a482843)という良くまとめられた記事を見ていて、色々と苦い記憶がよみがえってきたのですが、そういうHTTP/2仕様に困った系記事があまり見当たらなかったのでまとめました。

# **HTTP/2とは**

## **機能**

現在支流のHTTP 1/1よりも**より効率よく、セキュアな通信**をもらたす為に色々なアップグレードを施したHTTPの規格です。

特徴をざっというと、こんな感じ。

1. **ストリーム、メッセージ、フレーム**という新しいデータの交換方式を利用することによる、**実TCPセッション数削減**
2. **サーバー プッシュ**機能により、**複数のレスポンスが送信可能**
3. HTTPヘッダーの仕組みを見直し、**ヘッダー圧縮によるネットワーク負荷軽減**


### **HTTPS(TLS)との関係**

実はHTTP/2はHTTPSと深い関係があります。

- 実質的にHTTPS必須、しかもTLS1.2以上、cipher-suiteは`TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256`が必須です。[使用してほしくないリスト](https://tools.ietf.org/html/rfc7540#appendix-A)も存在しています。
SHOULD使用してほしくないリストと表現しましたが、RFCのタイトルが**Appendix A.  TLS 1.2 Cipher Suite Black List。実質使うなという強い意志を感じます**。

この辺りでもセキュアな通信を保証してるんですね。

### **本記事でのキーワード**

今回はHTTP/2で困ったことなので、そのキーワードを上げておきます。

- **cipher-suite、[使用してほしくないリスト](https://tools.ietf.org/html/rfc7540#appendix-A)が存在している。**
- **HTTPヘッダーの仕組みを見直し**

それでは本題に入ります。

# **HTTP/2導入で困ったこと**

## **発生した問題**

発生した問題は以下でした。

- HTTPサーバーにHTTP/2サポート機能を有効にしてHTTP/2テストの為にHTTPS接続を試みたところ、**(確か)IE以外のブラウザはHTTPS通信ができなかった。**

## **原因**

2点ありました。どちらもHTTP/2の仕様に関わる問題でした。

1. **IEが利用可能なcipher-suiteがcipher-suiteの制限に引っかかり、HTTP/2が使えていなかった。**
2. HTTPヘッダーの仕様変更により、**すべてのヘッダー フィールドが小文字のみ**に制限された。

以下2点について解説です。

## **cipher-suiteの制限**

**cipher-suite**とは？ざっくり説明すると、**HTTPS通信の中で利用する暗号化の仕組み**の事です。

HTTPSは、通信開始時に
SSLクライアント「使う暗号何にしましょうか?」 Client Helloでcipher-suite一覧を渡す。
⇒SSLサーバー  「よし、こいつにしよう！」 Server Helloでcipher-suite決定。
以降は決まったcipher-suiteに従った仕組みでメッセージが暗号化される！
クライアント-サーバー以外は暗号化済みのメッセージ内で共有された情報だったりを持っていないと解読できないという、残念！

といった仕組みになっています。
この**cipher-suiteにもいい悪いがあって、よりいい暗号の方が傍受されにくい**っていうのがあるので、HTTPSの強度を上げるために重要な要素だったりします。

### **制限されたcipher-suiteの種類**

**Appendix A.  TLS 1.2 Cipher Suite Black List**, ここには書きませんが種類が滅茶苦茶あります。

どれだけ厳しいのか？
[SSL/TLS暗号設定ガイドライン～安全なウェブサイトのために（暗号設定対策編）～](https://www.ipa.go.jp/security/vuln/ssl_crypt_config.html)という、IPAによって作られたガイドラインの中にこのcipher-suite選定のチェックリストと比較してみました。
(HTTPサーバー開発者の方で利用されていない方がいましたら、ぜひご利用ください。)

論外を除いたcipher-suite達を大項目としては以下の順に分けて評価。
1. 高セキュリティ型
2. 推奨セキュリティ型
3. セキュリティ例外型

試しにどの辺りで引っかかるのかいくつか見たところ、高セキュリティ型は平気そうでしたが、**推奨セキュリティ側は最上位グループのグループAでもNGが普通にあります！**
高セキュリティ型と推奨セキュリティ型の一部、本当にセキュアなものしか許しません！って感じかな。検索にかかった瞬間うお、厳しい！って声が出ました。

これをSHOULD部分まで準拠されたら先端を行ってるブラウザしか無理だな…

### **IEがHTTP/2を利用できなかった理由**

- 採用していたHTTPサーバー h2oが、HTTP/2仕様にならい、HTTP/2利用の為のcipher-suiteを大分制限していた。
- IEがそのcipher-suiteを軒並みサポートしていなかった。

というのが根本原因でした。もうこれは仕様なので、IEはクライアント側の問題でHTTP/2非サポートという形で収まったと記憶しています。
(うろ覚えで申し訳ないです。)

### **cipher-suiteの制限 まとめ**

**クライアントはHTTP/2実装だけでなく、セキュリティ方面も頑張らないとHTTP/2を利用できない。**

いいプロトコルには努力が必要なんですね。

## **すべてのヘッダー フィールドが小文字のみに仕様変更**

元々の問題は(確か)IEだけしかHTTPS通信できなかった。実は**HTTP/2でつなぐと、今回のシステムの既存のシーケンスだと通信エラーになる**という問題に早変わりしました。

…何それ下位互換じゃないの？との思いから、絶対自分らが手を入れたサーバー側のバグだろうと
必死でパケットからHTTPSを解読し、HTTP/2のフォーマットを解析し、HPACKの中身を解読し、見えてきた条件がこちら。

- **大文字を使用しているHTTPヘッダーが付いているHTTP request/responseがエラー扱い**されている。

え、だってHTTPヘッダーって大文字小文字区別しないはずだよね。どういうこと？
今度はHTTP/2の仕様詳細を必死に読み解くことに。RFCを読み込むと記述を発見。

>Just as in HTTP/1.x, header field names are strings of ASCII
characters that are compared in a case-insensitive fashion. However,
header field names MUST be converted to lowercase prior to their
encoding in HTTP/2.

**HTTP/1.xではHTTPヘッダーは大文字小文字区別しなかったけど、これからは小文字しか受け付けないぜ！**ですって。
愕然としました。…けど規格で決まった仕様ならしょうがない。小文字にしましょう。

ウェブページ作成チームにも報告。全く同じこと言われました。「だってHTTPヘッダーって大文字小文字区別しないですよね？当時の開発時点でRFCに書いてることまで確認しましたよ！」
うん、ですよねわかります。まさかその仕様が下位互換をうたってると聞いてたHTTP/2で変わるわけないと思いますよね。うんうん。

やむを得ずみんなで修正し試験しました。

### **すべてのヘッダー フィールドが小文字のみに仕様変更 まとめ**

今回は、物理面と精神面でなんかがっくし来ました。

**物理面**
- インターフェイスの仕様変更は影響範囲が大きい

え？小文字に直すだけですって？
HTTPヘッダーの仕様変更ですよ？このシステムで利用する全HTTPレスポンスヘッダータイプは最低でも試験しますよね？しかもHTTP2を使っていることを保証しつつですよ？
中々切ない作業となりました。

**精神面**
- 会社間、チーム間でこういうことがあるならまあなと思うけど、**RFC規格が互換性をうたっているのに、しれっと外部仕様を変更している**という事実が凄いショックでした。

RFCを完璧に読んだかといわれるとNOなので、互換性うたってるが勘違いなのかもしれませんが。
なんで皆さん困ってないのかな？似たような記事を見かけたことないけど、自分は滅茶苦茶ショックだったんですよね。

# **まとめ**

- **HTTPSで使用するcipher-suite、かなり制限されている**のでクライアントサイドの開発者は最新の暗号が使えるよう対応頑張ってください。
- **すべてのヘッダー フィールドが小文字のみになった**ので、特にHTTPサーバー開発者はご注意ください。
- 何があっても気を強く持って、開発に臨みましょう！

# **参考**

IPAのSSL/TLS設定ガイドライン
[SSL/TLS暗号設定ガイドライン～安全なウェブサイトのために（暗号設定対策編）～](https://www.ipa.go.jp/security/vuln/ssl_crypt_config.html)

HTTP/2の概要
[そろそろ知っておきたいHTTP/2の話](https://qiita.com/uutarou10/items/7698ee3336c70a482843)
[HTTPサーバーをHTTP/1.xからHTTP/2に乗り換えたら](https://developers.google.com/web/fundamentals/performance/http2/?hl=ja)

HTTP/2 RFC
[RFC 7540 Hypertext Transfer Protocol Version 2 (HTTP/2)](https://tools.ietf.org/html/rfc7540)
小文字の話⇒[8.1.2.  HTTP Header Fields](https://tools.ietf.org/html/rfc7540#section-8.1.2)
cipher-suite制限⇒[Appendix A.  TLS 1.2 Cipher Suite Black List] (https://tools.ietf.org/html/rfc7540#appendix-A)