🐈

WebSocketメモ

に公開

はじめに

最近WebSocketを使用した機能開発をする機会がありました。
ライブラリを使えば手軽に実装できるものの、HTTPとは違った部分で意識することが多々ありました。
今回は事前にキャッチアップした内容や、実装時に注意したことなどを備忘録としてまとめます。


WebSocketとは

  • 通信プロトコルの一種
    • HTTPやSSHなどと同様の通信プロトコル
  • クライアントとサーバー間の双方向通信を可能にする
  • 一度確立したコネクションを継続して使用するため効率的
    • クライアント・サーバー間で複数回やり取りがあっても、毎回コネクションを張り直す必要がない
  • ヘッダー情報のやり取りが最小限に抑えられ、通信効率が高い
  • 通信開始時に特徴的な仕組み(プロトコルアップグレード)を用いる

WebSocket通信の開始方法(プロトコルアップグレード)

  1. HTTPを用いてクライアントがWebSocketでの通信を要求
  2. サーバーがリクエストを受け入れる
  3. WebSocketに切り替えて通信開始

なぜプロトコルアップグレードが必要か?

  • ファイアウォールを通過するため
    • 一般的に通信は「プロトコルとポート番号」の組み合わせで制御されている
      例:HTTPSは443番、SSHは22番ポートなど
  • WebSocketはHTTPとは別のプロトコルのため、そのままではブロックされる可能性がある
  • そのため最初はHTTPとして接続し、その後WebSocketにアップグレードすることで、これらの制約を回避できる

プロトコルアップグレード時のヘッダー情報

リクエスト時(クライアント→サーバー)

Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-key: hogehoge
Sec-WebSocket-Protocol: chat
Sec-WebSocket-Version: 13
  • Sec-WebSocket-Key
    • クライアントがランダムな値(nonce)を生成して送信
    • サーバーはこれを仕様に従って変換し、Sec-WebSocket-Acceptとして返す
    • クライアントは戻ってきた値が正しいか検証し、サーバーがWebSocketに対応しているか確認する
    • 秘密情報ではない
  • Sec-WebSocket-Protocol
    • WebSocket通信確立後に使用するサブプロトコルを指定
    • アプリケーション固有のデータ交換ルールを示す(例:chat、jsonなど)
    • クライアントが候補を提示し、サーバーが選択する形

レスポンス時(サーバー→クライアント)

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: fugafuga

WebSocketの課題

負荷分散が難しい

  • リクエストごとに処理するHTTPと違い、WebSocketはコネクションを長時間保持するためコネクション数の管理や分散が複雑

HTTP前提のセキュリティとの不整合

  • 一般的なWebアプリケーションでは、認証やセキュリティの仕組みがHTTPの特性(ステートレス性、ヘッダーの送受信など)に基づいて設計されている
    • 例:Cookieによるセッション管理、Authorizationヘッダーによる認証、CORS(Cross-Origin Resource Sharing)によるリソース制御など
  • WebSocketはプロトコルアップグレード後にHTTPヘッダーが使えなくなるため、これらの仕組みがそのまま利用できない
    • 例えば、HTTPのように毎回リクエストヘッダーにトークンを載せるといった認証方法は使えない(WebSocketは常時接続型のため)
    • また、CORSのようなブラウザによる自動的なクロスオリジン制御も適用されないため、サーバー側でOriginヘッダーをチェックするなどの明示的な実装が必要

WebSocketにおける認証とセキュリティ

  • WebSocket通信はHTTPと違ってメタ情報(リクエストヘッダー等)を持たない
    • プロトコルアップグレード後は、純粋な双方向データストリームのみとなる
    • 認証やアクセス制御はアプリケーションレベルでの実装が必要
  • 同一オリジンポリシーが適応されない
    • HTTPではCORSなどブラウザ側の制約があるが、WebSocketには標準で存在しない
    • プロトコルアップグレード時のOriginヘッダーなどを用いて、サーバー側でチェックする必要がある

まとめ

  • WebSocketは双方向通信を可能にするプロトコル
  • HTTPとは仕組みが異なるため、別物として理解することが重要
  • 認証・セキュリティ・通信ルール(サブプロトコル)は、アプリケーション側の実装で補完する必要がある

参考文献

Discussion