エラーの内容
ブラウザを開くかリクエストを送信すると、以下のエラーが表示されます:
This site can't be reached. ERR_CONNECTION_TIMED_OUT
これは ERR_CONNECTION_REFUSED とは異なります。Refused(拒否)はサーバーが接続を能動的に拒否したことを意味します。Timeout(タイムアウト)はTCPハンドシェイクが完了しなかったことを意味します — パケットは送信されたが、何も返ってこず、クライアントは最終的に待機を諦めた状態です。
原因
- ファイアウォール(サーバー側またはネットワークレベル)が対象ポートのパケットをサイレントにドロップしている
- サーバープロセスが期待されるポートでリッスンしていない
- IPが間違っているか、DNSが誤ったホストに解決している
- セキュリティグループ / クラウドACLがインバウンドトラフィックをブロックしている
- ルーティングの問題 — パケットがサーバーに到達していない
- サーバーに過負荷がかかり、新しい接続を受け付けていない
ステップ1 — サーバーに到達できるか確認する
まず、ネットワークレベルでホストに到達できるか確認するために、通常のpingを試してください:
ping your-server-ip
pingがタイムアウトする場合、問題はネットワークまたはルーティング層にあります — アプリが関与する前の段階です。pingは成功するがポートにアクセスできない場合は、ファイアウォールまたはサービスの問題です。
次に、特定のポートが開いているか確認します:
# ポート80または443に到達できるか確認
telnet your-server-ip 80
# またはnetcatを使用
nc -zv your-server-ip 443
出力なしでハングする場合、ポートはフィルタリングされています — ファイアウォールがパケットをサイレントにドロップしています。Connection refused はむしろ良い兆候です:ポートには到達できているが、そのポートでリッスンしているサービスがないことを意味します。
ステップ2 — サーバーでリッスンしているものを確認する
SSHで接続し、サービスが起動中で正しいアドレスにバインドされているか確認します:
# リッスンしているポートを確認
ss -tlnp
# またはnetstatを使用
netstat -tlnp | grep LISTEN
多くの設定でここが問題になります。127.0.0.1:80 にバインドされたサービスはローカル接続のみを受け付け、外部からの接続は無視されます。外部トラフィックを受け付けるには 0.0.0.0:80 が必要です。
nginxでのバインド設定を修正:
server {
listen 0.0.0.0:80; # 変更前: listen 127.0.0.1:80;
...
}
Node.jsアプリの場合:
// 誤り — localhostのみ
app.listen(3000, '127.0.0.1');
// 正しい — すべてのインターフェース
app.listen(3000, '0.0.0.0');
ステップ3 — ファイアウォールを確認する
Linux (iptables / ufw)
# ufwのステータスを確認
sudo ufw status
# HTTPとHTTPSを許可
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw reload
# iptablesのルールを確認
sudo iptables -L INPUT -n -v
# ポート80が未設定の場合は許可
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT
# ルールを保存
sudo iptables-save > /etc/iptables/rules.v4
CentOS / RHEL (firewalld)
sudo firewall-cmd --list-all
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
クラウドプロバイダー — セキュリティグループ
AWS、GCP、Azure、またはDigitalOceanでは、OSのファイアウォールが完全に開放されていても、クラウドレベルのセキュリティグループがトラフィックをブロックしている場合があります。これらは別々のレイヤーであり、両方でポートを許可する必要があります。クラウドコンソールでインバウンドルールを確認してください:
- AWS: EC2 → セキュリティグループ → インバウンドルール →
0.0.0.0/0からのポート80/443を追加 - GCP: VPCネットワーク → ファイアウォール →
tcp:80,443のルールを追加 - DigitalOcean: ネットワーキング → ファイアウォール → インバウンドルール
ステップ4 — DNS解決を確認する
古いDNSレコードにより、トラフィックが古いサーバーIP(存在しないか、他の誰かのものになっているIP)に送られる場合があります:
# ドメインが解決するIPを確認
nslookup yourdomain.com
dig yourdomain.com A
# 実際のサーバーIPと比較
curl ifconfig.me # サーバー上で実行
IPが一致しない場合、DNSのAレコードを更新する必要があります。TTLが低い(300秒以下)場合、伝播は通常1時間以内に完了しますが、最悪の場合は48時間かかることもあります。
ステップ5 — ルートをトレースする
まだ解決しない場合、tracerouteを使用することで、ネットワークパスのどこでパケットの応答が止まるかを正確に確認できます:
# Linux/macOS
traceroute your-server-ip
# Windows
tracert your-server-ip
ホップの応答が止まる箇所を確認してください。そこがブロックポイントです。ISP、トランジットプロバイダー、またはサーバー自身のネットワークインターフェースのいずれかであっても — tracerouteで素早く絞り込めます。
ステップ6 — サーバーの負荷とリソース制限を確認する
過負荷状態のサーバーは新しい接続をサイレントにドロップする場合があります — エラーなし、無応答の状態です:
# CPUとメモリを確認
top
free -m
# 接続キューが満杯かどうか確認(nginxの場合)
ss -s
# nginx/apacheのエラーログを確認
tail -f /var/log/nginx/error.log
tail -f /var/log/apache2/error.log
ログに accept4() failed (24: Too many open files) が表示されていますか?それはLinuxのファイルディスクリプタ制限に達しています。多くのシステムではデフォルトが1024で、高負荷サーバーには低すぎます。制限を引き上げてください:
# /etc/security/limits.conf
* soft nofile 65536
* hard nofile 65536
# nginx.confにも追記
worker_rlimit_nofile 65536;
確認
変更を加えたら、サーバー自身からではなく、クライアントマシンからテストしてください:
# HTTPレスポンスをテスト
curl -v http://your-server-ip
curl -v https://yourdomain.com
# レスポンスタイムを確認
curl -w "Connect: %{time_connect}s\nTotal: %{time_total}s\n" -o /dev/null -s https://yourdomain.com
HTTP/1.1 200 OK が返れば成功です。近くのサーバーへの接続時間が200ms以内であれば正常です — まだ1秒以上かかる場合は、上流でまだ問題が発生しています。
予防のヒント
- デバッグに時間を費やした後ではなく、サービスをデプロイする前にファイアウォールルールを開放する
- 外部アクセスが必要な場合は、サービスを
0.0.0.0(または特定の外部インターフェース)にバインドする —127.0.0.1は絶対に使用しない - リバースプロキシに明示的な接続タイムアウトを設定する(例:nginxの
proxy_connect_timeout 10s)ことで、クライアントが30秒以上ハングするのではなく、素早く失敗できるようにする - サーバーの接続キューとファイルディスクリプタ制限を監視し、インシデントになる前にアラートを設定する
サブネット計算やIPがファイアウォールルールの許可CIDRレンジ内に含まれるかどうかを確認する場合、ToolCraftのSubnet Calculator が便利です — ブラウザ上で完全に動作し、データはアップロードされないため、内部IPレンジを安全に入力できます。

