してみるテストロゴ
Apache 2.4系でHTTP/2サーバを構築してみるテスト。

H2Paddingについて

Apache httpd server 2.4.39以降で使用できるH2Paddingディレクティブについて、試して見ます。

Apache httpd server 2.4.39より前の動作

まずは、H2Paddingを設定しない場合、もしくはApache Httpd server 2.4.39よりも前のサーバの挙動を確認してみます。

$ nghttp -v  https://http2.try-and-test.net/
[  0.014] Connected
The negotiated protocol: h2
…省略…
[  0.028] recv SETTINGS frame <length=6, flags=0x00, stream_id=0>
          (niv=1)
          [SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[  0.030] recv WINDOW_UPDATE frame <length=4, flags=0x00, stream_id=0>
          (window_size_increment=2147418112)
[  0.031] recv SETTINGS frame <length=0, flags=0x01, stream_id=0>
          ; ACK
          (niv=0)
[  0.032] recv HEADERS frame <length=212, flags=0x04, stream_id=13>
          ; END_HEADERS
          (padlen=0)
          ; First response header
…省略…
[  0.034] recv DATA frame <length=1291, flags=0x00, stream_id=13>
…省略…
[  0.094] recv DATA frame <length=1230, flags=0x01, stream_id=13>
          ; END_STREAM

このように、最初のデータフレームが、1291バイト、最後のデータフレームが1230バイトになっています。

何度試しても同じバイト数のデータフレームが送られてきます。

これでは、暗号化しても、受信データのバイト数からおおよそ、何のコンテンツを見ているのか、推測できてしまいそうです。

H2Paddingを設定

それでは、Apache2.4.39をインストールして試してみます。インストール方法は、コチラをご覧下さい。(そんなに特別なことはしなくても入ると思います。)

H2Paddingディレクティブはバーチャルホスト毎に変えられます。

今回は、バーチャルホストの設定として追加します。

# vi /usr/local/apache2/conf/extra/httpd-vhosts.conf
/usr/local/apache2/conf/extra/httpd-vhosts.conf
…(省略)…
<VirtualHost *:443>
        <IfModule http2_module>
                Protocols h2 http/1.1
                H2Padding 6
        </IfModule>
</VirtualHost>
…(省略)…

上記の設定で、0から、2の6乗=64までのいずれかのバイト数のダミーデータの付加(パディング)が行われます。

今回は6を設定しましたが、0~8までの数値を設定できます。0だと、旧バージョンと同じく、ダミーデータの付加を行いません。8なら、0~256バイトのいずれかのサイズのダミーデータを付加します。

この設定によって、データフレームのバイト数が、パディングによって変動するため、先ほどより、暗号化した、受信データのバイト数から、何のコンテンツを見ているのか、推測が難しくなります。

そのかわり、約1300バイトのデータフレームに、期待値32バイト程度のダミーデータが付加されるため、上記設定だと、3%程度のネットワークオーバーヘッドが発生します。

apachctl -tで、設定ファイルの間違いが無いことを確認の上、下記のように

# /usr/local/apache2/bin/apachctl -t
Syntax OK
# /usr/local/apache2/bin/apachctl stop
# /usr/local/apache2/bin/apachctl start

とします。Syntax OKと出なかった場合は、なにか間違ってますので、これまでの作業を見直してください。

早速、先ほどと同じく、nghttp2コマンドで試して見ます。

$ nghttp -v  https://http2.try-and-test.net/
[  0.152] Connected
The negotiated protocol: h2
[  0.166] recv SETTINGS frame <length=6, flags=0x00, stream_id=0>
          (niv=1)
          [SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[  0.167] recv WINDOW_UPDATE frame <length=4, flags=0x00, stream_id=0>
          (window_size_increment=2147418112)
[  0.169] recv SETTINGS frame <length=0, flags=0x01, stream_id=0>
          ; ACK
          (niv=0)
[  0.170] recv HEADERS frame <length=216, flags=0x0c, stream_id=13>
          ; END_HEADERS | PADDED
          (padlen=4)
          ; First response header
…省略…
[  0.172] recv DATA frame <length=1318, flags=0x08, stream_id=13>
          ;  PADDED
          (padlen=27)
…省略…
[  0.183] recv DATA frame <length=1238, flags=0x09, stream_id=13>
          ; END_STREAM |  PADDED
          (padlen=8)
[  0.183] send GOAWAY frame <length=8, flags=0x00, stream_id=0>
          (last_stream_id=0, error_code=NO_ERROR(0x00), opaque_data(0)=[])
	

ヘッダフレーム(HEADERS frame)や、データフレーム(DATA frame)の長さが、先ほどを変わっていることと、PADDEDの文字が追加されていることが、確認できると思います。

最初のデータフレームが、1291+27=1318バイト、最後のデータフレームが1230+8=1238バイトになっています。

以降、同じリクエストであっても、毎回異なるバイト数のデータフレームが送られてきますので、データフレームの長さから、リクエスト内容を推測することが難しくなりました。

このダミーデータの付加(パディング)は、TCPを使うHTTP/2でも有用ですが、フラグメント化しないようにUDPを使うHTTP/3では、必須の機能に思えます。(HTTP/3では、HTTP/2と違って互換性の問題が無いため、デフォルトになると思いますが…)

NEXT >> mod_http2のリファレンス

©Copyrights 2015-2019, non-standard programmer

このサイトは、あくまでも私の個人的体験を、綴ったものです。 軽く参考程度にご利用ください。