地方エンジニアの学習日記

興味ある技術の雑なメモだったりを書いてくブログ。たまに日記とガジェット紹介。

【Apache】http/2を試す

httpd.apache.org

この辺を参考に入れていく。CentOS7なら何もせずにビルドも成功したしモジュールも問題なく動いた。

<VirtualHost *:443>
    SSLEngine on
    
    <IfModule http2_module>
        ProtocolsHonorOrder On
        Protocols h2 http/1.1
    </IfModule>

    DocumentRoot "/var/https/example.com/htdocs/"
…(省略)…
</VirtualHost>

【Linux】ポートフォワードを使ってローカルのサービスを外部へ公開してみる

sshのリモートフォワードを使ってローカルで起動したサービスを外部からフォーワードする

# 以下を修正
$ vi /etc/ssh/sshd_config
GatewayPorts yes

# 再起動
$ systemctl restart sshd

以下のようにsshを起動することで192.168.1.1:8433へのアクセスが全てlocalhost:443へ繋がる。嬉しいケースとしてはlocalhostファイアウォールで守られているケースで他ユーザにサービスを確認してもらいたいケース。

$ ssh -R 8443:localhost:443 192.168.1.1

$ ss -antu | grep LIST | grep :8443
tcp    LISTEN     0      128       *:8443                  *:*
tcp    LISTEN     0      128    [::]:8443               [::]:*

www2.filewo.net

【HTTP】http/2におけるConnectionヘッダーの扱い

概要

http/2を喋る環境でバックエンドがConnectionヘッダーやらの取り扱いがどんな感じなのか気になって調べた。RFCとかみてもきちんと定められていて無視するなり不正リクエストにするべきであるというのが決まりの模様。

Connection や Keep-Alive などの接続固有のヘッダーフィールドは HTTP/2 では禁止されています。
Chrome と Firefox は HTTP/2 レスポンスでこれらを無視しますが、 Safari は HTTP/2 仕様の要件に準拠しており、これらを含むレスポンスは読み込まれません。

developer.mozilla.org

クライアント -> LB(http or httpsをプロキシするタイプ) -> Nginx

とかでNginxなりでConnectionヘッダーを付与する場合はアプリケーション層までLBが除けるならここで削除する必要がある。

RFC
   HTTP/2 does not use the Connection header field to indicate
   connection-specific header fields; in this protocol, connection-
   specific metadata is conveyed by other means.  An endpoint MUST NOT
   generate an HTTP/2 message containing connection-specific header
   fields; any message containing connection-specific header fields MUST
   be treated as malformed (Section 8.1.2.6).

proxy-connectionとか固有のヘッダーについての言及は無い模様。実際どれくらいが当てはまるのかはちょっとRFCだけでは確認できなかった。

実験

github.com

http/2に対応したNginxコンテナを用意してNginxで強制的にConenctionヘッダーをつけた場合のクライアントの動作を確認する

curl
$ curl --version
curl 7.64.1 (x86_64-apple-darwin19.0) libcurl/7.64.1 (SecureTransport) LibreSSL/2.8.3 zlib/1.2.11 nghttp2/1.39.2
Release-Date: 2019-03-27
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp smb smbs smtp smtps telnet tftp
Features: AsynchDNS GSS-API HTTP2 HTTPS-proxy IPv6 Kerberos Largefile libz MultiSSL NTLM NTLM_WB SPNEGO SSL UnixSockets

curlのhttp/2バージョンの対応が必要。libcurlとかは適宜上げる必要がある。

> GET / HTTP/2
> Host: localhost
> User-Agent: curl/7.64.1
> Accept: */*
>
* Connection state changed (MAX_CONCURRENT_STREAMS == 128)!
* http2 error: Invalid HTTP header field was received: frame type: 1, stream: 1, name: [connection], value: [keep_alive]
* HTTP/2 stream 0 was not closed cleanly: PROTOCOL_ERROR (err 1)
* stopped the pause stream!
* Connection #0 to host localhost left intact
* Closing connection 0

不正なヘッダーを受け取ったと行ってcurlがエラーとなっている。

firefox

閲覧できた

opera

閲覧できた

safari

プロトコルエラー

f:id:ryuichi1208:20210310194930p:plain

chrome

証明書エラーから進めず(原因不明)

結果

不正ヘッダーに関してはクライアントの実装依存でエラーにするなり閲覧可能で無視するなり別れる模様。Safariが読み込まないのはまあ良いとして外部呼び出し時にhttp/2では不正と呼ばれるヘッダーが付けられてくると利用側的に対応が難しそう(そもそもそんあサービス使うなって話か)