PR

WebSocket通信時のポート開放とファイアウォール設定の基礎

記事内に広告が含まれています。

チャット機能や通知システム、ダッシュボードのリアルタイム更新などを実装する際、双方向通信を実現する「WebSocket」は欠かせない技術です。

しかし、ローカル環境で動いていたアプリケーションを本番サーバーやクラウド(AWS、VPSなど)にデプロイした途端、「WebSocket connection failed と表示されて接続できない」「ファイアウォールで通信がブロックされているようだ」といったトラブルに直面するケースは少なくありません。

WebSocket通信を成立させるには、適切なポート開放とファイアウォールルールの設定が必須です。さらに、セキュリティや企業ネットワークからの接続性を考慮すると、単にポートを開けるだけでなく「どのポートをどのように開放するか」というアーキテクチャ設計も重要になります。

ネットワークの基礎知識やインフラ構築に不安がある方は、未経験からネットワークエンジニアを目指せる実践的スクールを活用して、基礎から体系的に学ぶのもおすすめです。

本記事では、WebSocketの標準ポート仕様から、Linux・Windows・AWSにおける具体的なファイアウォール設定コマンド、Nginxによるリバースプロキシ設定、接続できない場合のトラブルシューティングまでを網羅して解説します。

  1. WebSocket通信の標準ポート仕様と推奨設計
    1. 1-1. ws://(80番)と wss://(443番)の違い
    2. 1-2. 独自ポート(3000/8080等)の直接開放を避けるべき理由
    3. 1-3. ベストプラクティス:Nginx等のリバースプロキシで443番に集約する構成
  2. 2. 【環境別】ファイアウォールのポート開放手順
    1. 2-1. クラウド環境(AWS EC2 / セキュリティグループ)の設定
    2. 2-2. Linux(Ubuntu / ufw)でのTCPポート開放コマンド
    3. 2-3. Linux(RHEL / CentOS / AlmaLinux / firewalld)でのポート開放コマンド
    4. 2-4. Windows Server / Windows Defender ファイアウォールの受信規則設定
  3. 【本番実装】Nginxリバースプロキシを通すWebSocket設定
    1. 3-1. 必須ディレクティブ(Upgrade と Connection ヘッダー転送)
    2. 3-2. タイムアウト切断を防ぐ設定(proxy_read_timeout の調整)
    3. 3-3. 設定例(コピペで使える nginx.conf スニペット)
  4. ポート開放しても繋がらない時の原因と対処法
    1. 4-1. HTTPSサイトからの ws:// 接続による「Mixed Content」ブロック
    2. 4-2. 企業内LAN・UTM(プロキシ)によるプロトコル遮断(WSS化で解決)
    3. 4-3. クラウドとOSの二重ファイアウォール見落とし
    4. 4-4. アイドルタイムアウトによる切断対策(Ping/Pong・Heartbeat)
  5. WebSocket通信の疎通確認・デバッグ方法
    1. 5-1. CLIツール(wscat / curl)を使った接続テスト
      1. ① wscat による対話型接続テスト
      2. ② curl によるハンドシェイク検証
    2. 5-2. ブラウザの開発者ツール(Networkタブ)でのハンドシェイク確認
  6. まとめ:安全なWebSocket運用のチェックポイント

WebSocket通信の標準ポート仕様と推奨設計

WebSocketを利用するにあたり、まず理解しておくべきなのが「ポート番号の仕様」と「本番運用における推奨アーキテクチャ」です。

1-1. ws://(80番)と wss://(443番)の違い

