80
平文 HTTP のポート。いまどきは 443 へのリダイレクトを返すだけの存在ですが、閉じてしまうと証明書の更新が止まりますし、一般ユーザーのままでは bind した時点で失敗します。
自分の環境の行をそのまま実行してください。ポートを掴んでいるプロセス名と、バインドしているアドレスが出ます。たいていはそれだけで答えが分かります。
sudo lsof -nP -iTCP:80 -sTCP:LISTEN`-n` と `-P` でホストもポートも数値のまま、`-iTCP:80` でプロトコルとポートを選び、`-sTCP:LISTEN` で確立済みの接続を隠すので、持ち主だけが見えます。NAME の列がバインドアドレスで、`127.0.0.1:80` ならローカル専用、`*:80` なら全インターフェイス、つまりネットワークから届きます。COMMAND と PID がプロセス、USER はどのアカウントで動いているか。bind の後に権限を落としたサーバーは、ソケットを開いたのが root でもワーカーは `_www` や `nobody` で出てきます。何も出ず終了コード 1 なら、そのポートは空いています。
sudo ss -tlnp 'sport = :80'`-t` で TCP、`-l` で待ち受けソケット、`-n` でポートを数値のまま、`-p` で所有プロセスを出します。まず Local Address:Port の列を読んでください。`0.0.0.0:80` は全 IPv4 インターフェイス、`127.0.0.1:80` はループバックのみで、マシン上では応答するのに外からは届かない理由がこれです。`[::]:80` は IPv6 のワイルドカードで、たいていの Linux では IPv4 も受けます。nginx では同じポートに複数の行が並びますが、これは各ワーカーがソケットを継承しているだけで正常です。`sudo` なしだと自分の所有でないもののプロセス列は空になります。
sudo netstat -tlnp | grep ':80 '古いイメージや最小構成のコンテナ向けの net-tools 版です。フラグは同じで、PID/Program name の列は自分の所有でないソケットには特権が要り、man ページはこの値が信用できないと警告しています。パターン末尾の空白はちゃんと仕事をしています。ないと `:80` が `:8080`、`:8000`、`:80443` にも当たり、この出力の読み違いで最も多いのがまさにそれです。
netstat -ano | findstr :80`-a` で接続だけでなく待ち受けポートも、`-n` で数値のまま、`-o` で所有 PID が付き、`tasklist /FI "PID eq 1234"` で名前になります。Windows では答えが PID 4、つまり System プロセスであることが頻繁にあります。IIS や Web 配置エージェント、さらには Skype 時代の残骸のために、カーネルの HTTP.sys ドライバが 80 番を代理で握っているからです。PID 4 を kill するという選択肢はないので、`netsh http show servicestate` でどのアプリケーションが予約しているかを調べてください。いつもどおり `findstr` は部分一致なので、`:80` は `:8080` にも当たります。
`nmap -Pn -p 80 example.com` は三つの状態のどれかを返し、それぞれ次の一手が違います。`open` はハンドシェイクが成立したということなので、`curl -I http://example.com/` で中身を返すのかリダイレクトするのかを確かめてください。`closed` はホストがリセットを返した、つまり到達はできるが誰も待ち受けていない状態で、問題はネットワークではなくサーバープロセスの側にあります。`filtered` は何も返ってこなかったということで、ホストではなくセキュリティグループやクラウドのファイアウォール、上流の ACL を疑うべきです。推測ではなく実際に観測されたのがどれかは `--reason` で分かりますし、`-sV` を付ければ応答を読んでサーバーソフトウェアを報告します。スキャンは自分が責任を持つホストにだけ。
| 出ているもの | 意味 |
|---|---|
Error: listen EACCES: permission denied 0.0.0.0:80 | 衝突ではなく権限の検査です。80 番は 1024 未満なので、カーネルは特権のないプロセスに対して、ポートが空いているかを見る前に bind を拒否します。init システム経由でサービスを起動するか、Linux ならバイナリに `CAP_NET_BIND_SERVICE` を与えるか、8080 で待ち受けて前段にプロキシかリダイレクトを置いてください。Linux で `net.ipv4.ip_unprivileged_port_start` を下げる手もありますが、それが他に何を許すことになるか理解したうえで。 |
Error: listen EADDRINUSE: address already in use :::80 | こちらは本当に誰かがポートを持っています。何かを kill する前に、自分の環境のコマンドでバインドアドレスを読んでください。ワイルドカードで待ち受けているリスナーがいると同じポートのどの具体アドレスにも bind できませんが、別々の具体アドレスに 2 つ並ぶぶんには共存します。Windows では持ち主が通常のプロセスではなくカーネルの HTTP.sys ドライバであることがよくあります。 |
curl: (7) Failed to connect to example.com port 80 after 12 ms: Couldn't connect to server | ほぼ即座にリセットが返ってきたので、ホストには到達できていて 80 番では誰も待ち受けていません。Web サーバーが落ちているか、ループバックにバインドしているか、HTTPS のリスナーしか設定されていないロードバランサーを叩いているかのどれかです。手がかりは速さです。拒否は即座に返ります。 |
curl: (28) Failed to connect to example.com port 80 after 130004 ms: Connection timed out | 何も答えていないので、フィルタが黙ってパケットを捨てています。クラウドのセキュリティグループ、ホスト上のファイアウォール、そして経路上のネットワーク ACL を見てください。拒否がミリ秒なのに対して破棄は数十秒かかるので、他を調べる前に所要時間だけで二つの原因を切り分けられます。 |
Let's Encrypt: Timeout during connect (likely firewall problem) on an http-01 renewal | ACME のサーバーが公開インターネットから TCP の 80 番に到達できず、そして RFC 8555 はこのチャレンジで他のポートを使うことを許していません。チャレンジのパスのために 80 番を世界に開けるか、TXT レコードで検証するので受信ポートを一切必要としない DNS-01 チャレンジに切り替えてください。この形で失敗した更新は、証明書が切れるまで何も言いません。 |
The site works from the server itself but not from another machine | ほぼ確実にファイアウォールではなくバインドアドレスの問題です。コマンドの出力が `127.0.0.1:80` になっていれば、それはこのマシンにしか出しません。サーバーに `0.0.0.0` か具体的な外部アドレスを bind させてください。ファイアウォールのルールに触る前にこちらを確認してください。コマンド 1 回で済みますし、原因としてもこちらのほうが多いです。 |
IANA は 80 番を TCP・UDP・SCTP で `http` に割り当てていて、根拠は RFC 9110 ですが、実際に使われるのは TCP だけです。いまどきのサーバーでここに座っているのはアプリケーションであることのほうが珍しく、たいていは nginx や Caddy、Traefik といったリバースプロキシで、このポートでの仕事は HTTPS へのリダイレクトを返すことだけ——ただし、よく人を引っかける例外が一つあります。Let's Encrypt をはじめとする自動証明書の裏側にいる ACME には `http-01` チャレンジがあり、RFC 8555 はその検証リクエストが「HTTP サーバーの TCP ポート 80 に送られなければならない」と定めています。ポートは固定で、交渉の余地はありません。ファイアウォールで 80 番を丸ごと閉じると http-01 の更新が止まり、しかもたいてい何も言わずに止まって、60 日後に証明書が切れて初めて気づきます。もう一つ知っておくべきは、80 番が特権ポートだということです。Unix 系では 1024 未満は相応の権限を持つプロセスしか bind できず、カーネルはポートが空いているかを見る前にそれを検査します。macOS では一般ユーザーが 127.0.0.1:80 に bind しようとした時点で EACCES が返ります。Linux はこの境界を sysctl の `net.ipv4.ip_unprivileged_port_start` として公開しているので、決め打ちせず `sysctl net.ipv4.ip_unprivileged_port_start` で自分のマシンの値を読み、サーバー全体を root で走らせる代わりに、そのバイナリだけに `CAP_NET_BIND_SERVICE` を与えてください。開発サーバーの既定が 3000 や 5173、8080 なのも、同じコードが本番ではプロキシかリダイレクトを必要とするのも、すべてここが理由です。
80 番は、インターネットに出すのが普通で、しかも正しい数少ないポートの一つです。ただし何を出すかは意識的に決めてください。ここを流れるものは経路上の誰にでも読めて、書き換えもできるので、ログインフォームもセッション Cookie も API も管理画面も載せてはいけません。安全な形は、二つだけを返すリスナーです。HTTPS 版への 301 リダイレクトと、証明書クライアントが必要とする `/.well-known/acme-challenge/` のパス。HTTPS 側からは `Strict-Transport-Security` を返して、初回訪問以降ブラウザがそのホストに対して 80 番を使わなくなるようにし、Cookie には `Secure` を付けて、何かがすり抜けてもそこには乗らないようにしてください。「リダイレクトしかしていないから無害」という前提は捨ててください。敵対的なネットワークではリダイレクト先そのものが書き換えられます。HSTS はまさにそこを塞ぐために設計されています。最後にもう一つ。内部向けのサービスがループバックではなく `0.0.0.0:80` にうっかり待ち受けているのは、ステージング環境が公開状態になる最もありふれた経路です。プロセス名だけでなく、バインドアドレスを見てください。
どれもブラウザ内で完結します。アップロードは発生しません。
80 を調べているとき、ついでに確認することになりがちなポートです。
ほぼ権限の問題です。lsof や ss はソケット自体は出しますが、他ユーザーのプロセスは所有者の列を伏せるので、システムアカウントやコンテナランタイム、launchd が起動したサーバーは sudo を付け直すまで持ち主不明のリスナーに見えます。Windows は逆で、netstat には何も出ないのに bind だけ失敗します。これは Hyper-V や WSL2、Docker Desktop が起動時に予約したポート帯に当たっている状態です。
何なのかを先に見てください。取り残された開発サーバーなら問題ありませんが、書き込み中のデータベースは別ですし、他が依存しているシステムサービスも同様です。持ち主がコンテナならコンテナごと停止してください。ホストから見えるプロセスを kill してもランタイムが再起動するだけです。どうしても止められないものなら、自分のサービスを別のポートへ移すほうが早く片付きます。
0.0.0.0 ではなく 127.0.0.1 にバインドしているからです。各ページのコマンドがプロセス名と並べてバインド先アドレスを出しているのはこのためで、ループバックにバインドしたものはファイアウォールの設定に関係なく自分のマシンからしか届きません。最近は意図的にそれを既定にしているフレームワークも多いので、たいていはバグではなくフラグの問題です。すでに 0.0.0.0 なのに届かないなら、次に疑うのはホストのファイアウォールかクラウドのセキュリティグループです。
ほとんどなりません。インターネット全体を舐めるスキャナーはポート範囲を丸ごと走査し続けているので、稼げるのは数時間であって安全ではなく、代わりに関係者全員がその番号を覚える羽目になります。既定ポートを狙う無差別スキャンのログが減るという効果は確かにありますが、それだけです。結果を変えるのは認証と、送信元アドレスを絞ったファイアウォールと、そもそも外に出さないことです。
ポート 80 でまだ詰まっていますか。ポート一覧をすべて見る。あるいは上に戻って、実際に出たエラー文から追ってください。