Amazon AWS Cloud9環境(EC2)でHTTP/2プロトコルに対応する(Apache)

## HTTP/2 対応に必要な条件

私のCloud9環境はほぼ全て対応済だったのでだいぶ楽でした。
これからの時代はAWSですね。

### Apache Ver 2.4.17以上であること

```
$ httpd -v

Server version: Apache/2.4.41 (Amazon)
Server built:   Oct 15 2019 22:21:35
```

### OpenSSL Ver 1.0.2以上であること

```
$ openssl version

OpenSSL 1.0.2k-fips  26 Jan 2017
```

### mod_http2をインストールしていること

```
$ httpd -M | grep http2

http2_module (shared)

$ less /etc/httpd/conf.modules.d/00-base.conf | grep 'mod_http2'

LoadModule http2_module modules/mod_http2.so
```

### SSL対応していること(任意?)

こちら私の環境は未対応でした。
このためだけにRoute53でドメイン取得したりすんのはだるいので、
オレオレ証明書で対応することにしました。

以下の記事に書いてある通りに進めれば、
特にトラブルもなく対応できました。

https://qiita.com/abetd/items/d8ef4767ff1ac8284aa8

もしかすると、SSL対応しなくても
HTTP/2対応できるかもしれませんが試してません。

https://qiita.com/horizontal/items/ca350bd8a4f15d1f4fbc

## 特筆すべき点

私の環境はmod_sslをインストールしてなかったみたいなので、
yumでインストールしました

```
sudo yum install mod24_ssl.x86_64
```

上のモジュールをインストールし、オレオレ証明書でSSL対応して、
curlコマンドでHTTP/2になったかを確認してみたところ、
なってませんでした。

```
理想
curl -I --http2 --insecure https://XX.XXX.XXX.XX/

HTTP/2 200 <-- これが出るはず
```

```
現実
curl -I --http2 --insecure https://XX.XXX.XXX.XX/

HTTP/1.1 200 <-- あれ～～？？
```

「mpmでpreforkモジュールが設定されているとHTTP2が無効化される」らしいです。
自分でも何を言っているのかわかりません。ごめんなさい。

とりあえず以下のサイトにある通り、
`00-mpm.conf` から `mpm_prefork_module` をコメントアウトし、
`mpm_event_module` を有効化して、Apache再起動したらHTTP/2で読み込まれました。

https://www.kannon.link/fuku/index.php/2018/09/01/01-49/

```
$ sudo vi /etc/httpd/conf.modules.d/00-mpm.conf

#LoadModule mpm_prefork_module modules/mod_mpm_prefork.so
LoadModule mpm_event_module modules/mod_mpm_event.so
```

## 動作確認

curlコマンドを叩くことで確認できます。
私の環境はオレオレ証明書を使っているので `--insecure` オプションが必要です

```
curl -I --insecure --http2 https://XX.XXX.XXX.XX

HTTP/2 200
```

あるいは、ブラウザからでも簡単に確認することもできます

https://nelog.jp/http2-browser-extensions

## なぜ対応したのか？

Burp Suiteを用いて自分の開発環境で脆弱性診断を実施したところ、
「HTTPリクエストスマグリング」という脆弱性があることがわかったからです。

* HTTPリクエストスマグリングとは
* https://qiita.com/shoooooo/items/45899d4b4ccfd095f8c8
* https://www.scutum.jp/information/waf_tech_blog/2018/11/waf-blog-059.html

そして、その解決策は
「通信プロトコルをHTTP/1.1からHTTP/2にアップグレードすることである」
と書いてあったので、そうした次第です

BurpSuiteに書いてあった文章を翻訳したものを下記します。

```
問題の背景

HTTP リクエストの密輸の脆弱性は、
ウェブサイトが HTTP のパースが一貫していないウェブサーバを介して
HTTP リクエストをルーティングするときに発生します。

異なるサーバによって異なる長さと解釈されるリクエストを提供することで、
攻撃者はバックエンドの TCP/TLS ソケットを毒し、
次のリクエストに任意のデータを追加することができます。

ウェブサイトの機能にもよりますが、
フロントエンドのセキュリティルールを迂回したり、
内部システムにアクセスしたり、
ウェブキャッシュを毒したり、
サイトを積極的に閲覧しているユーザーに対して
様々な攻撃を仕掛けたりすることができます。

問題の修正

この脆弱性のすべてのバリエーションを解決するには、
フロントエンドサーバがバックエンドシステムとの通信に
HTTP/2 を排他的に使用するように設定するか、
バックエンド接続の再利用を完全に無効にする必要があります。

あるいは、チェーン内のすべてのサーバが同じ設定で
同じウェブサーバソフトウェアを実行していることを確認することもできます。

この脆弱性の特定のインスタンスは、
フロントエンドサーバを再設定して
曖昧なリクエストを正常化してからルーティングするか、
バックエンドサーバが曖昧なリクエストに遭遇したときに
メッセージを拒否して接続を閉じるように設定することで解決できます。
```

## コマンド履歴

未来の自分のために、どんなコマンドを叩いたのかを記します

```
openssl version
yum list installed | grep openssl
httpd -v
sudo cp /etc/httpd/conf/httpd.conf /etc/httpd/conf/httpd.conf.bak
sudo vi /etc/httpd/conf/httpd.conf
sudo service httpd restart
httpd -M | grep http2
less /etc/httpd/conf.modules.d/00-base.conf | grep 'mod_http2'
ls -l /etc/httpd/modules/ | grep ssl
sudo yum list available | grep ssl
sudo yum install mod24_ssl.x86_64 
ls -l /etc/httpd/modules/ | grep ssl
mkdir ~/ssl
cd ~/ssl
openssl genrsa -out ca.key 2048
openssl req -new -key ca.key -out ca.csr
openssl x509 -req -days 365 -in ca.csr -signkey ca.key -out ca.crt
sudo cp -p ca.crt /etc/pki/tls/certs/
sudo cp -p ca.key /etc/pki/tls/private/
sudo cp -p ca.csr /etc/pki/tls/private/
restorecon -RvF /etc/pki/
sudo cp /etc/httpd/conf.d/ssl.conf /etc/httpd/conf.d/ssl.conf.bak
sudo vi /etc/httpd/conf.d/ssl.conf
sudo service httpd restart
curl -I --insecure --http2 https://XX.XXX.XXX.XX
sudo less /etc/httpd/logs/error_log
sudo cp /etc/httpd/conf.modules.d/00-mpm.conf /etc/httpd/conf.modules.d/00-mpm.conf.bak
sudo vi /etc/httpd/conf.modules.d/00-mpm.conf
sudo service httpd restart
history
```

## 参考URL

* https://knowledge.sakura.ad.jp/7735/
* https://blog.apar.jp/linux/8339/
* https://webnetforce.net/apache-with-http2/#mod_http2Apache