WebSocketには、HTTPと同様に「暗号化されていない通信(ws://)」と「暗号化された安全な通信(wss://)」の2種類が存在します。それぞれの標準ポート番号は以下のとおりです。

  • ws://(WebSocket): 標準ポート 80(HTTPと同じ)
  • wss://(WebSocket Secure): 標準ポート 443(HTTPSと同じ)

WebSocketは、最初に通常のHTTP/HTTPSリクエストを使ってサーバーと「ハンドシェイク(接続確立)」を行い、その後プロトコルをWebSocketへとアップグレード(切り替え)して常時接続を維持します。

HTTP通信やパケット送受信の基本構造を詳しく確認したい場合は、Webエンジニア向けネットワーク基礎!HTTP/2とTCP/IPの違いをわかりやすく解説をご覧ください。

現代のWeb開発においては、セキュリティ面およびブラウザ仕様の観点から wss://(443番ポート)の利用が実質的な標準 となっています。WSS化に必要な証明書の設定手順については、SSL/TLS証明書の仕組みとWebサーバーへの設定手順まとめで詳しく解説しています。

1-2. 独自ポート(3000/8080等)の直接開放を避けるべき理由

開発時、Node.jsやPython、Goなどで作成したWebSocketサーバーを 300080808000 といった独自ポートで起動することが一般的です。

そのため「ファイアウォールで 3000 番ポートをそのまま外部へ開放すればよいのではないか」と考えがちですが、本番環境で独自ポートを直接インターネットに公開することは推奨されません。主な理由は以下の2点です。

  1. ファイアウォールやUTM(プロキシ)による遮断: 企業の社内LAN、学校、公共Wi-Fiなどのネットワーク環境では、セキュリティ対策として 80443 以外のポートへのアウトバウンド(外部送信)通信を遮断しているケースが非常に多くあります。独自ポートを開放しても、一部のユーザーがアクセスできない事態が発生します。
  2. セキュリティ攻撃面の拡大: アプリケーションサーバーのポートを直接公開すると、DDoS攻撃や脆弱性を突いた不正アクセスの標的になりやすくなります。

1-3. ベストプラクティス:Nginx等のリバースプロキシで443番に集約する構成

本番環境におけるベストプラクティスは、「フロントエンドのWebサーバー(Nginxなど)で 443番(HTTPS/WSS)を受け、内部でローカルのWebSocketサーバーへ転送する(リバースプロキシ)」 という構成です。

安全なWEBSOCKETアーキテクチャ図 図解

この構成を採用するメリットは以下の通りです。

  • 接続の確実性: 全ての通信が443番ポートを通るため、企業内プロキシや厳しいファイアウォール環境でもブロックされにくい。
  • SSL/TLS証明書の一元管理: 暗号化・復号処理(SSL終端)をNginxに任せられるため、バックエンドアプリケーション側で個別に証明書を組み込む必要がない。
  • 強固なセキュリティ: ファイアウォールで開放するポートを 80443(および管理用の 22/SSH)だけに最小化できる。

リバースプロキシとして採用されるWebサーバーの特徴については、【Webサーバー構築】ApacheとNginxの違いと選び方を比較も参考にしてください。

2. 【環境別】ファイアウォールのポート開放手順

WebSocket通信を通すためには、サーバーのOSや利用しているクラウドプラットフォーム上で、該当ポートへの着信(インバウンド通信)を許可する必要があります。

ここでは、実務で使われることの多い4つの環境(AWS、Ubuntu、RHEL系Linux、Windows)での具体的な設定手順を解説します。

2-1. クラウド環境(AWS EC2 / セキュリティグループ)の設定

AWSなどのパブリッククラウドを利用している場合、OS内部のファイアウォールだけでなく、クラウド側の仮想ファイアウォール(セキュリティグループ)の設定が最優先されます。

設定手順(AWSマネジメントコンソール):

  1. EC2ダッシュボードから、対象インスタンスにアタッチされている「セキュリティグループ」を開く。
  2. 「インバウンドルールを編集」をクリックする。
  3. 以下のルールを追加して保存する。
タイププロトコルポート範囲ソース用途
HTTPSTCP4430.0.0.0/0(全許可)WSS通信 / リバースプロキシ向け
HTTPTCP800.0.0.0/0(全許可)ハンドシェイク・HTTPリダイレクト用
カスタムTCPTCP3000必要なIPアドレス(※独自ポート直接公開の場合のみ)

※本番運用のベストプラクティスに従い、リバースプロキシ経由で公開する場合は 443番(HTTPS)および 80番(HTTP) のみを開放します。

EC2インスタンスの初期セットアップやWebサーバー構築の全体像を把握したい方は、【初心者向け】AWS EC2を使ったモダンなWebサーバー構築入門で詳しく解説しています。

2-2. Linux(Ubuntu / ufw)でのTCPポート開放コマンド

UbuntuをはじめとするDebian系ディストリビューションでは、標準ファイアウォールツールとして ufw(Uncomplicated Firewall)が広く使われています。

ポート開放コマンド(443番および80番を開放する場合):

# 状態の確認
sudo ufw status

# HTTPS (443/tcp) と HTTP (80/tcp) の通信を許可
sudo ufw allow 443/tcp
sudo ufw allow 80/tcp

# (独自ポート 3000 を直接開放する場合)
sudo ufw allow 3000/tcp

# 設定の再読み込み
sudo ufw reload

# ルールが適用されたか確認
sudo ufw status numbered

2-3. Linux(RHEL / CentOS / AlmaLinux / firewalld)でのポート開放コマンド

Red Hat Enterprise Linux(RHEL)、CentOS、AlmaLinux、Rocky Linuxなどでは、firewalld を使用してポートを制御します。

サーバー運用で選定するLinux OSの違いや特徴について知りたい場合は、Web開発環境のOSはCentOSとUbuntuどっちがおすすめ?もあわせて参考にしてください。

ポート開放コマンド(firewalld):

# 稼働状態の確認
sudo firewall-cmd --state

# HTTPS (443) / HTTP (80) サービスを恒久的に許可
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --permanent --add-service=http

# (独自ポート 3000/tcp を恒久的に開放する場合)
sudo firewall-cmd --permanent --add-port=3000/tcp

# 設定を再読み込みして即座に反映
sudo firewall-cmd --reload

# 開放されているポート・サービスの一覧を確認
sudo firewall-cmd --list-all

注意: --permanent オプションを付けずにコマンドを実行すると、サーバー再起動時に設定が消去されてしまうため必ず付与してください。

2-4. Windows Server / Windows Defender ファイアウォールの受信規則設定

Windows環境でWebSocketサーバーをホストする場合や、社内テスト用PCで通信を受け付ける場合は、「セキュリティが強化された Windows Defender ファイアウォール」でインバウンドルールを作成します。

GUIでの設定手順:

  1. スタートメニューから「セキュリティが強化された Windows Defender ファイアウォール」を起動。
  2. 左ペインの 「受信の規則」 を右クリックし、「新しい規則」 を選択。
  3. 規則の種類で 「ポート」 を選択し、「次へ」。
  4. プロトコルで 「TCP」 を選択し、特定のローカルポートに 443(または 3000 など)を入力して「次へ」。
  5. 操作で 「接続を許可する」 を選択し、「次へ」。
  6. プロファイル(ドメイン・プライベート・パブリック)を用途に合わせてチェックし、「次へ」。
  7. 規則の名前(例: WebSocket_WSS_443)を入力して「完了」をクリック。

PowerShell(管理者権限)で即座に設定する場合:

# TCP 443番ポートの受信を許可するルールを追加
New-NetFirewallRule -DisplayName "WebSocket_HTTPS_443" -Direction Inbound -Protocol TCP -LocalPort 443 -Action Allow

# (独自ポート 3000 を開放する場合)
New-NetFirewallRule -DisplayName "WebSocket_Custom_3000" -Direction Inbound -Protocol TCP -LocalPort 3000 -Action Allow

【本番実装】Nginxリバースプロキシを通すWebSocket設定

ポート開放(443番)を完了したら、Webサーバー(Nginx)側でWebSocket通信を中継できるように設定します。

通常のHTTP通信と異なり、WebSocket通信をリバースプロキシさせるには特有のヘッダー制御とタイムアウト対策が必要です。

3-1. 必須ディレクティブ(Upgrade と Connection ヘッダー転送)

WebSocket接続は、クライアントからの「HTTPプロトコルをWebSocketに切り替えてほしい(プロトコルアップグレード)」という要求から始まります。

Nginxがこのリクエストを受け取った際、バックエンドサーバー(Node.js等)に対してヘッダーを正しく転送しないとハンドシェイクが失敗します。具体的には以下の設定が必須です。

  • proxy_http_version 1.1; WebSocketのアップグレードヘッダーはHTTP/1.1以降でのみサポートされるため、HTTPプロトコルバージョンを明示的に 1.1 に指定します。
  • proxy_set_header Upgrade $http_upgrade; クライアントから送られた Upgrade: websocket ヘッダーをバックエンドにそのまま中継します。
  • proxy_set_header Connection $connection_upgrade;(または "upgrade" ホップバイホップヘッダーである Connection をバックエンドに確実に渡します。

3-2. タイムアウト切断を防ぐ設定(proxy_read_timeout の調整)

Nginxのリバースプロキシには、バックエンドとの無通信時間を監視するタイムアウト設定(proxy_read_timeout)があります。

Nginxのデフォルト値は 60秒 です。そのため、クライアントとサーバー間でデータの送受信が60秒間途切れると、Nginxが勝手に接続を切断してしまいます。

チャットアプリなどアイドル時間が長くなりやすいシステムでは、以下のいずれかの対策を講じます。

  1. Nginx側でタイムアウト値を延長する: proxy_read_timeout 3600s;(1時間)や 86400s(24時間)に引き上げる。
  2. アプリ側で定期的な通信を行う: 30秒〜45秒おきに「Ping / Pong(Heartbeatパケット)」を定期送信して接続を維持する。

3-3. 設定例(コピペで使える nginx.conf スニペット)

以下は、SSL(443番ポート)でWebSocket(WSS)を受け付け、ローカルの localhost:3000 で稼働するWebSocketサーバーへ安全に中継する実践的な設定例です。

Nginx

http {
    # クライアントのUpgradeヘッダーの有無に応じてConnectionヘッダーを制御
    map $http_upgrade $connection_upgrade {
        default upgrade;
        ''      close;
    }

    server {
        listen 80;
        server_name example.com;
        # HTTPアクセスをHTTPSへ常時リダイレクト
        return 301 https://$host$request_uri;
    }

    server {
        listen 443 ssl http2;
        server_name example.com;

        # SSL/TLS証明書の設定パス
        ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

        # 通常のWebアプリケーションへのプロキシ設定
        location / {
            proxy_pass http://127.0.0.1:3000;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }

        # WebSocket専用のエンドポイント(例: /ws/ パスで受ける場合)
        location /ws/ {
            proxy_pass http://127.0.0.1:3000;
            
            # WebSocket中継に必要な必須設定
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $connection_upgrade;
            
            # クライアント情報の伝達
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;

            # アイドル切断を防ぐタイムアウト設定(例: 24時間に設定)
            proxy_read_timeout 86400s;
            proxy_send_timeout 86400s;
        }
    }
}

設定ファイルを編集した後は、構文チェックを実行してからNginxを再読み込みしてください。

Bash

# 構文エラーのチェック
sudo nginx -t

# 設定の再読み込み
sudo systemctl reload nginx

ポート開放しても繋がらない時の原因と対処法

ファイアウォールのポートを開放し、Nginxの設定を済ませたにもかかわらず接続できない場合、原因は単純なポート閉鎖以外に潜んでいることが多々あります。

実務で頻出する4大原因とその対処法を順に確認していきましょう。

4-1. HTTPSサイトからの ws:// 接続による「Mixed Content」ブロック

Webサイト全体をHTTPS化している場合、ブラウザのセキュリティ仕様(Mixed Content制限)により、非暗号化プロトコルである ws:// への接続は強制的にブロックされます。

  • 現象: ブラウザのコンソールに Mixed Content: The page at 'https://...' was loaded over HTTPS, but attempted to connect to the insecure WebSocket endpoint 'ws://...'. This request has been blocked. と表示される。
  • 原因: 暗号化されたセキュアなWebページから、暗号化されていないエンドポイントを呼び出している。
  • 対処法: クライアント側の接続先URLを ws:// から wss:// に変更し、443番ポート経由でSSL/TLS通信を行うように修正します。

4-2. 企業内LAN・UTM(プロキシ)によるプロトコル遮断(WSS化で解決)

オフィスや学校、公共施設のネットワークでは、セキュリティアプライアンス(UTMや次世代ファイアウォール)が導入されており、DPI(Deep Packet Inspection: パケット詳細解析) によって通信内容をチェックしています。

  • 現象: 自宅の回線やスマホのテザリングでは繋がるのに、会社の社内LANからだけ接続できない。
  • 原因: 80番ポートや独自ポートで ws:// 通信を行うと、UTMが「HTTPの標準的な通信パターンと異なる」と検知してパケットを破棄・切断する。
  • 対処法: wss://(443番ポート・暗号化) を使用します。TLSでエンドツーエンド暗号化されていれば、UTMやプロキシサーバーは通信の中身(WebSocketヘッダーやデータ)を識別できず通常のHTTPSトラフィックとして通過させるため、遮断を回避できます。

4-3. クラウドとOSの二重ファイアウォール見落とし

インフラ構築で非常によくある盲点が、「上位レイヤー(クラウド)と下位レイヤー(サーバーOS)の二重ファイアウォール」です。

通信がサーバー内部のアプリケーションに届くまでには、複数の関門が存在します。

[インターネット]
       │
       ▼
1. クラウド側の仮想ファイアウォール(AWS セキュリティグループ / VPS パケットフィルタ)
       │
       ▼
2. サーバーOS側のファイアウォール(Linux ufw / firewalld / Windows Defender)
       │
       ▼
3. Webサーバー / リバースプロキシ(Nginx / Apache)
       │
       ▼
4. WebSocketアプリケーション(Node.js / Python 等)

「AWSのセキュリティグループで443を開放したのに、OS側の ufw で443をブロックしていた」「Nginxは起動しているがバックエンドのNode.jsプロセスが落ちていた」といったケースは頻発します。外側から内側へと順に通信が許可されているかを切り分けましょう。

ネットワークの階層構造やパケットが流れるルートの切り分けは、インフラの基礎知識が身についているとスムーズに原因特定ができます。体系的なネットワークスキルを習得したい方は、専門スクールの活用も効果的です。

4-4. アイドルタイムアウトによる切断対策(Ping/Pong・Heartbeat)

「接続自体は成功するが、数十秒から数分何もしないと勝手に切断されてしまう」という場合は、アイドルタイムアウトが原因です。

  • 原因: クライアントとサーバーの間に介在するロードバランサー(AWS ALB等)、リバースプロキシ(Nginx)、または途中のルーターは、一定時間パケットの送受信がないTCPセッションを「切断された不要な接続」とみなして自動的にクローズします。
  • 対処法:
    1. Ping / Pong フレームの活用: WebSocketプロトコル標準のPing/Pongフレームを使い、30秒前後の間隔で定期的に疎通確認を行う。
    2. アプリケーション層のHeartbeat: Socket.ioなどのライブラリに組み込まれているPing/Pong機能を有効にするか、独自に軽量なメッセージ(例: {"type": "ping"})を定期送信する。

WebSocket通信の疎通確認・デバッグ方法

ファイアウォールやリバースプロキシの設定を適用した後は、実際に外部から通信が通っているかをツールを使って段階的に検証します。

ブラウザの画面上だけで確認するのではなく、CLIツールや開発者ツールを組み合わせることで、どの段階でエラーが起きているかを素早く切り分けることができます。

5-1. CLIツール(wscat / curl)を使った接続テスト

ターミナルから手軽にWebSocket接続を検証できるCLIツールを活用すると、フロントエンドの実装を待たずにサーバー単体の疎通を確認できます。

① wscat による対話型接続テスト

Node.js環境があれば、wscat を使うことでターミナル上から直接WebSocket接続を確立し、メッセージの送受信テストが行えます。

# wscat のインストール(未導入の場合)
npm install -g wscat

# 暗号化接続(WSS)でテスト接続
wscat -c wss://example.com/ws/

# 接続成功時の表示例:
# Connected (press CTRL+C to quit)
# > こんにちは
# < エコー返信メッセージ

Connected と表示されれば、ファイアウォール・リバースプロキシ・バックエンドの全レイヤーで通信が正常に通っています。

② curl によるハンドシェイク検証

curl を使用してHTTPヘッダーのレスポンスを確認することで、プロトコルの切り替え(アップグレード)が正常に行われているかを判定できます。

curl -i -N \
     -H "Connection: Upgrade" \
     -H "Upgrade: websocket" \
     -H "Host: example.com" \
     -H "Origin: https://example.com" \
     -H "Sec-WebSocket-Version: 13" \
     -H "Sec-WebSocket-Key: SGVsbG8sIHdvcmxkIQ==" \
     https://example.com/ws/

確認ポイント:

  • レスポンスの先頭が HTTP/1.1 101 Switching Protocols(ステータスコード 101)で返ってくれば、ハンドシェイクは成功しています。
  • もし 502 Bad Gateway が返る場合は「Nginxからバックエンドへの接続失敗」、404 Not Found の場合は「Nginxの location パス設定ミス」、403 Forbidden の場合は「Originチェックの弾き」が疑われます。

5-2. ブラウザの開発者ツール(Networkタブ)でのハンドシェイク確認

Webブラウザ上で動作検証を行う際は、ブラウザの開発者ツール(DevTools)を活用してパケットのやり取りを可視化します。

確認手順(Google Chromeの場合):

[F12キー] で DevTools 起動
   └─ ①「Network」タブを選択
        └─ ② フィルタで「WS」(WebSocket)を選択
             └─ ③ 該当のリクエスト(例: /ws/)をクリック
  1. Headers(ヘッダー)タブの確認:
    • General: Status Code: 101 Switching Protocols になっているか確認。
    • Response Headers: Connection: upgrade および Upgrade: websocket が返ってきているか確認。
  2. Messages(メッセージ)タブの確認:
    • 送信データ(上向き矢印)と受信データ(下向き矢印)がリアルタイムに流れているかを確認。
    • 切断された場合、終了コード(例: 1000 Normal Closure, 1006 Abnormal Closure)が表示されるため、切断理由の特定に役立ちます。

まとめ:安全なWebSocket運用のチェックポイント

WebSocket通信を安定して本番運用するための要点を、チェックリスト形式で振り返ります。

チェック項目推奨される設定・対応
ポート・プロトコル独自ポートを直接開けず、443番(wss:// に集約する
ファイアウォールクラウド(AWS SG等)とOS(ufw/firewalld)の両方で 443/80 を許可
リバースプロキシNginxで Upgrade / Connection ヘッダーをバックエンドへ中継する
タイムアウト対策proxy_read_timeout の延長、またはアプリ層での Ping/Pong(Heartbeat) 実装
セキュリティ・企業対策暗号化(TLS/WSS)により、企業UTMやプロキシによるパケット遮断を回避

WebSocketのデプロイやトラブルシューティングには、単なるコードの実装力だけでなく、Linuxサーバーの操作やネットワーク・セキュリティの体系的な知識が欠かせません。

WebSocketを含めたWebアプリケーションの本番デプロイ全体の流れやサーバー構築手順については、HTML5/WebアプリをデプロイするためのLinuxサーバー構築手順でも詳しく解説していますので、あわせて参考にしてください。

ネットワークやインフラの知識を体系的に身につけたい方へ

ポート開放やファイアウォール、プロトコル仕様の理解など、Web開発の現場ではネットワーク知識が大きな武器になります。

「インフラやネットワークの仕組みを基礎からしっかり学びたい」「資格取得や実務に直結するスキルを身につけたい」という方は、実践的なカリキュラムで学べる専門スクールを検討してみてはいかがでしょうか。