ポートとは?Linuxでlisten中のサービスを確認する方法
ポートの仕組みと、Linuxでssコマンドを使って現在listenしているサービスを特定する方法を解説します。TCPとUDPの違いや、Local Address列からローカルポートとパブリックポートを見分けるコツも学べます。セキュリティ対策として、意図しないプロセスがポートを開いていないか確認する際に役立つ知識です。
ポートの正体
ポートとは、1つのサーバーで複数のサービスを通信を混同することなく同時に実行するための番号です。VPSには1つのIP addressがありますが、Web server、SSH server、databaseを同時に実行することがあります。パケットが届いた際、OSはそれがどのサービス宛てかを知る必要があります。その答えがポート番号です。Webトラフィックはport 443へ、SSHはport 22へ送られます。IP addressはパケットをサーバーまで運び、ポートはサーバー内の適切なプログラムへと運びます。
ポートは16-bitの数値です。16 bitsでは0から65535までを表現できます。0は予約されているため、実際には1から65535までのポートが使用されます。1024未満のポートは「well-known」ポートと呼ばれ、開くにはroot権限が必要です。そのため、SSH用の22、HTTP用の80、HTTPS用の443、DNS用の53といった標準的なサービスがここに配置されています。1024より大きい番号は、通常のプログラムが自由に使用できます。
ポートにはTCPとUDPの2種類があり、一方のポート番号はもう一方の同じ番号とは別物として扱われます。TCPはSSH、HTTP、databaseなど、ほとんどのサービスで使用されるコネクションベースのプロトコルです。UDPはコネクションレスであり、DNSや一部のVPNなどで使用されます。ファイアウォールを設定する際は、通常どちらかを選択します。例えば 22/tcp です。
Listeningとはプログラムがポートで待機している状態を指す
接続を受け取りたいプログラムは、カーネルに対してポートでの「listen」を要求します。その瞬間から、そのポートはマシン上でオープンになり、ファイアウォールの設定に従って、届いた通信にプログラムが応答します。何もlistenしていないポートは、接続を拒否します。したがって、セキュリティチェックにおける最初の質問は「何が、どこでlistenしているか」となります。
その答えを得るためのコマンドは ss です。
sudo ss -tlnp各flagの意味は以下の通りです。TCP (t)、listenしているソケットのみ (l)、数値によるポート表示 (n、これにより 22 ではなく ssh が表示されます)、および所有プロセス (p) です。典型的な実行結果は以下の通りです。
State Recv-Q Local Address:Port Process
LISTEN 0 0.0.0.0:22 sshd
LISTEN 0 127.0.0.1:5432 postgres
LISTEN 0 [::]:80 nginxProcess 列は、各ポートをどのプログラムが所有しているかを示します。これにより、意図せず起動したままになっているプロセスを特定できます。
Local Address列が最も重要である
各ポートの前に表示されるアドレスを注意深く確認してください。これがサービスの到達範囲を決定するためです。頻繁に目にするケースは3つあります。
0.0.0.0:22 は、「このマシンが持つすべてのIPv4 address(パブリックIPを含む)でlistenする」ことを意味します。ファイアウォールが許可していれば、インターネットからIPv4経由でサービスにアクセス可能です。
[::]:80 は、IPv6における同様の意味です。「すべてのIPv6 address(パブリックIPを含む)でlistenする」ことを意味します。多くのプログラムはデフォルトでこれにバインドします。Linuxでは、:: ソケットがIPv4も受け付けることがよくあります。
127.0.0.1:5432 は、「loopbackのみでlistenする」ことを意味します。127.0.0.1 はマシンが自分自身と通信するために使用するアドレスであり、外部からルーティングすることはできません。ここにバインドされたサービスは、同じサーバー内からのみアクセス可能であり、ファイアウォールの設定に関わらず、インターネットからは決してアクセスできません。上記のPostgresの行は、この仕組みにより安全です。
ここから導き出される実用的なルールは以下の通りです。自身のアプリケーションのみが使用するdatabase、cache、またはadmin panelは、0.0.0.0 ではなく 127.0.0.1 にバインドすべきです。パブリックアドレスでlistenしていなければ、攻撃者が到達する手段はありません。
Listeningと到達可能性は別物である
混乱を避けるための重要な区別があります。マシン上でポートがopenしていること(プログラムがlistenしていること)と、そのポートが外部からreachableであること(ファイアウォールが許可していること)は異なります。リモートクライアントが接続するには、両方が成立している必要があります。
したがって、制御には2つのレイヤーがあります。各サービスのbind addressを設定することで、何がlistenするかを決定します。そして、ファイアウォールによって外部から何にアクセスできるかを決定します。適切に運用されているサーバーは、この両方を使用しています。サービスは必要な場所にのみバインドし、ファイアウォールは明示的に許可したもの以外をすべて拒否します。ss でlistenしているものを確認するのはステップ1です。ファイアウォールで何を許可するかを決定するのはステップ2であり、UFWによるファイアウォールの基本で解説します。
ここで注意すべき点があります。IPv4とIPv6は別物です。IPv4のみをカバーするファイアウォールを使用している場合、[::] サービスはIPv6経由でオープンなままになります。この罠については、以下の記事で説明しています:IPv6ファイアウォールの罠。
FAQ
Linuxサーバーでどのポートがopenしているか確認するには?
TCPの場合は sudo ss -tlnp、UDPの場合は sudo ss -ulnp を実行してください。これにより、すべてのlistenしているソケット、ポート、バインドされているlocal address、および所有プロセスがリストされます。Local Address 列を確認してください。0.0.0.0 または [::] はサービスがネットワークに公開されていることを意味し、127.0.0.1 はマシン自身のみでlistenしていることを意味します。
0.0.0.0と127.0.0.1の違いは何ですか?
0.0.0.0 は「パブリックIPを含むすべてのIPv4 addressでlistenする」ことを意味し、ネットワーク経由でサービスにアクセス可能です。127.0.0.1 はloopbackであり、マシンが自分自身と通信するために使用するアドレスです。これは外部からルーティングできないため、これにバインドされたサービスはローカルからのみアクセス可能です。内部サービスは、外部に公開されないよう 127.0.0.1 にバインドしてください。
サービスを動作させるためにファイアウォールでポートを開ける必要がありますか?
他のマシンからアクセスする必要があるサービスのみ、必要です。127.0.0.1 にバインドされたサービスは、外部からアクセスできないため、ファイアウォールのルールは不要です。0.0.0.0 または [::] のサービスは、トラフィックを許可するためにファイアウォールのルールが必要であり、ルールを追加するまではデフォルトで拒否されるべきです。
TCPポートとUDPポートの違いは何ですか?
TCPはコネクションベースであり、SSH、Web server、databaseなど、ほとんどのサービスで使用されます。UDPはコネクションレスであり、DNSや一部のVPNで使用されます。TCPとUDPの同じ番号は別のポートとして扱われるため、53/tcp と 53/udp は異なります。ファイアウォールのルールを作成する際は、22/tcp のようにプロトコルを指定します。