今回は、Linuxでポートを使用しているアプリケーションを確認する方法を説明します。
「サーバーを用意したのにうまく通信できない!」
「使用したいポートがすでに何かに使われている!」
と困ったときに、原因調査に役立つ知識です。
具体的には、
・似たような文脈でソケットというのもあるけど、ポートとの違いは何?
・すでにポートが使われているみたいなんだけど、どのプログラムが使っているのか調べられる?
・外部に向けて必要なポートが解放されているか(不必要なポートが閉じられているか)確認できる?
といった疑問に答えます。
それでは、行ってみましょう。
ポート(port)とは
ポート(port)には、「港」という意味があります。
そこで、Linuxのポートを「港」に見立てると、Linux(サーバー)は「島」、インターネットは「海(ケーブルが船の航路)」になります。
また、Linux(サーバー)で動作するWebサーバーなどのサーバーアプリケーションは「島にある企業」というイメージでしょうか。
Linux(サーバー)には0番~65535番のポートが存在しますので、これはそのまま島に0番~65535番の港が存在すると考えます。
続けて、ポートに関する説明をいくつかピックアップして、港の概念で説明し直してみましょう。
ポートを開いたり閉じたり?
港のたとえで考えると、「ポートを開く」は「港の使用を許可して船(荷物)を受け入れる」という意味で、「ポートを閉じる」は「港を使用禁止にして船(荷物)を受け入れない」という意味です。
「Linuxのポートを閉じて、外部からの通信を遮断する」という言い方を聞いたことがあるでしょうか。
これは、「港を使用禁止にして、外部からの船(荷物)が入港できないようにする」というイメージです。
また、「セキュリティを考慮して80番と443番のポートだけを開く」という説明は、「セキュリティを考慮して80番の港と443番の港だけ使用を許可して船(荷物)を受け付け、他の港は(誰/何が乗っているかわからないため)使用禁止にして船(荷物)を受け入れない」と言いかえられます。
1つのプロセスが複数のポートを使用する?
複数のプロセスが1つのポートを共用する?
Linuxでは、1つのプロセスが2つ以上のポートを使用する場合があります。
※ここで突然「プロセス」という言葉がでてきましたが、ここでは、サーバーアプリケーションとほぼ同義と考えても差し支えありません。
逆に、複数のプロセスが1つのポートを共用することはありません。
港にたとえると、1つの企業が2つ以上の港を使用する場合がありますが、2つの企業が1つの港を共用することはありません、となります。
徐々にポートと港のイメージが重なってきたでしょうか。
ポートの特定方法は?
ポートは、Linux(サーバー)にある何番のポートか(=島にある何番の港か)という点にのみ注目した概念です。
そのため、単純に番号だけで特定されます。
それ以外の情報はありません。
ソケットとは
さて、次はポートと非常に似たような概念であるソケットの話をします。
この後に紹介するコマンドの中には、ソケットの情報を確認するコマンドがあります。
そこで、なぜソケットの情報を確認すると、ポートの情報がわかるのか、という点について理解する必要があります。
ソケットは港(ポート)の管理者と言える
先ほどの、ポートを港にたとえた話を続けると、ソケットは港の管理者のようなイメージと言えます。
島にある企業(=サーバーアプリケーション)が、80番の港に荷物が届くのを待つ場合、80番の港に管理者(=ソケット)を配置します。
たとえば船(荷物)が無事に届いた場合、港の管理者(=ソケット)は、企業の担当者(=また別のソケット)に送受信の管理を引き継ぎます。
逆に船(荷物)が一部欠けていた場合、港の管理者(=ソケット)は、他の島の港にいる管理者(=送信元のソケット)に、再送を依頼します。
このように、ポートが港なら、ソケットは管理者、と言えるくらいの違いがあります。
ソケットの特定方法は?
管理者(=ソケット)は、自分の島にも他の島にも存在するため、島の番号と港の番号(=IPアドレスとポート番号)+αの情報を組み合わせて特定されます。
ソケットを特定する情報の中にポート番号が含まれるため、ソケットの状況(IPアドレス+ポート番号+α)を確認すれば、ポートの状況が確認できるという考え方です。
内部からポートの状況を確認する
さて、たとえを交えながら長々と説明してしまいましたが、ここからは、Linuxのコマンドを中心に説明していきましょう。
まず初めは、内部からポートの状況を確認する方法を説明します。
内部からポートの状況を確認することは、島のたとえで言えば、島の役人が、島の企業が、それぞれどの港を使っているかを調べることにたとえられます。
プロセスが使用しているポートを確認する
特定のファイルやポートをオープンしているプロセスを確認するlsofコマンドで、プロセスが使用しているポートを調べる方法を紹介します。
入力するコマンドは以下のとおりです。
sudo lsof -i -P
そして、実行結果は以下のとおりです。
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME avahi-dae 698 avahi 12u IPv4 18833 0t0 UDP *:5353 avahi-dae 698 avahi 13u IPv6 18834 0t0 UDP *:5353 avahi-dae 698 avahi 14u IPv4 18835 0t0 UDP *:60008 avahi-dae 698 avahi 15u IPv6 18836 0t0 UDP *:38367 cupsd 707 root 10u IPv6 18906 0t0 TCP ip6-localhost:631 (LISTEN) cupsd 707 root 11u IPv4 18907 0t0 TCP localhost:631 (LISTEN) cups-brow 727 root 8u IPv4 18008 0t0 UDP *:631 dhclient 1231 root 6u IPv4 20845 0t0 UDP *:68 dnsmasq 1251 nobody 4u IPv4 20184 0t0 UDP yazaki-VirtualBox:53 dnsmasq 1251 nobody 5u IPv4 20185 0t0 TCP yazaki-VirtualBox:53 (LISTEN) dnsmasq 1251 nobody 11u IPv4 20208 0t0 UDP *:37000 ntpd 2292 ntp 16u IPv6 25003 0t0 UDP *:123 ntpd 2292 ntp 17u IPv4 25006 0t0 UDP *:123 ntpd 2292 ntp 18u IPv4 25010 0t0 UDP localhost:123 ntpd 2292 ntp 19u IPv4 25012 0t0 UDP 10.0.2.15:123 ntpd 2292 ntp 20u IPv6 25014 0t0 UDP ip6-localhost:123 ntpd 2292 ntp 21u IPv6 25016 0t0 UDP [fe80::df7f:1c50:ea1e:89b0]:123 apache2 4078 root 4u IPv6 28543 0t0 TCP *:80 (LISTEN) apache2 4081 www-data 4u IPv6 28543 0t0 TCP *:80 (LISTEN) apache2 4082 www-data 4u IPv6 28543 0t0 TCP *:80 (LISTEN)
この表示から、以下の内容が読み取れます。
- 「apache2」で始まる3行の表示から、
apache2コマンドの3つのプロセス(4078,4081,4082)が、
任意のIPアドレスの80番ポートからの通信を待っている(TCPの場合はLISTENと表示されます) - 「dhclient」で始まる行の表示から、
dhclientコマンドの1つのプロセスが、
任意のIPアドレスの68番ポートからの通信を待っている(UDPの場合はLISTENと表示されません)
同様に、53番ポート、123番ポート、631番ポート、5353番ポート、37000番ポート、38367番ポート、60008番ポートからの通信を待っているプロセスがあることがわかります。
接続待ちをしているソケットを確認する
接続待ちをしているソケットを確認するssコマンドで、ポートを利用しているアプリケーションを調べる方法を紹介します。
sudo ss -ltunp
実行結果は、以下のとおりです。
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port udp UNCONN 0 0 *:60008 *:* users:(("avahi-daemon",pid=698,fd=14)) udp UNCONN 0 0 *:631 *:* users:(("cups-browsed",pid=727,fd=8)) udp UNCONN 0 0 127.0.1.1:53 *:* users:(("dnsmasq",pid=1251,fd=4)) udp UNCONN 0 0 *:68 *:* users:(("dhclient",pid=1231,fd=6)) udp UNCONN 0 0 10.0.2.15:123 *:* users:(("ntpd",pid=2292,fd=19)) udp UNCONN 0 0 127.0.0.1:123 *:* users:(("ntpd",pid=2292,fd=18)) udp UNCONN 0 0 *:123 *:* users:(("ntpd",pid=2292,fd=17)) udp UNCONN 0 0 *%enp0s3:37000 *:* users:(("dnsmasq",pid=1251,fd=11)) udp UNCONN 0 0 *:5353 *:* users:(("avahi-daemon",pid=698,fd=12)) udp UNCONN 0 0 :::38367 :::* users:(("avahi-daemon",pid=698,fd=15)) udp UNCONN 0 0 fe80::df7f:1c50:ea1e:89b0%enp0s3:123 :::* users:(("ntpd",pid=2292,fd=21)) udp UNCONN 0 0 ::1:123 :::* users:(("ntpd",pid=2292,fd=20)) udp UNCONN 0 0 :::123 :::* users:(("ntpd",pid=2292,fd=16)) udp UNCONN 0 0 :::5353 :::* users:(("avahi-daemon",pid=698,fd=13)) tcp LISTEN 0 5 127.0.1.1:53 *:* users:(("dnsmasq",pid=1251,fd=5)) tcp LISTEN 0 5 127.0.0.1:631 *:* users:(("cupsd",pid=707,fd=11)) tcp LISTEN 0 128 :::80 :::* users:(("apache2",pid=4082,fd=4),("apache2",pid=4081,fd=4),("apache2",pid=4078,fd=4)) tcp LISTEN 0 5 ::1:631 :::* users:(("cupsd",pid=707,fd=10))
この表示から、以下の内容が読み取れます。
- 「apache2」が含まれる行の表示から、
apache2コマンドの3つのプロセスが、
任意のIPアドレスの80番ポートからの通信を待っている(TCPの場合はLISTENと表示されます) - 「dhclient」が含まれる行の表示から、
dhclientコマンドの1つのプロセスが、
任意のIPアドレスの68番ポートからの通信を待っている(UDPの場合はUNCONNと表示されます)
こちらも同様に、53番ポート、123番ポート、631番ポート、5353番ポート、37000番ポート、38367番ポート、60008番ポートからの通信を待っているプロセスがあることがわかります。
外部からポートの状況を確認する
次に、外部からポートの状況(主にopen、closed、filtered)を確認する方法を紹介します。
外部からポートの状況を確認することは、島のたとえで言えば、他の島の役人が、どの港が使用できるかを調べること(どの企業が使っているかはわからない)にたとえられます。
TCPのポートの状況を確認する
まずはTCPに限定したコマンドから紹介します。
nmap -p 0-65535 localhost
実行結果は以下のとおりです。
Starting Nmap 7.01 ( https://nmap.org ) at 2018-06-10 19:20 JST Nmap scan report for localhost (127.0.0.1) Host is up (0.000055s latency). Not shown: 65534 closed ports PORT STATE SERVICE 80/tcp open http 631/tcp open ipp Nmap done: 1 IP address (1 host up) scanned in 2.05 seconds
この表示から、以下の内容が読み取れます。
- 「PORT STATE SERVICE」の下の2行の表示から、
80番ポートと、631番ポートが外部からの通信を受け付けている状態(open)になっている - 「PORT STATE SERVICE」の上の1行の表示から、
80番と631番以外の65534個のポートは、すべて外部からの通信を受け付けているアプリケーションがない状態(closed)になっている
lsofコマンドやssコマンドで確認したdnsmasqコマンドが待っているはずの53番ポートは、外部からは閉じて見えるようですね。
UDPのポートの状況を確認する
次は、UDPに限定したコマンドを紹介します。
UDPの場合は、全ポートをスキャンすると大変な時間がかかるため、調査するポートも限定しています。
sudo nmap -sU localhost
実行結果は以下のとおりです。
Starting Nmap 7.01 ( https://nmap.org ) at 2018-06-10 19:25 JST Nmap scan report for localhost (127.0.0.1) Host is up (0.0000060s latency). Not shown: 996 closed ports PORT STATE SERVICE 68/udp open|filtered dhcpc 123/udp open ntp 631/udp open|filtered ipp 5353/udp open|filtered zeroconf Nmap done: 1 IP address (1 host up) scanned in 2.75 seconds
この表示から、以下の内容が読み取れます。
- 「PORT STATE SERVICE」の下の4行の表示から、
68番ポート、631番ポート、5353番ポートの3つが、
外部からの通信を受け付けている状態(open)または外部からの通信がフィルタリングされている状態(filtered)のどちらかになっており、判別できない - 「PORT STATE SERVICE」の上の1行の表示から、
よく使われているポートのうちの996個のポートは、
外部からの通信を受け付けているアプリケーションがない状態(closed)になっている
53番ポート、37000番ポート、38367番ポート、60008番ポートは、lsofコマンドやssコマンドで確認すると通信を受け付けているように見えますが、実行結果に含まれていませんので、次のコマンドで確認します。
sudo nmap -p 53,37000,38367,60008 -sU localhost
次のように表示されました。
Starting Nmap 7.01 ( https://nmap.org ) at 2018-06-10 19:33 JST Nmap scan report for localhost (127.0.0.1) Host is up (0.000053s latency). PORT STATE SERVICE 53/udp closed domain 37000/udp closed unknown 38367/udp closed unknown 60008/udp open|filtered unknown Nmap done: 1 IP address (1 host up) scanned in 1.39 seconds
なるほど、53番ポート、37000番ポート、38367番ポートは、外部からの通信を受け付けているアプリケーションがない状態(closed)ですね。
そして、60008番ポートは、外部からの通信を受け付けている状態(open)または外部からの通信がフィルタリングされている状態(filtered)のどちらかになっており、判別できないことがわかりました。
まとめ
今回は、ポートを「港」に、ソケットを「港の管理者」にたとえながら、それぞれの概要を説明しました。
また、ポートを使用しているプロセスを調べる方法と、外部からのポートの状況を調べる方法を紹介しました。
今回紹介したlsofコマンド、ssコマンド、nmapコマンドには、さまざまなオプションが用意されています。
オプションを適切に組み合わせることで、必要な情報をすばやく取得できるでしょう。
興味が湧いた方は、コマンドのオプションも調べてみると面白いですよ!
では、今回はこの辺で!