RFC 2818 - TLS 上の HTTP (HTTPS) - 2. TLS 上の HTTP (HTTP Over TLS)
2. TLS 上の HTTP (HTTP Over TLS)
中核原則 (Core Principle)
概念的には非常にシンプル: HTTP/TLS は非常にシンプルです。TCP で HTTP を使用するのとまったく同じように、TLS 上で HTTP を使用します。
2.1. 接続の開始 (Connection Initiation)
プロセス:
1. クライアント → サーバー: TCP 接続を確立 (ポート 443)
2. クライアント → サーバー: TLS ClientHello を送信
3. ↔ TLS ハンドシェイクプロセス ↔
4. ハンドシェイク完了後: クライアントは最初の HTTP リクエストを開始できる
要件:
- ✅ HTTP クライアントは TLS クライアントとして動作する
- ✅ 適切なポートに接続する (デフォルト 443)
- ✅ ハンドシェイクを開始するために TLS ClientHello を送信する
- ✅ すべての HTTP データは TLS の "application data" として送信されなければならない (MUST)
フロー例:
クライアント:
1. www.example.com:443 に TCP 接続
2. ClientHello を送信
サーバー:
3. ServerHello + Certificate を応答
4. ServerHelloDone
クライアント:
5. ClientKeyExchange
6. ChangeCipherSpec
7. Finished
サーバー:
8. ChangeCipherSpec
9. Finished
← TLS ハンドシェイク完了 →
クライアント:
10. 暗号化された HTTP リクエストを送信:
GET / HTTP/1.1
Host: www.example.com
2.2. 接続の終了 (Connection Closure)
TLS は、セキュアな接続終了のための機能を提供します。
終了アラート (Closure Alert)
定義:
- 有効な終了 (Valid Closure): 適切な終了アラートを受信した
- 不完全な終了 (Incomplete Close): 終了アラート送信後すぐに接続を閉じる
- 早期終了 (Premature Close): 終了アラートを受信せずに接続を閉じた
要件:
- ✅ 実装は接続を閉じる前に終了アラート交換を開始しなければならない (MUST)
- ⚠️ 実装は終了アラート送信後に接続を閉じてもよい (MAY) (待機せずに)
- ❌ 早期終了した接続はセッションを再利用してはならない (MUST NOT)
2.2.1. クライアントの動作 (Client Behavior)
問題: HTTP は接続終了を使用してサーバーデータの終了を通知します。
クライアントは MUST:
- ✅ すべての早期終了をエラーとして扱う
- ✅ 受信したデータを切り捨てられた可能性があるものとして扱う
- ✅ 接続を閉じる前に終了アラートを送信する
特殊なケース:
- Content-Length のないレスポンス:
HTTP/1.1 200 OK
Content-Type: text/html
[接続終了が終わりを示す]
← 早期終了がサーバーによるものか攻撃者によるものか区別できない →
- Content-Length が存在するが完全に読み取られていない場合:
HTTP/1.1 200 OK
Content-Length: 1000
[終了前に 500 バイトのみ受信]
← サーバーエラーか攻撃かを判断できない →
例外: 受信したデータが Content-Length と一致する場合は、完了として扱うべきです。
クライアント例:
✅ 通常の終了:
クライアント: closure_alert を送信
サーバーの closure_alert を待機
接続を閉じる
⚡ 高速終了:
クライアント: closure_alert を送信
すぐに接続を閉じる (待機しない)
← これによりサーバー側で不完全な終了が発生 →
2.2.2. サーバーの動作 (Server Behavior)
RFC 2616 の要件: サーバーはクライアントの終了から適切に回復しなければならない (MUST)。
サーバーは SHOULD:
- ✅ クライアントからの不完全な終了を受け入れる準備をする
- ✅ このように終了された TLS セッションの再開を許可する
- ✅ クライアントと終了アラートを交換しようとする
- ⚡ 終了アラート送信後に接続を閉じてもよい (MAY)
実装注意事項:
持続的な接続を使用しない HTTP:
- サーバーは接続終了によってデータの終わりを通知
- しかし、クライアントはすでに終了アラートを送信し切断している可能性がある
2.3. ポート番号 (Port Number)
デフォルトポート: 443
理論的根拠:
HTTP サーバーが期待: Request-Line (例: GET / HTTP/1.1)
TLS サーバーが期待: ClientHello
← 同じポートでは区別できない →
解決策: 異なるポートを使用
- HTTP: 80
- HTTPS: 443
例:
# HTTP (平文)
curl http://www.example.com:80/
# HTTPS (暗号化)
curl https://www.example.com:443/
2.4. URI 形式 (URI Format)
プロトコル識別子: https:// (http:// の代わり)
例:
https://www.example.com/~smith/home.html
https://api.example.com:8443/v1/users
https://192.168.1.1/admin
URI コンポーネント:
https://www.example.com:443/path?query#fragment
↑ ↑ ↑ ↑ ↑ ↑
scheme host port path query fragment