【Ubuntu】ポート疎通の確認:ss / lsof / nc / curl で原因切り分け(新人が迷わない型)
この記事で解決できること
- 「繋がらない」を ネットワーク / サーバ / アプリ のどこで止まっているか切り分けできます
- ありがちな "ufwのせいだと思い込む" "サービスの起動だけ見て満足する" を避けられます
- 最短で原因に当たりを付けるコマンドセット(ss / lsof / nc / curl)が身につきます
結論(最短ルート)
「繋がらない」は、次の順番で見ると一発で整理できます。
- DNSが正しいか(必要なら)
- クライアント→サーバの到達確認:
nc -vz HOST PORT - サーバ側で待受確認:
ss -lntp | grep :PORT - 誰が掴んでるか:
lsof -i :PORT - HTTPなら応答確認:
curl -I http(s)://HOST - サービスとログ:
systemctl status/journalctl -u
目次
前提(対象環境)
- OS:Ubuntu(サーバ側)
- 対象:サーバ触り始めた新人
- ここでは「調査・切り分け」に集中(最終修正は別記事へリンク)
1. まず「何が繋がらないのか」を言語化する
最低限この3点を先に確定します。
- HOST:example.com なのか、IPなのか
- PORT:22 / 80 / 443 / 3000 / 8080 / 3306 など
- プロトコル:SSH?HTTP?DB?
例:
- SSHが繋がらない →
HOST=example.comPORT=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:基本OK301/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 は最終手段です。まずは nc と ss で原因階層を決めてください。
やってはいけない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 で動作確認済みです。