【Ubuntu】ポート疎通の確認:ss / lsof / nc / curl で原因切り分け(新人が迷わない型)

ポート疎通の確認 - ネットワークトラブルシューティング

この記事で解決できること

  • 「繋がらない」を ネットワーク / サーバ / アプリ のどこで止まっているか切り分けできます
  • ありがちな "ufwのせいだと思い込む" "サービスの起動だけ見て満足する" を避けられます
  • 最短で原因に当たりを付けるコマンドセット(ss / lsof / nc / curl)が身につきます

結論(最短ルート)

「繋がらない」は、次の順番で見ると一発で整理できます。

  1. DNSが正しいか(必要なら)
  2. クライアント→サーバの到達確認nc -vz HOST PORT
  3. サーバ側で待受確認ss -lntp | grep :PORT
  4. 誰が掴んでるかlsof -i :PORT
  5. HTTPなら応答確認curl -I http(s)://HOST
  6. サービスとログsystemctl status / journalctl -u

目次

  1. まず「何が繋がらないのか」を言語化する
  2. クライアント側:到達できるか(nc)
  3. サーバ側:待ち受けているか(ss)
  4. 誰がそのポートを掴んでいるか(lsof)
  5. HTTPの場合:curl で応答確認
  6. DNSの切り分け
  7. サービス確認(systemctl / journalctl)
  8. 失敗例とエラーの読み方
  9. やってはいけないこと

前提(対象環境)

  • OS:Ubuntu(サーバ側)
  • 対象:サーバ触り始めた新人
  • ここでは「調査・切り分け」に集中(最終修正は別記事へリンク)

1. まず「何が繋がらないのか」を言語化する

最低限この3点を先に確定します。

  • HOST:example.com なのか、IPなのか
  • PORT:22 / 80 / 443 / 3000 / 8080 / 3306 など
  • プロトコル:SSH?HTTP?DB?

例:

  • SSHが繋がらない → HOST=example.com PORT=22(または2222)
  • Webが見れない → PORT=80/443
  • APIが死んでる → PORT=3000/8080

この時点で曖昧だと、永遠に迷子になります。

2. クライアント側:まず到達できるか(nc)

一番大事なポイント:サーバ側をいじる前に、クライアントから到達できるか見たほうが速いです。

2-1. nc で疎通確認(TCP)

$ nc -vz example.com 22

2-2. ポートが違う場合(例:2222)

$ nc -vz example.com 2222

2-3. 結果の読み方(ここが核心)

  • succeededネットワーク的には届いている(次はサーバ/アプリの問題)
  • timed out届いていない(FW/SG/経路/DNS/相手死んでる)
  • refused届いているが待受がない(サービス停止/ポート違い/バインド先が違う)

timed out で ufw を疑うのはアリですが、クラウド側FW(SG等)でも同じ症状になります。ufwだけ直しても改善しないことが多いので、次の手順で"サーバ側の待受"とセットで見ます。

3. サーバ側:そのポートで待ち受けているか(ss)

nc refused のとき、ここで一発で決まります。

3-1. 全待受を表示

$ sudo ss -lntp
  • -l:listen中
  • -n:数字で表示(DNS解決しない)
  • -t:TCP
  • -p:プロセス表示(sudoが必要)

3-2. 特定ポートだけ絞る(例:80)

$ sudo ss -lntp | grep ':80 '

3-3. よくある "罠" の見分け

罠1:127.0.0.1 でしか待ってない(外から繋がらない)

ss の結果にこう出るパターン:

LISTEN 0 4096 127.0.0.1:3000 ...

これは サーバ内部からしかアクセスできません。外部公開したいなら 0.0.0.0:3000 等で待つ必要があります(アプリ設定側)。

4. サーバ側:誰がそのポートを掴んでいるか(lsof)

ss でも分かりますが、lsofは「人間に読みやすい」です。

4-1. 80番の占有プロセスを表示

$ sudo lsof -i :80

4-2. 3000番の例

$ sudo lsof -i :3000

ここで「想定してないプロセス」が掴んでいたら、別サービスが邪魔している可能性があります。

5. HTTPの場合:curlで"応答の中身"まで見る

Web/APIは「ポートは開いてるけど500」みたいな状況が普通にあります。

5-1. ヘッダだけ確認

$ curl -I http://example.com
$ curl -I https://example.com

5-2. 典型的なステータスの読み方

  • 200:基本OK
  • 301/302:リダイレクト(意図通りか確認)
  • 403:権限/アクセス制御(WAF/Basic認証/許可IPなど)
  • 404:ルーティング/パス間違い
  • 500:アプリ内部エラー(ログへ)
  • 502/503/504:上流/下流(リバプロやアプリ)問題

6. DNSの切り分け(HOSTがドメインの場合)

「ドメインだけ繋がらない」はDNSか証明書かリダイレクトが原因になりがちです。

6-1. ドメインがどのIPを引いているか

$ dig example.com +short

6-2. 直接IPに向けて疎通してみる(DNS切り離し)

$ nc -vz 203.0.113.10 80
$ curl -I http://203.0.113.10

IPだとOKでドメインだとNG → DNS(またはCDN/WAF)側の問題が濃厚

7. "サーバは届いてるのに動かない"とき(systemctl / journalctl)

nc succeeded なのにアプリが返してこない/エラー、みたいな場合はここです。

7-1. サービスが動いてるか

$ sudo systemctl status nginx
$ sudo systemctl status apache2
$ sudo systemctl status ssh

7-2. ログを見る(最短)

$ sudo journalctl -u nginx -n 200
$ sudo journalctl -u ssh -n 200

"起動してる" だけ見て終わるのは危険です。起動直後に落ちている、設定エラーで再起動ループしている、などはログを見ないと分かりません。

8. 失敗例(エラー文から原因階層を当てる)

8-1. nc: connect ... timed out

原因候補:ufw、クラウドFW(SG)、社内FW、経路、サーバダウン

8-2. nc: connect ... refused

原因候補:待受が無い、ポート違い、プロセス落ちてる

8-3. curl: (7) Failed to connect

原因候補:到達できない(timed out系) or 待受なし

8-4. curl: (60) SSL certificate problem

原因候補:証明書/ホスト名/中間証明書

8-5. curl -I が 502 Bad Gateway

原因候補:nginx/apache → upstream(アプリ)が死んでる/別ポート

9. やってはいけないこと

やってはいけない1:いきなりFWを無効化してごまかす

ufw disable は最終手段です。まずは ncss で原因階層を決めてください。

やってはいけない2:ポート番号を確認せず22固定で進める

本当は2222で待っているのに「22を許可した」とか、時間が溶けます。

やってはいけない3:サーバ側の"待受(ss)"を見ずにアプリを疑う

待受が無いならアプリ以前です。切り分けの順序を守るのが最短です。

コピペ用:切り分けテンプレ

# クライアント側(到達確認)
nc -vz example.com PORT

# サーバ側(待受確認)
sudo ss -lntp | grep ":PORT "

# サーバ側(占有プロセス)
sudo lsof -i :PORT

# HTTPなら応答確認
curl -I http://example.com
curl -I https://example.com

# サービス/ログ
sudo systemctl status <service>
sudo journalctl -u <service> -n 200

まとめ

  • nc届く/届かない をまず確定
  • ss待受がある/ない を確定
  • curlアプリとして正しく返ってるか を確認
  • 迷ったら「timed out / refused / succeeded」の違いに戻る

検証環境

本記事のコマンドは Ubuntu 24.04 LTS / bash 5.2 で動作確認済みです。

次に読む